فهرست مطالب:

آموزش AVR Assembler 2: 4 مرحله
آموزش AVR Assembler 2: 4 مرحله

تصویری: آموزش AVR Assembler 2: 4 مرحله

تصویری: آموزش AVR Assembler 2: 4 مرحله
تصویری: برنامه نویسی avr گام اول | Programming For AVR microcontroler 2024, جولای
Anonim
آموزش AVR Assembler 2
آموزش AVR Assembler 2

این آموزش ادامه "آموزش AVR Assembler 1" است

اگر از آموزش 1 استفاده نکرده اید ، باید همین حالا متوقف شوید و ابتدا آن را انجام دهید.

در این آموزش ما برنامه نویسی زبان اسمبلی atmega328p مورد استفاده در آردوینو را ادامه می دهیم.

شما نیاز خواهید داشت:

  1. یک آردوینو یا فقط یک آردوینو معمولی مانند آموزش 1
  2. یک LED
  3. یک مقاومت 220 اهم
  4. یک دکمه
  5. سیمها را برای ایجاد مدار روی تخته نان متصل کنید
  6. دفترچه راهنمای مجموعه: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. برگه اطلاعات: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

مجموعه کامل آموزش های من را می توانید در اینجا پیدا کنید:

مرحله 1: ساختن مدار

ساختن مدار
ساختن مدار

ابتدا باید مداری را بسازید که ما در این آموزش در حال مطالعه آن هستیم.

در اینجا نحوه اتصال آن آمده است:

PB0 (پین دیجیتال 8) - LED - R (220 اهم) - 5V

PD0 (پین دیجیتال 0) - دکمه فشاری - GND

می توانید با اتصال آن به GND به جای PB0 ، به درستی جهت گیری LED را بررسی کنید. اگر اتفاقی نیفتاد جهت را معکوس کنید و چراغ روشن شود. سپس دوباره آن را به PB0 متصل کرده و ادامه دهید. تصویر نشان می دهد که چگونه آردوینوی ورق من متصل شده است.

مرحله 2: نوشتن کد مجمع

نوشتن کد مجمع
نوشتن کد مجمع

کد زیر را در یک فایل متنی بنام pushbutton.asm بنویسید و آن را مانند avra در آموزش 1 کامپایل کنید.

توجه داشته باشید که در این کد ما نظرات زیادی داریم. هر بار که اسمبلر نقطه ویرگول می بیند ، بقیه خط را رد کرده و به خط بعدی می رود. این یک روش برنامه نویسی خوب است (مخصوصاً در زبان اسمبلی!) که به شدت کد خود را کامنت کنید تا وقتی در آینده به آن بازگشتید ، بدانید که چه می کردید. من قصد دارم در چند آموزش اول چیزها را کاملاً توضیح دهم تا بدانیم دقیقاً چه اتفاقی می افتد و چرا. بعداً ، هنگامی که کمی در برنامه نویسی مونتاژ بهتر شدیم ، من جزئیات را با جزئیات کمتری توضیح خواهم داد.

;************************************

؛ نوشته شده توسط: 1o_o7؛ تاریخ: 23 اکتبر 2014 ؛ **********************************

.نویسنده

. شامل "m328Pdef.inc".list.def temp = r16؛ تعیین رجیستر کار r16 به عنوان temp rjmp Init؛ خط اول اجرا شد

شروع:

درجه حرارت ؛ تمام بیت های دما را روی 1 قرار دهید. خارج از DDRB ، دما ؛ تنظیم مقدار 1 به عنوان جهت داده ورودی/خروجی ؛ ثبت نام در PortB ، که DDRB است ، آن را تنظیم می کند ؛ پین به عنوان خروجی ، 0 آن پین را به عنوان ورودی تنظیم می کند. بنابراین در اینجا ، همه پین های PortB خروجی (تنظیم شده روی 1) ldi temp ، 0b11111110 هستند ؛ بارگذاری شماره "فوری" در ثبت دما ؛ اگر فقط ld بود ، استدلال دوم ؛ به جای DDRD ، temp باید محل حافظه باشد. mv temp به DDRD ، نتیجه این است که PD0 ورودی است. و بقیه خروجی ها clr temp هستند. همه بیت های temp روی 0 خارج PortB ، temp تنظیم می شوند. همه بیت ها (یعنی پین ها) را در PortB روی 0V ldi temp ، 0b00000001 تنظیم کنید ؛ بارگذاری شماره فوری به temp PortD، temp؛ انتقال دما به PortD PD0 دارای مقاومت کششی است. (یعنی روی 5V تنظیم شده است) زیرا دارای 1 در آن بیت است ؛ بقیه از 0 تا 0 ولت هستند.

