دوشنبه , ۳ تیر ۱۳۹۸
آخرین مطالب
LINK TABLES
خانه | میکروکنترلر | دوره آموزشی AVR | برنامه نویسی اسمبلی برای AVR (جلسه ۹)

برنامه نویسی اسمبلی برای AVR (جلسه ۹)

در این جلسه مفاهیم و ملزومات لازم برای برنامه نویسی اسمبلی AVR در Atmel Studio مطرح می‌شود

برخی از شبه دستورات(دستورالعمل های اسمبلر)

 تفاوت دستورات با دستورالعمل ها در این است که دستورات وظایف را برای cpu تعریف می کنند، در حالی که دستورالعمل ها یا شبه دستورات راهنما و هدایتگر اسمبلر هستند.

شبه دستورات دراسمبلر AVR با علامت نقطه آغاز می شوند. خلاصه ای از کاربرد برخی از دستورالعمل های AVR  در زیر آمده است.

EQU.

این دستوررالعمل برای نسبت دادن یک مقدار ثابت یا یک آدرس معین به یک برچسب به کار می رود.اگر در هر کجای برنامه از این برچسب استفاده شود اسمبلر مقدار ثابت را جایگزین آن می کند.

فرمت این دستورالعمل به این شکل است:

مثال:

مزیت استفاده از این شبه دستور در این است که اگر از یک مقدار ثابت به کرات در برنامه استفاده شده باشد بوسیله آن می توان تنها با تغییر یک بار در مقدار ثابت در اول برنامه مقدار آن را عوض کرد.مثلا می توانیم بجای آدرس ثبات های I/O از نام آن ها استفاده کنیم.

SET.

 این دستورالعمل هم همانند دستورالعمل قبلی برای تعریف یک مقدار ثابت یا یک مقدار معین به کار می رود، تنها تفاوت آن با دستورالعمل قبلی در این است که مقدار های نسبت داده شده با استفاده از این دستورالعمل را می توان بعدها دوباره مقداردهی کرد.

ORG.

 این دستورالعمل برای نمایش شروع آدرس به کار می رود.از این دستوالعمل می توان هم برای کد و هم برای داده استفاده کرد منظور از داده داده های ثابتی هستند که میخواهیم در ROM ذخیره کنیم.

INCLUDE.

 با استفاده از این دستورالعمل می توان محتویات یک فایل را به برنامه اضافه کرد.این فایل ها می توانند حاوی ثابت های نمادی که با استفاده از دستورالعمل EQU تعریف شده اند و یا حتی برنامه های از پیش نوشته شده که لازم است به برنامه اضافه شوند باشند. برای استفاده از این دستورالعمل نام فایل مورد نظر به همراه پسوند باید مابین دوعلامت” ” قرار بگیرد.

DB.

همانطور که در جلسه هشتم گفته شد از این دستورالعمل برای تخصیص  داده های ثابت به خانه های ROM استفاده می شود.در اینجا باید اضافه کنم که فضای EEPROM را هم می توانیم به وسیله این دستورالعمل مقدار دهی اولیه کنیم.

ESEG.

 از این  دستورالعمل به همراه دستورالعمل بالایی برای تخصیص داده در EEPROM استفاده می شود.

مثال:

همانطور که در مثال بالا می بینید برای اینکه داده هایی که بوسیله دستورالعمل DB تعریف شده اند در فضای حافظه EEPROM قرار بگیرند باید قبل از دستورالعمل DB از دستوالعمل ESEG استفاده کرد.اگر بخواهیم این داده ها در فضای حافظه ROM قرار بگیرند باید به جای دستورالعمل ESEG از دستورالعمل CSEG استفاده کرد.البته اگر قبل از دستورالعمل DB. چیزی ننویسیم اسمبلر به صورت پیش فرض داده ها را به فضای ROM تخصیص میدهد.

تعریف ماکرو و روش استفاده از آن در AVR

در برنامه نویسی موقعیت هایی پیش می آید که در آن گروهی از دستوراتی که کار واحدی را انجام می دهند مکررا استفاده می شوند.به عنوان مثال انتقال داده به خانه های رم ممکن است مکررا تکرار شوند.و یا ممکن است که یک قطعه برنامه به کرات در برنامه اجرا شود.منطقی نیست زمانی که به این برنامه ها احتیاج داریم آن هارا دوباره بازنویسی کنیم.ماکرو ها برای کاهش زمان نوشتن برنامه و کاهش امکان خطا به وجود آمدند.ماکرو ها این امکان را به برنامه نویس می دهند که یک وظیفه را فقط یک بار نوشته و در مواقع لزوم از آن استفاده کند.

LISTMACRO.

 اگر بخواهیم برنامه را اشکال زدایی کنیم باید از فایلی با پسوند lst. استفاده کنیم.محتویات این فایل شامل دستورات و کد معادل آنها به همراه آدرس ROM وهمچنین ماکروها می باشد. در حالت پیش فرض ماکروها به صورت کوتاه در این فایل نمایش داده می شوند و کد آنها آشکار نیست.اگر بخواهیم به جای تمام اسامی ماکرو ها کد آنها برای عیب یابی قرار بگیرد با استفاده از این دستورالعمل می توانیم نمایش بدنه ماکروها را در فایل .lst فعال کنیم.

نحوه تعریف ماکرو

در تعریف ماکرو باید سه بخش زیر وجود داشته باشد:

عبارت MACRO دستورالعملی است که به وسیله آن ابتدای ماکرو تعریف میشود و دستورالعمل ENDMACRO انتهای ماکرو را تعیین می کند.هر آنچه که مابین این دو دستورالعمل قرار بگیرد بدنه ماکرو را تشکیل می دهد که درواقع همان دستورات ماکرو هستند. نام ماکرو باید یکتا باشد و از قواعد نام گذاری زبان اسمبلی پیروی کند.یک ماکرو در زبان اسمبلی می تواند تا ۱۰پارمتر ورودی داشته باشد.پارمترهای ورودی ماکرو در زبان اسمبلی با نمادهای @۰ تا @۱۰ در بدنه ماکرو استفاده می شوند.ماکرو ها به وسیله اسمشان در برنامه فراخوانی می شوند.

مثال:

ماکروی تعریف شده در مثال بالا یک مقدار بلافصل یا مستقیم را در یک ثبات I/O بار می کند.این ماکرو به صورت زیر در برنامه اصلی فراخوانی می شود.

 

تفاوت ماکرو ها و زیرروالها

 ماکروها با هر بار فراخوانی حجم کد را افزایش می دهند ولی زیر روال ها با هر بار فراخوانی فقط به اندازه دستور فراخوانی حجم کد را افزایش می دهند.اجرای ماکروها از اجرای زیرروال ها سریعتر است.زیرروالها در هنگام فراخوانی از پشته استفاده می کنند ولی ماکروها از پشته استفاده نمی کنند.

چهار چوب کلی یک برنامه اسمبلی

برای نوشتن یک برنامه اسمبلی برای AVR به یک پردازشگر متن نیازداریم.همانطور که قبلا گفتم از نرم افزار رایگان AVR Studio می توان استفاده کرد.این نرم افزار شامل پردازشگر متن، اسمبلر و یک شبیه ساز است که میتوان برنامه نوشته شده را درآن تست کرده و معایب آن را رفع کرد.

studio6_overview_980x352_NO_CTA

 Verify Execution 1 Small

معمولا اولین خط برنامه اسمبلی از شبه دستور INCLUDE شروع می شود.با استفاده از این شبه دستور ثابت های نمادی و یا ماکروها و کدهای ازپیش تعریف شده را که در فایل هایی با پسوند INC ذخیره شده اند به برنامه اضافه می کنیم.

در خطوط بعدی معمولا ماکروها و ثابت های نمادی تعریف می شوند.باید توجه داشت که اگر خواستیم از یک ثابت  نمادی در یک ماکرو استفاده کنیم باید آن را قبل از تعریف ماکرو تعریف کرده باشیم.

بعد از موارد گفته شده باید به وسیله شبه دستور ORG آدرسی از ROM را که قرار است AVR کدهای برنامه را از آنجا شروع به خواندن کند مشخص کنیم.

در میکروکنترلر AVR مکانهایی از حافظه ROM که معمولا در ابتدای آن قرار میگیرند برای سرویس دادن به وقفه ها استفاده می شود که به آنها جدول بردار وقفه می گویند.(در مورد وقفه ها در آینده صحبت خواهد شد).ما باید آدرس شروع کد را طوری مشخص کنیم که اگر در برنامه خواستیم از وقفه استفاده کنیم برنامه اصلی با جدول بردار وقفه تداخل پیدا نکند.

بعد از تعیین آدرس شروع کد باید ثبات استک پوینتر(SP) را جهت تنظیم مکان پشته مقدار دهی کنیم.بهتر است که پشته از دورترین آدرس حافظه رم شروع شود.بدین صورت احتمال تداخل پشته با داده های ذخیره شده در رم کاهش پیدا می کند.

بعد از مقدار دهی استک پوینتر برنامه اصلی نوشته می شود.چهار چوب برنامه اصلی در اختیار برنامه نویس است ولی معمولا به این صورت است که ابتدا الگوریتم برنامه در قالب زیرروال هایی نوشته می شود.یعنی هر عمل و وظیفه ای در قالب یک زیر روال یا ماکرو کد نویسی شده و این زیر روال ها و ماکروها طبق الگوریتم فراخوانی می شوند.

در AVR دستوری برای اعلام پایان برنامه وجود ندارد، بنابراین باید دقت کنیم که کنترلر پس از پایان برنامه جلوتر نرود.برای این کار می توان با استفاده از دستورات پرش بلند مثل  RJMP و JMP کل الگوریتم را در یک چرخه دائمی قرار داد.

در مثال زیر یک برنامه کامل اسمبلی ساده برای ATMEGA32 نوشته شده که پس از اسمبل شدن می توان فایل هگز آن را بر روی فلاش میکرو پروگرام کرد.

در این مثال میکرو پس از دریافت داده از روی پورت A و B و ذخیره آنها در RAM آنها را با هم جمع می کند و حاصل آن را بعد از ذخیره در RAM بر روی پورت C به نمایش می گذارد.

مثال بالا یک مثال ساده از چهار چوب کلی برنامه نویسی به زبان اسمبلی می باشد.برنامه بالا را می توان خلاصه تر هم نوشت ولی بنده هر عمل را به صورت ماکرو یا زیرروال برای نشان دادن کلیات درآوردم.برچسب RAMEND قبلا در فایلی که به وسیله دستورالعمل INCLUDE به اول برنامه اضافه شده به آدرس آخرین خانه رم نسبت داده شده.اگر بخواهیم تعدادی داده ثابت را در ROM یا EEPROM تعریف کنیم باید به طریق گفته شده در جلسات قبل آنها را در آخرین خط برنامه بنویسیم.استفاده نکردن از دستورالعمل .ORG باعث می شود که داده هایی که به ROM تخصیص داده شده اند در آخر کدهای دستورات در ROM قرار بگیرند.در اینجا فقط برای مثال، این مورد را در آخر برنامه نوشتم اما کاربردی در برنامه ندارد.لازم به ذکر است که زیرروال SET_MIC برای تنظیم پایه های میکرو به صورت ورودی یا خروجی نوشته شده که در مباحث بعدی آموزش داده می شود.

این جلسه، آخرین جلسه ای بود که در مورد اسمبلی AVR حرف زده شد. از این پس در مورد اجزای داخلی AVR و کار کردن و برنامه ریزی آن‌ها با زبان C و زبان اسمبلی صحبت خواهیم کرد. برای دیدن اجزای داخلی و قسمت‌های آن اینجا را کلیک کنید.

درباره ی احسان عبداللهی

احسان عبداللهی هستم | کارشناسی الکترونیک خوندم و کارشناسی ارشد مخابرات |در سال 94 وب سایت میکرولرن را راه اندازی کردم | سعی کردم هر چیزی را به صورت کاربردی دنبال کنم، برای همین از کارشناسی کار با میکروکنترلرهای AVR و ARM، برنامه نویسی C و طراحی PCB را به صورت تخصصی کار کردم و از کارشناسی ارشد برنامه نویسی پایتون ، Computer vision و deep learning را به صورت تخصصی و کاربردی شروع کردم | الان هم سعی میکنم همیشه خودم را به روز نگه دارم و لذت کار کردن با دنیای برنامه نویسی و امبدد سیستم ها را به دیگران انتقال بدم

۴ دیدگاه

  1. سلام
    ببخشید شما این رجیستر های avr رو از کجای دیتا شیت پیدا کردید؟
    ایا همه ی رجیستر های avr با هم یکسان هستند؟
    مثلا یه جا گفتید که دستور LDI از رجیستر ۱۶ به بعد کار می کنه مثلا این تو همه میکرو های avr یکسانه؟
    بعدش من اگر بخام برای arm به صورت اسمبلی بنویسم این دستوراتی که گفتین واسه arm هم کار می کنه؟البته منظورم رجیستر نیست بله کلا دستورات و توابع اسمبلی رو می گم

    من اگر بخوام کلا برای یه میکرو arm اسمبلی برنامه بنویسم باید چیکار کنم رجیستر هاشونو باید از دیتاشیت پیدا کنم؟

    مثلا شما از کجا دونستید که دستور LDI برای برخی میکرو های avr وجود داره و برای میکرو های ضعیف نه؟البته دستور LDI رو مثال زدم

    ممنون

    • با درود فراوان
      اول یک نکته رو باید خدمتتون عرض کنم، برای بحث اسمبلی هر میکروکنترلر ساختار و معماری متفاوتی داره، پس هیچ وقت دستورات اسمبلی avr و دستورات اسمبلی arm یکسان نیستند هرچند که در عمل شبیه به هم هستند. برای یادگیری زبان اسمبلی یک میکروکنترلر نباید به دیتا شیت مراجعه کنید چون دیتا شیت فقط رجیسترها و نکات فنی رو گفته. هر کمپانی برای میکروکنترلرهای خودش فایل های مخصوص آموزش اسمبلی رو ارئه میکنه. برای مثال شرکت اتمل که میکروکنترلرهای avr را تولید میکنه در سایت خودش فایل هایی تحت عنوان Application note ارائه میده که در این لینک قابل دسترسی هست.
      در این صفحه هر چه برای آموزش اسمبلی avr لازم دارید را میتونید پیدا کنید. البته فقط مطالب اسمبلی در این صفحه نیست و خیلی مطالب مفید دیگه قابل دستیابی هست.

  2. خیلی ممنون
    واقعا خسته نباشید
    هیجا اینطور نگفته بود
    ولی من یه سوال دارم اینکه یه جا گفتین از میکرو های مگا ۶۴ به بعد چون رجیستر هاش زیاده باید برنامه رو متناسب با امکاناتش نوشت
    میشه اینجا رو یکم توضیح بدین

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *