(آموزش Assembly جلسه اول)
مقدمه:
پس از ۵ جلسه آشنایی با میکروها و راه اندازی بخش های مختلف آن ها توسط توابع پیش ساخته بسکام نوبت به آموزش زبان مادری میکرو یعنی اسمبلی می رسد. زبان اصلی میکرو همان زبان ماشین است که کار با آن برای افراد فوق حرفه ای که قصد نوشتن کامپایلرهای مختلفی مانند Bascom و یا کامپایلرهایی با زبان انحصاری خود (حتی فارسی) را دارند پیشنهاد می شود. زبان ماشین از کدهای ١۶ بیتی شبیه به کد زیر تشکیل شده است که معادل اسمبلی آن نیز در بالای آن آمده است:
ما از این جلسه کار با اسمبلی را شروع می کنیم. زبان اسمبلی دقیقاً همان کد زبان ماشین است با این تفاوت که به جای ٠ و ١ ها از نام های بامعنی مثل MOV استفاده می شود. وقتی که برنامه ای به زبان اسمبلی نوشته می شود برای تبدیل دوباره اسمهای رمزی به کد زبان ماشین از برنامه کوچکی به نام اسمبلر استفاده می شود. با توجه به اینکه میکروکنترلرهای AVR محصول کمپانی ATMEL می باشند اسمبلر رایگان avrasm نیز برای همین منظور توسط اتمل طراحی شده است. این اسمبلر در دو مدل تحت DOS و تحت ویندوز موجود است و احتمالاً تحت Linux و MAC نیز طراحی شده است.
هر دو اسمبلر بالا حجمی در حد چند صد کیلوبایت دارند و در کنار هر یک پوشه ای شامل فایل های Include تمام میکروهای AVR قرار دارد. فایل های INC فایل ای متنی هستند که برای بخش های مختلف میکرو مثل تایمر، پورتها، مبدل آنالوگ به دیجیتال و… نامهای رمزی در نظر می گیرند. البته نیازی به استفاده از این فایلهای INC نمی باشد ولی در غیر این صورت مجبورید مثلاً در میکروی ATmega32 به جای استفاده از نام PORTB از آدرس سخت افزاری آن که شماره 0x18 استفاده کنید و یا خط زیر را از فایل Inc کپی گرفته و در ابتدای فایل Asm خود Paste نمایید:.equ PORTB = 0x18
ما در تمام برنامه های این سری از آموزش ها از فایلهای Inc استفاده می کنیم و فایلهای لازم به همراه اسمبلر تحتDOS را پوشه مقاله جاری قرار داده ایم.
یکی دیگر از نرم افزار های رایگان که توسط ATMEL پشتیبانی می شود AVR Studio نام دارد. این برنامه به صورت پیشفرض به عنوان یک اسمبلر همراه با شبیه ساز تمام رجیسترها و اجرای برنامه به کار میرود و در صوتی که کامپایلر رایگان WinAVR نیز روی سیستم شما نصب شده باشد از هسته GCC این کامپایلر استفاده می کند و می توانید از آن به عنوان یک کامپایلر رایگان C نیز استفاده نمایید. (البته دوستانی که WinAVR را نصب می کنند معمولا با Editor خودِ WinAVR کار می کنند. ضمناً در خصوص WinAVR و GCC پس از اتمام جلسات اسمبلی بحث خواهیم کرد). ما در اینجا از اسمبلر تحت DOS استفاده می کنیم.
راه اندازی اسمبلر و نوشتن اولین برنامه اسمبلی:
پوشه AVR64.com-avr-assembler.zip را که در کنار این مقاله وجود دارد Unzip کرده و برنامه avrasm و پوشه Appnotes را به طور مستقیم در درایو C کامپیوتر کپی نمایید.
سپس از منوی Start روی Run کلیک کرده و عبارت CMD را تایپ نمایید و OK کنید تا پنجره خط فرمان در داخل ویندوز XP باز شود. در داخل این پنجره برای رفتن به Root عبارت cd\ را تایپ و Enter کنید و در صورتی که در درایو دیگری غیر از C بودید عبارت C: را تایپ و Enter نمایید. (توجه: منظور ما از درایو C همان درایوی است که فایل اسمبلر و پوشه اپلیکیشن نوتز ها را در داخل آن کپی کرده اید و این درایو می تواند هر درایوی باشد). در نهایت برای تست اسمبلر و نمایش ورژن آن عبارت avrasm را در داخل خط فرمان تایپ و Enter نمایید:
پنجره مذکور را به صورت Open نگه داشته و آن را Minimize کنید. سپس به درایو C باز گشته و یک فایل خالی Notepad ایجاد نمایید. (راست کلیک در فضای خالی درایو، انتخاب گزینه New و در نهایت انتخاب گزینه Text file) نام فایل جدید را به prog1.asm تغییر دهید. توجه داشته باشد که اگر قبل از تغییر نام پسوند فایل که به صورت txt است نشان داده نمی شود و نام فایل فقط به صورت New text file نماش داده می شود بایستی سیستم خود را طوری تنظیم کنید که پسوند ها را نمایش دهد. برای این منظور در ویندوز XP از داخل همان درایو C وارد منوی Tools و سپس Folder Options… شوید، از سربرگ View تیک گزینه Hide extensions for known file types را بردارید و OK کنید. در این صورت نام فایل ایجاد شده توسط Notepad به صورت New Text file.txt درمی آید. البته اگر با تغییر این گزینه و OK کردن باز هم پسوند فایل ظهر نشد و با مراجعه مجدد به این پنجره مشاهده کردید که تنظیمات دوباره به حالت اولیه بازگشته اند نشان از ویروسی بودن سیستم دارد. همچنین اگر Folder Options در منوی Tools وجود نداشت باز هم مشکل از ویروس می باشد. البته جای هیچ نگرانی نیست و باز هم قادر به دیدن پسوند فایلها خواهید بود. برای این منظور هر دوفایل showhiddenexts.vbs نمایش پسوند فایلها showhiddenextsundo.vbs عدم نمایش پسوند فایلها که در پوشه مقاله جاری با نام AVR64.com-showhiddenexts.zip موجود می باشد Unzip کرده و روی اولی کلیک نمایید و سیستم را Restart کنید. در این صورت تمامی پسوندها نمایش داده می شوند و برای عدم نمایش نیز روی دومی کلیک کنید. (این فایلها کارKelly هستند).
پس از موفقیت در ایجاد فایل Prog1.asm روی آن کلیک کرده و عبارات زیر را داخل آن تایپ نمایید:
برنامه بالا یک چشمکزن دولامپی ساده با میکروکنترلرATtiny13 می باشد که با Notepad++ باز شده است. البته Notepad++ قابلیت نمایش کدهای اسمبلی AVR به صورت رنگی را ندارد و تمامی حروف ذخیره شده و پسوند asm به صورت دستی در آن وارد شده اند. در مورد دستورات داخل این فایل بعداً به طور مفصل بحث خواهیم کرد ولی فعلاً نحوه اسمبل کردن و ایجاد فایل Hex و نیز نحوه پروگرم کردن میکروکنترلر را آموزش خواهیم داد.
پس از ذخیره فایل Prog1.asm در داخل Root (ریشه) درایو C، پنجره DOS مربوط به اسمبلر را که قبلاً به حالت Minimize برده بودید باز کنید و در آن عبارت زیر را تایپ و Enter نمایید:avrasm -fI Prog1.asm
توجه داشته باشید که بین avrasm و –fI یک فاصله و بین دو عبارت بعدی یعنی –fI و Prog1.asm نیز یک فاصله وجود دارد. عبارت –fI باید به صورت پشت سر هم نوشته شود. این Option به معنی فرمت فایل خروجی Intel Hex می باشد. پس از تایپ عبارت بالا و زدن کلید Enter جدولی نمایش داده می شود که اطلاعاتی در مورد آدرس های قرار گیری کد و دیتا و نیز حجم استفاده شده و باقیمانده از حافظه Flash (کد) و SRAM(دیتا) و نیز EEPROM(دیتای دائمی) را نشان می دهد. به علاوه خطاها و هشدارها نیز در انتهای صفحه نشان داده می شوند:
در صورتی که هیچ Error ی وجود نداشته باشد فایل Hex در کنار فایل Asm ایجاد می شود که می توانیم آن را در میکرو پروگرم نماییم.
برای پروگرم کردن فایل Hex راه های متفاوتی وجود دارد. یکی از این راه ها باز کردن Bascom، ایجاد یک فایل خالی، رفتن به پروگرمر با زدن کلید F4 و باز کردن فایل هگز از طریق منوی پنجره پروگرمر و پروگرم کردن آن می باشد. روش دیگر استفاده از پروگرمرهای رایگان USBو STK است. پروگرمرهای USB به سخت افزار خاصی احتیاج دارند که برد پروگرمر USB نامیده می شود و مدارهای آن به صورت رایگان در اینترنت وجود دارد، همچنین بردهای ساخته شده آن نیز توسط شرکت های داخلی به وفور در مغازه های لوازم الکترونیکی به نام “پروگرمر USB برای میکروکنترلر AVR” به چشم می خورد. در صورتی که از پروگرمرهای USB استفاده می کنید می توانید با توجه به دفترچه راهنمای آن پروگرمر فایل Hex را در میکرو بار کنید ولی در صورتی که تصمیم به ساخت یک پروگرمر ساده و ارزان قیمت با پورت موازی یا پرینتر دارید قسمت بعد را مطالعه کنید. در قسمت بعدی نحوه ساخت یک پروگرمر ساده با پورت LPT و نرم افزار رایگان AVR-ISP آموزش داده شده است. با استفاده از این نرم افزار به راحتی می توانید فایل های Hex را داخل میکرو پروگرم نموده و فیوزبیت های آن را تنظیم کنید، همچنین قفل کردن میکرو نیز از طریق فیوز بیت ها میسر است و در آخر اینکه ویژگی جالب این نرم افزار تعیین شماره سریال برای هر میکروکنترلر مجزا است تا بتوانید آی سی های محصولات تولیدی خود را از سایر آی سی ها تشخیص دهید و برای دستگاه های ساخت خود شماره سریال خاصی برای گارانتی و… در نظر بگیرید. این شماره سریال را با تنظیمات برنامه می توانید در Flash یا EEPROM و در آدرس مشخصی ذخیره کنید.
آموزش کار با AVR-ISP نرم افزار رایگان ارتباط با پروگرمر STK200/300
سخت افزار (نقشه STK200/300):
یکی از ساده ترین راه های انتقال فایل .HEX به میکرو استفاده از پورت موازی (LPT) یا همان پورت پرینتر می باشد. برای این منظور می توان از پروگرمر های استاندارد AVR با نام اختصاری STK200/300 استفاده کرد. این پروگرمرها از یک پورت نری DB25 تشکیل شده و مدار ساده ای مطابق شکل زیر دارند:
(٨ سیم بالای پورت به هم و به زمین وصل شده اند)
نرم افزار AVR-ISP
برای ارتباط با میکرو و انتقال فایل Hex می توانید از نرم افزار رایگان AVR-ISP استفاده کنید. این نرم افزار را می توانید از بخش دانلود سایت Avr64 دریافت نمایید. این نرم افزار محصولی از Kanda Systems بوده و به طور رایگان در سایت مربوطه نیز برای دانلود قرار داده شده است. در هنگام نصب این برنامه ممکن است سوالی با مضمون Disable XP Polling… پرسیده شود در ابتدا تیک آنرا نزنید و برنامه را نصب کنید. اگر به مشکلی برخوردید تیک آنرا بزنید و مجدداً نصب کنید. (در بعضی از ورژن های ویندوز پورت LPT به درستی کار نمی کند و این گزینه مشکل آنرا برطرف خواهد کرد).
پس از نصب برنامه میکرو را داخل پروگرمر قرار داده کابل آنرا وصل کنید و در نهایت تغذیه را متصل کنید و روی Icon برنامه کلیک نمایید. از پنجره باز شده از گزینه Device نام چیپ مورد نظر را انتخاب کنید و از منوی Device (در بالا کنار File) روی Erase کلیک نمایید. اگر چراغ پایین سمت چپ سبز شد آی سی شما شناسایی شده است در غیر این صورت روی دکمه Setup در صفحه اصلی کلیک کرده و سرعت پروگرمر را روی Fast و یا Slow و … تنظیم کرده و مجدداً امتحان کنید.
پروگرم کردن و تنظیم فیوزبیت ها و قفل میکرو
برای پروگرم کردن میکرو از منوی فایل روی Load کلیک کرده و فایل Hex ایجاد شده را باز کنید. سپس از منوی Device روی Erase کلیک کنید تا حافظه میکرو پاک شود. سپس از منوی Device روی Program و سپس روی Flash کلیک کنید و منتظر بمانید تا فایل Hex به آی سی انتقال داده شود. پس از اتمام انتقال از منوی Device روی Verify و سپس روی Flash کلیک کنید تا فایل ریخته شده روی میکرو با فایل موجود در کامپیوتر مقایسه شده و صحت انتقال آن تایید شود. در صورتی که تمام این عملیات با موفقیت انجام شود چراغ پایین سمت چپ برنامه سبز می شود.
برای تنظیم فیوزبیت های میکرو در ابتدا از منوی Device روی Read و سپس روی Fuses کلیک کنید. پنجره فیوزبیت ها به طور خودکار باز می شود. این پنجره برای هر میکرو متفاوت است. فیوز های میکروی ATtiny2313 را در شکل زیر مشاهده می کنید:
گروه اول این فیوز بیت ها که با نام General Options شناخته می شوند مربوط به تنظیمات بخش های داخلی میکرو از قبیل فعال و غیر فعال کردن پایه Reset، پروتکل SPI، پروتکل JTAG، Watchdog و.. است که برای هر میکرو متفاوت است و از روی متن انگلیسی آن می توان به کاربرد آن پی برد.
گروه دوم فوق العاده مهم بوده و فرکانس کاری CPUی میکرو را مشخص می کنند. هر میکرو می تواند چندین منبع کلاک داشته باشد. ارزان ترین و ساده ترین روش استفاده از اسیلاتور مقاومت و خازن داخلی است که رنج های محدودی را شامل می شود و با Calibrated Internal RC Oscillator نام گزاری می گردد. پیش فرض اکثر میکروها روی RC 1MHz است؛ بنابراین نیازی به نصب کریستال خارجی بین پایه های Xtal1 و Xtal2 میکرو نیست. انتخاب بعدی External Crystal/Ceramic.. است که با انتخاب هر یک از این گزینه ها که یک محدوده فرکانس را شامل می شود بایستی یک کریستال در همان محدوده بین پایه های Xtal1 و Xtal2 میکرو متصل کنید. البته در این صورت هر کدام از پایه های کریستال را نیز توسط یک خازن عدسی ٢٢ پیکوفاراد به زمین وصل کنید تا میکرو راه اندازی شود (در میکروی AT90S8515 اگر این خازن ها را قرار ندهید میکرو روشن نمی شود ولی در سری Mega بدون خازن هم کار می کند ولی فرکانس دقیق نمی دهد). انتخاب بعدی هم مربوط به کلاک خارجی بوده و با External Clock نمایش داده می شود. در صورت استفاده از این منبع بایستی با یک آی سی کلاک خارجی فرکانس خود را به پایه Xtal1 میکرو بدهید. RC خارجی هم در برخی از میکروها وجود دارد که برای استفاده از آن باید یک شبکه مقاومت و خازن بین پایه های میکرو ایجاد کنید و گاهی میتوان خازن داخلی موجود در آی سی را فعال کرد و فقط با یک مقاومت خارجی به فرکانس مذبور دست یافت. توجه داشته باشید که با هر انتخابی غیر از RC داخلی میکروی شما از کار می افتد مگر اینکه در پروگرمر بین پایه های Xtal1,2 آن یک کریستال قرار دهید (برای کریستال خارجی) یا یک کلاک جدا به پایه Xtal1 وصل کنید (برای کلاک خارجی و RC خارجی و کریستال خارجی).
فیوزبیت سمت راست به نام Brown-out در حالت حای غیر فعال است. این فیوز بیت در صورتی که روی مقدار ولتاژ های خاص قرار بگیرد (مقادیر مختلف برای هر میکرو) با رسیدن ولتاژ میکرو به اندازه ذکر شده میکرو را ریست می کند. شبیه پیغام Low Battery موبایل.
فیوز بیت های SUT مخفف Start up time بوده و تاخیر زمانی روشن شده CPU پس از وصل تغذیه میکرو را مشخص میکنند. این زمان از ٠ تا چند میلی ثانیه متغیر است.
سربرگ دوم این پنجره (انتخاب از سمت راست) مربوط به گزینه های حافظه بوت و قفل کردن حافظه میکرو می باشد. در صورتی که Lock bits را روی Mode3 قرار دهید حافظه فلش و EEPROM میکرو قفل شده و با کپی کردن آن اطلاعات به صورت غلط کپی می شوند. برای بازگرداندن این قفل بایستی یک فایل جدید روی میکرو فلش کنید تا قفل باز شود. البته محتویات فایل قبلی از بین می رود ولی میکرو قابل استفاده خواهد شد. برای اعمال تغییرات فیوزبیت ها و بیت های قفل از گزینه Device روی Program و سپس روی Security Lookbits و Fuses کلیک کنید.
نکته: هرگز فیوزبیت ها روی روی گزینه های Reserved قرار ندهید. این کار باعث خراب شدن میکرو شده و بازگرداندن آن با ابزارهای معرفی شده غیر ممکن است.
برای خواندن حافظه های Flash و EEPROM نیز می توانید از منوی Device روی Read و سپس روی Flash یا EEPROM کلیک کنید. سپس از منوی File روی Save کلیک کرده و فایل مورد نظر را ذخیره نمایید.
آخرین گزینه منوی Device تمام کار را را خودکار می کند. روی این گزینه کلیک کرده و کارهایی را که مایلید پشت سر هم انجام دهید تیک بزنید؛ مثل: Load مجدد فایل، پاک کردن فلش، پروگرم کردن فلش، Verify کردن فلش. با این کار با هر بار فشار کلید F5 تمام این کارها به طور خودکار انجام خواهند شد. البته هر بار که این برنامه را باز می کنید برای مرحله اول فایل هگز را یک بار دستی Load کنید تا آدرس آن در حافظه برنامه باقی بماند و فایل پروژه قبل را Load نکند.
برای تعیین شماره سریال آی سی نیز از گزینه Serial Numbers استفاده کنید. در صورتی که سریال را در Flash ذخیره می کنید آدرس شماره سریال را بایستی در نقطه ای خارج از محدوده کاری برنامه قرار دهید و در صورتی که از آدرس های برنامه اطلاعی ندارید به این گزینه دست نزنید چون در این صورت فایل هگز داخلی آی سی خراب می شود. برای ذخیره شماره سریال در حافظه EEPROM نیز در صورتی که برنامه شما از این حافظه استفاده نمی کند می توانید شماره سریال را در این حافظه ذخیره کنید و آدرس ٠ مکان مناسبی است. (آدرس ٠ فلش مکان مناسبی نیست، بعداً در خصوص بردارهای وقفه و اینکه آدرس های آنها در ابتدای فلش قرار داده شده است بحث خواهیم کرد، هرگز برای شماره سریال از فلش استفاده نکنید).
آزمایش مدار:
برای تست این پروژه، سخت افزاری مطابق با شماتیک زیر بر روی بِرِد بُرد ببندید. با قرار دادن آی سی پروگرم شده در مکان مناسب و اتصال تغذیه ۵ ولت شاهد چشمکزدن دیود های نورانی خواهید بود. (البته این مدار ساده ترین مدار ممکن با اسمبلی است و در آینده به راه اندازی LCD و کی پد و … خواهیم پرداخت).
با نگاهی به کد Hex تولید شده توسط اسمبلر مشاهده می کنیم که هیچ کد اضافی تولید نشده و تمام برنامه در ۵ خط جمع آوری شده است. برنامه های اسمبلی همیشه سرعت اجرای بالایی دارند و خطا در آنها صفر است. البته راه اندازی سایر دستگاه ها از قبیل LCD نیاز به داشتن اطلاعات کافی در مورد نحوه سیگنالینگ و طرز کار آنهاست. در بخش بعد به تحلیل برنامه چشمکزن دولامپی می پردازیم.
تحلیل برنامه نوشته شده با اسمبلی:
هم اکنون نوبت به آموزش زبان اسمبلی رسیده است. تا اینجا با نحوه نوشتن یک کد اسمبلی، ذخیره و اسمبل کردن و نیز پروگرم کردن آن در میکرو آشنا شدیم. در این قسمت در مورد دستورات زبان اسمبلی و بخش های داخلی میکرو صحبت می کنیم. همانطوریکه می دانیم یک میکروکنترلر از بخش هایی مانند CPU، حافظه Flash (محل ذخیره سازی ثابت ها و Hex)، SRAM (محل ذخیره سازی موقت متغیرها)، EEPROM (محل ذخیره سازی دائمی متغیرها)، مبدل آنالوگ به دیجیتال (در برخی میکروها)، واحد تشخیص وقفه ها (Interrupts)، تایمرها و… تشکیل شده است. از طرفی تنها راه ارتباط میکرو با دنیای خارج پورت ها هستند. در میکروی نمونه ATtiny13 فقط یک پورت B وجود دارد که به جای ٨ پین فقط ۶ پین دارد و دلیل آن هم محدودیت پایه های این نوع آی سی است. (DIP8). هر یک از بخش های داخلی میکرو آدرس خاصی دارند و همگی روی یک DATABUS هشت بیتی قرار گرفته اند. به طور مثال در این برنامه ساده فقط پورت B مورد استفاده قرار می گیرد و بیت های این پورت ٠ و ١ می شوند. در این برنامه از فضای SRAM و سایر بخش های میکرو هیچ استفاده ای به عمل نیامده و فقط از رجیستر های همه منظوره CPU برای ایجاد حلقه ها و تولید تاخیر (Delay) بهره گرفته شده است.
در محیط اسمبلی خطوطی که با علامت سمی کالن شروع می شوند به عنوان توضیح به حساب آمده و در عملکرد اسمبلر نقشی ندارند. در این برنامه ٢ خط اول توضیح هستند. خط شماره ٣ که با .include شروع شده است برای ضمیمه کردن فایل inc میکروکنترلر مربوطه به کار می رود (تقریباً شبیه به regfile=ATtiny13.dat در Bascom).
دو خط بعدی مربوط به تعیین محل قرار گیری کدهای Hex در حافظه فلش میکرو هستند. اصولاً دستوراتی که با نقطه شروع می شوند به رهنمودها یا راهنماهای پیش پردازنده معروفند و برای راهنمایی اسمبلر به کار می روند (رهنمودهای پیش پردازنده در اسمبلی با نقطه، در C با # و در بیسیک (بسکام) با $ شروع می شوند). رهنمود .CSEG مخفف Code Segment است و خط بعد از آن آدرس شروع سگمنت کد برنامه را مشخص می کند. ما در اینجا آدرس ٠ ر انتخاب کرده ایم. البته همیشه بعد از .CSEG بلافاصله .ORG 0x00 نوشته می شود که به معنای خانه شماره ٠ حافظه کدی میکرو است و در آن فقط دستور call main یا rcall main یا rjmp main نوشته شده و بلافاصه پس از آن دستورات پرش به روتین های وقفه آورده می شود (در جلسات بعدی با این مفاهیم در داخل کدهای موبوط به وقفه ها بیشتر آشنا خواهیم شد) در این برنامه چون این موارد رعایت نشده اگر وقفه ای روی دهد خط موجود درآدرس بردار وقفه اجرا می شود و ترتیب اجرای برنامه به هم می ریزد.
به غیر از .CSEG دو رهنمود دیگر نیز به نام های .DSEG برای حافظه دیتا یا همان SRAM و .ESEG برای حافظه EEPROM وجود دارند. آدرس .DSEG معمولاً از 0x60 شروع می شود و در مقادیر بالای این آدرس برای آدرس دهی SFR ها، پورتها و سایر امکانات داخلی میکرو به کار می روند و دلیل همپوشانی این آدرس ها استفاده از باس مشترک برای رم و سایر بخش های داخلی میکرو است. .ESEG از آدرس ٠ شروع می شود و این نشان دهنده جدا بودن باس آن از سایر بخش هاست. البته تمام این موارد ممکن است برای میکروهای مختلف متفاوت باشد و در دیتا شیت میکروی مورد نظر آورده شده است.
پس از ORG مربوط به CSEG نوبت به نوشتن اولین خطوط از کدهای اسمبلی فرا می رسد. معمولاً اولین کاری در یک میکرو بعد از Startup انجام می شود تعیین آدرس پشته یا همان Stack است. همانطوریکه در جلسات قبلی (بسکام) نیز ذکر شده بود با فراخوانی هر زیر برنامه که با دستور Call، rcall یا… صورت می گیرد آدرس جاری PC که مخفف پروگرم کانتر یا همان شمارنده برنامه است در مکان جاری پشته ذخیره می شود و پس از اجرا و اتمام زیر برنامه به رسیدن به ret یا reti (در زیر برنامه های مربوط به اینتراپت یا وقفه) آدرس مورد نظر از پشته بازخوانی شود و ادامه برنامه از PC+1 یعنی دستور بعد از Call از سر گرفته می شود. (محاسبات PC+1 ممکن است قبل از جایگذاری آدرس در پشته صورت بگیرد و یا بعد از بازخوانی آن و اهمیتی ندارد). به همین دلیل تنظیم سایز پشته اهمیت فراوانی دارد و در صورت عدم تنظیم آن هیچ یک از فراخوانی های برنامه کار نخواهند کرد. همیچنین نکته قابل توجه استفاده درست از فضای رم میکرو است. در صورتی که از حافظه SRAM تا نزدیک آخر استفاده شود و نیز به دلیل فراخوانی های تو در توی توایع و زیر برنامه ها فضای پشته ها به اندازه کافی به سمت بالا رشد کند مشکلی به نام Stack overflow ایجاد می شود که در هسته AVR می توان آن را Overlap یا همپوشانی نامید، چرا که چیزی به نام سرریزی پشته وجود ندارد ولی اطلاعات پشته با رم دچار اختلاط شده و باعث از بین رفتن اطلاعت داخل رم می شود. این مشکل ممکن است باعث ایجاد حلقه های نامحدود شود و کل برنامه مانند کامپیوتری که به حالت Freeze رفته هنگ کند که این مشکل با Watch dog قابل حل است ولی در صورتی که فقط باعث خراب کردن دیتا شود و فقط مقدار آن را تغییر دهد مشکل جدی تر خواهد بود چرا که در ظاهر، میکرو به درستی کار می کند ولی اطلاعات غلط می دهد. به همین دلیل بهترین راه استفاده کمتر از فضای رم و تخمین حداکثر فضای لازم برای فراخوانی های تو در تو می باشد.
برای تعیین سایز پشته بایستی آدرس انتهای SRAM در رجیسترهای SPL و SPH قرار بگیرند. این دو رجیستر ٨ بیتی که مخفف Stack Pointer می باشند برای تعیین محل شروع پشته به کار می روند. نظر به اینکه پشته به صورت معکوس رشد می کند بهترین مکان برای شروع پشته برای حداکثر استفاده از فضای رم انتهای آن است. در داخل فایل Inc میکرو متغیری به نام RAMEND تعریف شده است که مقدار آن برابر با آدرس پایان رم میکرو است. با توجه به اینکه در میکروهای با حافظه رم بالاتر از ٢۵۶ بایت این متغیر دو بایتی می باشد با استفاده از دستور Low() مقدار LSB یا بیت های کم ارزش تر آن را جدا کرده و توسط دستور LDI که به معنای Load Immediate می باشد مقدار آن را در رجیستر R20 میکرو به طور موقت کپی می کنیم. توجه داشته باشید که AVR ها ٣٢ رجیستر همه منظوره با شماره های ٠ تا ٣١ دارند که معمولاً از رجیستر های ١۶ به بالا برای مصارف عمومی استفاده می شود و تمام این رجیستر ها ٨ بیتی اند. البته ۶ رجیستر آخر دو به دو تشکیل رجیستر های ١۶ بیتی X و Y و Z را می دهند که در جای خود بحث می شود. در خط بعدی با دستور Out که برای ارسال مقدار به یک آدرس خاص مثل پورت یا یکی از SFR های داخلی میکرو استفاده می شود، مقدار داخل رجیستر R20 را در رجیستر SPL کپی می کنیم. نظر به اینکه میکروی Tiny13 فقط 64 بایت SRAM دارد کاری با رجیستر SPH نداریم ولی در غیر این صورت می بایست با دستور High(RAMEND) مقدار بالای آدرس انتهایی رم را نیز در رجیستر SPH کپی می کردیم.
در میکروی ATmega32 بایستی اینگونه عمل کنیم: (دستور byte1 معادل low و دستور byte2 معادل high است).
1 2 3 4 5 |
.include “Appnotes\m32def.inc” ldi r20, byte1(RAMEND) out SPL, r20 ldi r20, byte2(RAMEND) out SPH, r20 |
با مراجعه به دیتا شیت میکرو در صورتی که مشاهده کردید فضای SRAM از ٢۵۶ بایت بیشتر است از روش دوم استفاده کنید در غیر این صورت فقط متغیر SPL را مقدار دهی نمایید. (ضمناً استفاده از رجیستر R20 اجباری نیست و از هر کدام از رجیسترهای R16 تا R31 می توانید بهره ببرید).
در خطوط ١١ و ١٢ با مقدار دهی رجیستر DDR که مخفف Data Direction Register به معنای رجیستر تعیین جهت داده است، ورودی یا خروجی بودن پورت مورد نظر را تعیین می نماییم. در این پروژه میکروی ما فقط یک پورت B داشته و فقط DDRB موجود است. نظر به اینکه یک پورت استاندارد دارای ٨ پایه می باشد رجیستر DDR نیز از ٠ تا ٧ به صورت DDRB,0 قابل آدرس دهی است. هر چند به طور کلی نیز می توان DDRB را با یک عدد ٨ بیتی آدرس دهی کرد. برای تعیین پایه مورد نظر به صورت خروجی بایستی DDR مربوطه را با ١ مقدار دهی کرده و برای تنظیم به صورت ورودی با ٠ مقدار دهی نماییم. دستور sbi برای ست کردن یک بیت و cbi برای ریست کردن آن به کار می رود. در دو خط زیر با یک کردن دو بیت ٠ و ١ رجیستر پورت B این دو پایه را به صورت خروجی تعریف می نماییم.
قسمت بعدی بدنه اصلی برنامه چشمکزن دولامپی است. این برنامه از یک لیبل با علامت دو نقطه پس از آن شروع شده و با rjmp خاتمه می یابد. در واقع دو دستور یاد شده تشکیل یک حلقه نامحدود مانند Do:Loop بیسیک یا While(1){}; زبان C را می دهند. در داخل این حلقه با دستورات sbi و cbi رجیسترهای portb را روشن خاموش کرده ایم. سپس با فراخوانی زیر برنامه delay کمی تاخیر ایجاد کرده و مجدداً دیود های LED را به صورت عکس روشن و خاموش نموده ایم.
توجه داشته باشید که دستورات rcall و rjmp به صورت استاندارد call و jmp نیز وجود دارند و قادر به پرش به نقاط دور تری می باشند ولی به دلیل اینکه حافظه زیادی از میکرو می گیرند بهتر است در میکروهای کم حافظه از معادل آنها استفاده کنید. ضمناً برخی از دستورات استاندارد در میکروهای کوچک تعریف نشده اند.
قسمت آخر برنامه مربوط به زیربرنامه delay یا تاخیر است. در این زیر برنامه با پر و خالی کردن رجیستر های ١۶ تا ١٨ وقت CPU گرفته می شود و اندکی تاخیر در چشمکزدن LED ها ایجاد می شود. در این برنامه با دستور dec یک واحد از رجیستر کم می شود و با دستور brne بررسی می کنیم که اگر مقدار رجیستری که در سیکل قبلی روی آن عملیات صورت گرفت 0 نشده بود به دستور جلوی brne پرش کند در غیر این صورت به خط بعد برود. (چیزی شبیه به دستور شرطی IF). در این برنامه حلقه داخلی Loop3 به تداد 255 سیکل ماشین وقت CPU را هدر می دهد و حلقه Loop2 به تعداد 255×255 بار و حلقه اصلی Loop1 به میزان 10x255x255 بار. با تغییر عدد ١٠ می توان زمان این تاخیر را تغییر داد. اصولا در کامپایلرهایی مانند بسکام، کدویژن یا WinAVR از تابعی به نام Waitms x یا wait_ms(x) استفاده می شود که در درون آن چنین کدی نهفته است و مقدار متغیر ورودی با محاسباتی داخل رجیستر r16 ذخیره می شود (r16 در این برنامه). دستور ret نیز به معنای بازگشت می باشد و میکرو با رسیدن به آن، آدرس جایی را که از آنجا پرش کرده بود از Stack فرا می خواند و به PC تحویل می دهد.
در این برنامه از کد سگمنت فقط برای ذخیره فایل اجرایی یعنی Hex میکرو استفاده شد و از دیتا سگمنت و ESEG نیز استفاده ای به عمل نیامد. ازکد سگمنت می توان برای تعریف جدول دیتا و یا ثابت ها استفاده کرد و از دیتا سگمنت نیز برای تعریف متغیرها استفاده می شود. متغیرهایی که در بسکام با دستور Dim و در C با ساختار دستوری int x; تعریف می شوند در فضای دیتا سگمنت قرار می گیرند. با تعریف متغیرها می توان اطلاعات را به جای رجیستر های محدود در داخل آنها کپی کرد و برنامه را وسعت داد. البته رجیستر ها کاربرد خود را دارند و به دلیل سرعت دسترسی بالا و اینکه به طور مستقیم در یک خط قابل دسترسی هستند قابل مقایسه با فضای رم نمی باشند. فضای ایپرام نیز برای ذخیره متغیرهای دائمی به کار می رود که در اسمبلی کار با آن ساده است. برای راه اندازی سایر بخش های داخل میکرو از قبیل تایمرها و … دستورات خاصی وجود دارد و همانند پورت ها که قبل از استفاده احتیاج به مقدار دهی رجیستر خاص DDR دارند، ادوات دیگر نیز بایستی قبل از استفاده توسط رجیستر تنظیمات خود پیکره بندی شوند و سپس مورد استفاده قرار گیرند. در جلسه بعدی از میکروی بزرگتر Mega16/32 برای راه اندازی LCD و کی پد بهره می گیریم و پس از آشنایی با روش تعریف متغیرها نحوه کار با تایمر را شرح می دهیم. بیس اصلی اسمبلی در این جلسه نهفته است و در صورتی که تسلط کافی در تعریف پورت ها، تشخیص سگمنت ها، اسمبل کردن و اشکال زدایی برنامه این جلسه پیدا کنید مطالعه جلسات بعدی برای شما به مراتب آسان تر و لذت بخش تر خواهد بود. ضمناً از جلسه بعد کنسول LCDو کی پد و میکروی Mega16/32 را تا چند جلسه ثابت نگه می داریم تا بتوانیم توسط این ورودی و خروجی های استاندارد با سایر بخش های داخلی میکرو از قبلی تایمرها، وقفه ها، مبدل آنالوگ به دیجیتال و … ارتباط برقرار کنیم. شایان ذکر است تمام میکرو ها همه بلوک های موجود را در داخل خود ندارند ولی با زبان اسمبلی (و حتی بیسیک و C) می توان بلوک هایی را که فقط با ٠ و ١ ها سر و کار دارند (نه بلوک های آنالوگ) مانند ارتباط سریال، ارتباط با MMC، ارتباط با TCP/IP بدون نیاز به چیپ جدا، ارتباط با انواع سنسورها از قبیل DS1820، SMT160، فرستنده و گیرنده مادون قرمز و… را به صورت نرم افزاری پیاده کرد. از اسمبلی برای نوشتن هدر فایل های C و Lib های بسکام نیز استفاده می شود و با مطالعه آن و تسلط کافی و تحقیق در مورد فرمت های وسایل ارتباطی مختلف (مثل ماوس) می توانید هدر ها و کتابخانه های شخصی و تجاری برای کامپایلرهای مختلف بنویسید.
دانلود PDF این مقاله + برنامه اسمبلر AVR و فایلهای مربوطه
بازدیدها: 1191