اصلی:

در دما ، PinD ؛ PinD وضعیت PortD را دارد ، این را در temp کپی کنید. اگر دکمه به PD0 متصل است این خواهد بود ؛ 0 وقتی دکمه فشار داده می شود ، 1 در غیر این صورت از زمانی که ؛ PD0 دارای یک مقاومت کششی است که معمولاً در 5 ولت خروجی PortB ، دما است. 0 و 1 خوانده شده در بالا را به PortB ارسال می کند. این بدان معناست که ما می خواهیم LED به PB0 متصل شود ، وقتی PD0 LOW باشد ، PB0 را روی LOW قرار می دهد و می چرخد. روی LED (از آنجا که طرف دیگر LED وصل است ؛ به 5 ولت متصل است و این PB0 را روی 0 ولت تنظیم می کند ؛ جریان جاری می شود) rjmp Main؛ به شروع Main باز می گردد

توجه داشته باشید که این بار ما نه تنها نظرات بیشتری در کد خود داریم ، بلکه یک قسمت سربرگ نیز داریم که اطلاعاتی در مورد اینکه چه کسی آن را نوشته و چه زمانی نوشته شده است ارائه می دهد. بقیه کد نیز به بخش هایی تقسیم می شود.

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

مرحله 3: تحلیل خط به خط کد

من از خطوطی که صرفاً نظرات هستند می گذرم ، زیرا هدف آنها بدیهی است.

.نویسنده

. شامل "m328Pdef.inc".list

این سه خط شامل فایل حاوی تعاریف Register و Bit برای ATmega328P است که ما در حال برنامه نویسی هستیم. دستور.nolist به اسمبلر می گوید که این فایل را در فایل pushbutton.lst که هنگام مونتاژ آن ایجاد می کند ، قرار ندهد. گزینه فهرست را خاموش می کند. پس از افزودن فایل ، گزینه فهرست را با فرمان.list دوباره روشن می کنیم. دلیل انجام این کار این است که فایل m328Pdef.inc بسیار طولانی است و ما واقعاً نیازی به دیدن آن در فایل لیست نداریم. اسمبلر ما ، avra ، به طور خودکار یک فایل لیست ایجاد نمی کند و اگر بخواهیم با استفاده از دستور زیر مونتاژ کنیم:

avra -l pushbutton.lst pushbutton.asm

اگر این کار را انجام دهید ، فایلی به نام pushbutton.lst ایجاد می شود و اگر این فایل را بررسی کنید ، متوجه می شوید که کد برنامه شما را به همراه اطلاعات اضافی نشان می دهد. اگر به اطلاعات اضافی نگاه کنید ، خواهید دید که خطوط با C شروع می شوند: به دنبال آن آدرس نسبی در شش ضلعی جایی که کد در حافظه قرار داده شده است. اساساً در 000000 با اولین فرمان شروع می شود و با هر فرمان بعدی از آنجا افزایش می یابد. ستون دوم بعد از محل نسبی در حافظه ، کد hex برای فرمان است و سپس کد hex برای استدلال فرمان. در فایلهای آموزشی بیشتر در مورد آموزشهای بعدی بحث خواهیم کرد.

.def temp = r16؛ رجیستر کار r16 را به عنوان دما تعیین کنید

در این خط ما از دستور assembler ".def" برای تعریف متغیر "temp" برابر با r16 "ثبت کار" استفاده می کنیم. ما از ثبت نام r16 به عنوان شماره ای که اعدادی را که می خواهیم کپی کنیم در پورت ها و رجیسترهای مختلف (که نمی توان آنها را مستقیماً نوشت) ذخیره می کنیم.

تمرین 1: سعی کنید یک عدد دودویی را مستقیماً در یک درگاه یا ثبت ویژه مانند DDRB کپی کنید و ببینید وقتی سعی می کنید کد را جمع آوری کنید چه اتفاقی می افتد.

یک ثبت شامل یک بایت (8 بیت) اطلاعات است. اساساً معمولاً مجموعه ای از SR-Latches است که هر یک "بیت" است و شامل 1 یا 0 است. ما ممکن است بعداً در این سری در مورد این (و حتی ساخت!) بحث کنیم. شاید برای شما این سوال پیش آمده باشد که "ثبت کار" چیست و چرا ما r16 را انتخاب کردیم. وقتی در باتلاق داخلی تراشه فرو می رویم ، در یک آموزش آینده در مورد آن بحث خواهیم کرد. در حال حاضر من می خواهم شما نحوه انجام کارهایی مانند نوشتن کد و برنامه سخت افزار فیزیکی را درک کنید. سپس یک چارچوب مرجع از آن تجربه خواهید داشت که درک و ثبت ویژگیهای میکروکنترلر را آسان تر می کند. متوجه هستم که اکثر کتابهای درسی و بحث های مقدماتی این کار را برعکس انجام می دهند ، اما من متوجه شده ام که بازی کردن ویدئویی برای مدتی برای بدست آوردن دیدگاه جهانی قبل از خواندن دفترچه راهنما بسیار آسانتر از خواندن کتابچه راهنمای اولیه است.

rjmp Init؛ خط اول اجرا شد

این خط یک "جهش نسبی" به برچسب "Init" است و در اینجا واقعاً ضروری نیست زیرا دستور بعدی در Init است ، اما ما آن را برای استفاده در آینده قرار می دهیم.

شروع:

درجه حرارت ؛ تمام بیت های دما را روی 1 قرار دهید.

پس از برچسب Init ، فرمان "set register" را اجرا می کنیم. با این کار همه 8 بیت موجود در ثبت "temp" (که به یاد می آورید r16 است) را روی 1 قرار می دهد. بنابراین temp اکنون حاوی 0b11111111 است.

خارج از DDRB ، دما ؛ مقدار کمی روی 1 در رجیستر ورودی/خروجی جهت داده تنظیم کنید

؛ برای PortB ، که DDRB است ، آن پین را به عنوان خروجی تنظیم می کند. 0 آن پین را به عنوان ورودی تنظیم می کند. بنابراین در اینجا ، همه پین های PortB خروجی هستند (روی 1 تنظیم شده است)

رجیستر DDRB (Data Direction Register for PortB) می گوید که کدام پین ها در PortB (یعنی PB0 تا PB7) به عنوان ورودی و کدام به عنوان خروجی تعیین شده اند. از آنجا که ما پین PB0 را به LED خود وصل کرده ایم و بقیه به هیچ چیزی متصل نیستیم ، تمام بیت ها را روی 1 تنظیم می کنیم ، به این معنی که همه آنها خروجی هستند.

ldi temp ، 0b11111110 ؛ شماره "فوری" را در ثبت دما بارگذاری کنید

؛ اگر فقط ld بود ، استدلال دوم چنین می کرد ؛ باید محل حافظه باشد

این خط شماره دودویی 0b11111110 را در ثبت دما بارگذاری می کند.

out DDRD، temp؛ mv temp به DDRD ، نتیجه این است که PD0 ورودی است و

؛ بقیه خروجی هستند

اکنون ما Data Direction Register را برای PortD از temp تنظیم می کنیم ، زیرا temp هنوز حاوی 0b11111110 است ، می بینیم که PD0 به عنوان یک پین ورودی تعیین می شود (زیرا در نقطه راست 0 وجود دارد) و بقیه به عنوان خروجی تعیین می شوند. 1 در آن نقاط

دمای clr ؛ همه بیت های دما روی 0 تنظیم می شوند

خارج PortB، temp؛ تمام بیت ها (یعنی پین ها) در PortB را روی 0 ولت تنظیم کنید

ابتدا دمای ثبت نام را "پاک" می کنیم ، یعنی همه بیت ها را به صفر می رسانیم. سپس آن را در ثبت PortB کپی می کنیم که 0V را روی همه آن پین ها تنظیم می کند. صفر در بیت PortB به این معنی است که پردازنده آن پین را روی 0V نگه می دارد ، یک بیت روی بیت باعث می شود که آن پین روی 5V تنظیم شود.

تمرین 2: از یک مولتی متر برای بررسی اینکه آیا همه پین های PortB در واقع صفر هستند یا خیر استفاده کنید. آیا چیز عجیبی در مورد PB1 اتفاق می افتد؟ آیا می دانید چرا ممکن است چنین باشد؟ (مشابه تمرین 4 زیر و سپس کد را دنبال کنید …) تمرین 3: دو خط بالا را از کد خود حذف کنید. آیا برنامه هنوز به درستی اجرا می شود؟ چرا؟

ldi temp ، 0b00000001 ؛ بارگذاری شماره فوری در temp

خارج PortD، temp؛ انتقال دما به PortD PD0 در 5V است (دارای مقاومت کششی) ؛ از آنجا که دارای 1 در آن بیت است بقیه 0V هستند. تمرین 4: دو خط بالا را از کد خود حذف کنید. آیا برنامه هنوز به درستی اجرا می شود؟ چرا؟ (این با تمرین 3 بالا متفاوت است. نمودار پین را ببینید. تنظیمات پیش فرض DDRD برای PD0 چیست؟ (به صفحه 90 صفحه داده مراجعه کنید

ابتدا ما شماره 0b00000001 را "فوری" در temp بارگذاری می کنیم. بخش "فوری" وجود دارد زیرا ما یک شماره مستقیم را در temp بارگذاری می کنیم تا یک اشاره گر در یک مکان حافظه حاوی شماره بارگیری. در این صورت ما به سادگی از "ld" به جای "ldi" استفاده می کنیم. سپس این شماره را به PortD ارسال می کنیم که PD0 را روی 5V و بقیه را روی 0V تنظیم می کند.

اکنون ما پین ها را به عنوان ورودی یا خروجی تنظیم کرده ایم و حالت های اولیه آنها را به صورت 0V یا 5V (LOW یا HIGH) تنظیم کرده ایم و بنابراین اکنون "حلقه" برنامه خود را وارد می کنیم.

اصلی: در temp ، PinD ؛ PinD حالت PortD را دارد ، این را در temp کپی کنید

؛ اگر دکمه به PD0 متصل است ، این خواهد بود. 0 وقتی دکمه فشار داده می شود ، 1 در غیر این صورت PD0 دارای مقاومت کششی است که معمولاً در 5V است

PinD ثبت شده شامل وضعیت فعلی پین های PortD است. به عنوان مثال ، اگر سیم 5 ولت را به PD3 وصل کرده اید ، در چرخه ساعت بعدی (که 16 میلیون بار در ثانیه اتفاق می افتد زیرا ما میکروکنترلر را به سیگنال ساعت 16 مگاهرتز متصل کرده ایم) بیت PinD3 (از وضعیت فعلی PD3) تبدیل به 1 به جای 0 می شود. بنابراین در این خط ما وضعیت فعلی پین ها را در temp کپی می کنیم.

خارج PortB، temp؛ 0 و 1 خوانده شده در بالا را به PortB ارسال می کند

؛ این بدان معنی است که ما می خواهیم LED به PB0 متصل شود ، بنابراین ؛ وقتی PD0 LOW باشد ، PB0 را روی LOW قرار می دهد و می چرخد. روی LED (طرف دیگر LED متصل است ؛ به 5V و این PB0 را روی 0V تنظیم می کند تا جریان جریان یابد)

حال ما وضعیت پین ها را در PinD به خروجی PortB ارسال می کنیم. به طور موثر ، این بدان معناست که PD0 یک عدد 1 را به PortD0 ارسال می کند مگر اینکه دکمه فشار داده شود. در این صورت از آنجا که دکمه به زمین متصل است ، پین در 0V خواهد بود و صفر را به PortB0 ارسال می کند. حال ، اگر به نمودار مدار نگاه کنید ، 0V در PB0 به این معنی است که چراغ LED روشن می شود زیرا طرف دیگر آن 5V است. اگر ما دکمه را فشار نمی دهیم ، به طوری که 1 به PB0 ارسال می شود ، این بدان معناست که ما 5V در PB0 و همچنین 5V در طرف دیگر LED داریم و بنابراین هیچ اختلاف احتمالی وجود ندارد و هیچ جریانی جریان نخواهد داشت و بنابراین چراغ LED روشن نمی شود (در این مورد یک LED است که یک دیود است و بنابراین جریان فقط در یک جهت بدون در نظر گرفتن هر چیزی جریان می یابد).

rjmp Main؛ بازگشت به شروع

این جهش نسبی ما را به برچسب اصلی ما باز می گرداند و دوباره PinD را بررسی می کنیم و غیره. هر 16 میلیونم ثانیه بررسی کنید که آیا دکمه فشار داده می شود و PB0 را بر این اساس تنظیم کنید.

تمرین 5: کد خود را طوری تغییر دهید که LED شما به جای PB0 به PB3 متصل شود و ببینید آیا کار می کند. تمرین 6: LED خود را به جای 5 ولت به GND وصل کنید و بر این اساس کد خود را اصلاح کنید.

مرحله 4: نتیجه گیری

در این آموزش ما زبان مونتاژ ATmega328p را بیشتر بررسی کرده ایم و نحوه کنترل LED با یک دکمه را یاد گرفته ایم. به طور خاص دستورات زیر را یاد گرفتیم:

ser register تمام بیت های یک ثبات را روی 1 قرار می دهد

clr register تمام بیت های یک ثبات را روی 0 تنظیم می کند

در ثبت نام ، i/o register شماره را از یک ثبت نام i/o به یک ثبت کار کپی می کند

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

قبل از ادامه این آموزش ها ، باید منتظر بمانم و میزان علاقه مندی را ببینم. اگر تعدادی از افراد واقعاً از یادگیری نحوه برنامه نویسی برنامه های این ریزپردازنده در زبان اسمبلی لذت ببرند ، من مدارهای پیچیده تر را ادامه می دهم و از کد قوی تری استفاده می کنم.

توصیه شده: