Mundarija:

AVR Assembler qo'llanmasi 3: 9 qadamlar
AVR Assembler qo'llanmasi 3: 9 qadamlar

Video: AVR Assembler qo'llanmasi 3: 9 qadamlar

Video: AVR Assembler qo'llanmasi 3: 9 qadamlar
Video: Anleitung für den elektrischen Stromkreis der Zweitaktmotorzündung mit Schaltplan 2024, Iyul
Anonim
AVR Assembler qo'llanmasi 3
AVR Assembler qo'llanmasi 3

3 -sonli darslikka xush kelibsiz!

Ishni boshlashdan oldin, men falsafiy fikrni aytmoqchiman. Ushbu qo'llanmalarda biz yaratayotgan sxemalar va kodlar bilan tajriba qilishdan qo'rqmang. Atrofdagi simlarni o'zgartiring, yangi komponentlar qo'shing, komponentlarni chiqarib oling, kod satrlarini o'zgartiring, yangi qatorlar qo'shing, satrlarni o'chiring va nima bo'lishini ko'ring! Biror narsani sindirish juda qiyin va agar buzsangiz, kimga g'amxo'rlik qiladi? Biz foydalanadigan hech narsa, shu jumladan mikrokontrolder ham juda qimmatga tushmaydi va ishlar qanday muvaffaqiyatsiz bo'lishi mumkinligini ko'rish har doim ta'lim beradi. Keyingi safar nima qilmaslik kerakligini nafaqat bilib olasiz, balki, eng muhimi, nima uchun bunday qilmasligingizni bilib olasiz. Agar siz menga o'xshagan bo'lsangiz, bolaligingizda va sizda yangi o'yinchoq bo'lganida, uni bo'laklarga aylantirganingizga ko'p vaqt bo'lmaganida, uning to'g'ri tiklanishiga nima sabab bo'lganini ko'rdingizmi? Ba'zida o'yinchoq tuzatib bo'lmaydigan darajada buzilib ketadi, lekin hech qanday muammo bo'lmaydi. Bolaga qiziquvchanligini o'yinchoqlar singangacha o'rganishga ruxsat berish, uni idish yuvish mashinasi o'rniga olim yoki muhandisga aylantiradi.

Bugun biz juda oddiy sxemani o'tkazamiz va keyin nazariyaga biroz og'irlik kiritamiz. Kechirasiz, lekin bizga asboblar kerak! Men buni 4 -o'quv qo'llanmasida to'ldirishga va'da beraman, bu erda biz yanada jiddiyroq elektr inshootlarini quramiz va natija juda zo'r bo'ladi. Biroq, bu darsliklarning barchasini bajarish usuli juda sekin, o'ychan tarzda. Agar siz shunchaki shudgor qilsangiz, sxemani tuzing, kodni nusxa ko'chiring va joylashtiring va keyin ishga tushiring, albatta, u ishlaydi, lekin siz hech narsani o'rganmaysiz. Siz har bir satr haqida o'ylashingiz kerak. To'xtatish. Tajriba. Ixtiro qiling. Agar siz shunday qilsangiz, 5 -dars oxirida siz ajoyib narsalarni yaratishni to'xtatasiz va sizga boshqa repetitorlik kerak bo'lmaydi. Aks holda, siz o'rganish va yaratish o'rniga, shunchaki tomosha qilyapsiz.

Qanday bo'lmasin, falsafa etarli, boshlaylik!

Ushbu qo'llanmada sizga kerak bo'ladi:

  1. sizning prototip taxtangiz
  2. LED
  3. ulash simlari
  4. 220 dan 330 ohmgacha bo'lgan qarshilik
  5. Ko'rsatmalar to'plami: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. Ma'lumotlar jadvali: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. boshqa kristalli osilator (ixtiyoriy)

O'quv qo'llanmalarining to'liq to'plamiga havola:

1 -qadam: O'chirish sxemasini qurish

O'chirish tizimini qurish
O'chirish tizimini qurish

Ushbu darslikdagi sxema juda oddiy. Biz asosan "miltillash" dasturini yozmoqchimiz, shuning uchun bizga quyidagilar kifoya qiladi.

LEDni PD4 ga, keyin 330 ohmli rezistorga, so'ngra erga ulang. ya'ni

PD4 - LED - R (330) - GND

va bu shunday!

Nazariya juda qiyin bo'ladi …

2 -qadam: Nima uchun bizga izohlar va M328Pdef.inc fayli kerak?

O'ylaymanki, biz nima uchun qo'shilgan fayl va sharhlar foydali ekanligini ko'rsatishimiz kerak. Ularning hech biri aslida kerak emas va siz ularsiz kodni xuddi shunday yozishingiz, yig'ishingiz va yuklashingiz mumkin va u juda yaxshi ishlaydi (garchi qo'shilmagan fayl bo'lmasa ham, siz montajchidan shikoyat olishingiz mumkin - lekin xatolar yo'q)

Bu erda biz bugun yozmoqchi bo'lgan kod, faqat men sharhlar va qo'shilgan faylni o'chirib tashladim.

ATmega328P qurilmasi

.org 0x0000 jmp a.org 0x0020 jmp ea: ldi r16, 0x05 0x25, r16 ldi r16, 0x01 sts 0x6e, r16 sei clr r16 out 0x26, r16 sbi 0x0a, 0x04 sbi 0x0b, 0x04 b: 0x04 b: sbi 0 cbi 0x0b, 0x04 rcall c rjmp bc: clr r17 d: cpi r17, 0x1e brne d ret e: inc r17 cpi r17, 0x3d brne PC+2 clr r17 reti

juda oddiy, to'g'rimi? Xaha Agar siz ushbu faylni yig'gan va yuklagan bo'lsangiz, siz LEDni sekundiga 1 marta yonib -o'chib turishiga olib kelasiz, uning yonishi 1/2 soniya davom etadi va miltillovchi orasidagi pauza 1/2 sekund davom etadi.

Biroq, bu kodni ko'rib chiqish deyarli ma'rifatli emas. Agar siz shunday kod yozmoqchi bo'lsangiz va kelajakda uni o'zgartirmoqchi bo'lsangiz yoki o'zgartirishni xohlasangiz, sizga qiyin bo'ladi.

Keling, sharhlar yozib, faylni o'z ichiga olaylik, shunda biz buni tushunib olamiz.

3 -qadam: Blink.asm

Mana bugun biz muhokama qiladigan kod:

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

; muallif: 1o_o7; sana:; versiya: 1.0; fayl quyidagicha saqlanadi: blink.asm; AVR uchun: atmega328p; soat chastotasi: 16 MGts (ixtiyoriy); **********************************; Dastur funktsiyasi: ---------------------; LEDni miltillatish bilan soniyalar sonini hisoblab chiqadi;; PD4 - LED - R (330 ohm) - GND;; --------------------------------------.nolist. "./m328Pdef.inc" ni o'z ichiga oladi..list; ==============; Deklaratsiyalar:.def temp = r16.def to'lqinlari = r17.org 0x0000; xotira (shaxsiy kompyuter) qayta o'rnatish ishlovchilarining joylashuvi rjmp Reset; jmp 2 ta protsessor tsiklini, rjmp esa atigi 1 ta turadi; shuning uchun 8k baytdan oshib o'tish kerak bo'lmasa; sizga faqat rjmp kerak. Faqat ba'zi mikrokontrollerlar; rjmp va jmp emas.org 0x0020; Timer0 to'lg'azish moslamasining xotira joyi rjmp overflow_handler; timer0 to'lishi to'xtab qolsa, bu erga o'ting; ============ Reset: ldi temp, 0b00000101 TCCR0B, temp; CS00, CS01, CS02 soat tanlagichlarini 101 ga o'rnating; bu taymer Counter0, TCNT0 ni FCPU/1024 rejimiga o'tkazadi; shuning uchun u protsessor chastotasida/1024 ldi temp, 0b00000001 sts TIMSK0, temp; Taymerni to'ldirishni to'xtatishni yoqish bitini o'rnating (TOIE0); Timer Interrupt Mask Register (TIMSK0) sei; global uzilishlarni yoqish - "sbi SREG, I" clr temp out TCNT0, temp; taymer/hisoblagichni 0 sbi DDRD, 4 ga ishga tushirish; PD4 ni chiqishga o'rnating; =====================; Dasturning asosiy qismi: miltillash: sbi PORTD, 4; chaqirishni kechiktirish PD4 -dagi LEDni yoqish; kechikish 1/2 soniya cbi bo'ladi PORTD, 4; chaqirishni kechiktirish PD4 -dagi LEDni o'chiring; kechikish 1/2 soniya rjmp miltillaydi; boshlang'ich kechikishiga qaytish: clr overflows; toshib ketishni 0 sec_count ga o'rnating: cpi overflows, 30; to'lib toshganlar sonini va 30 soniya sonini solishtiring; tarmoqqa teng bo'lmaganda sec_count -ga qaytish; agar 30 ta to'lib toshgan bo'lsa, miltillashga qaytish overflow_handler: inc overflows; toshmalarga o'zgarmaydigan cpi overflows ga 1 qo'shing, 61; 61 brne PC+2 bilan solishtiring; Counter + 2 dasturi (keyingi qatorni o'tkazib yuborish), agar teng bo'lmasa, to'lg'azish; agar 61 ta to'lib toshgan bo'lsa, hisoblagichni nol retiga qaytaring; uzilishdan qaytish

Ko'rib turganingizdek, hozir mening sharhlarim biroz qisqartirilgan. Ko'rsatmalar to'plamidagi buyruqlar nima ekanligini bilib olsak, buni izohlarda tushuntirishga hojat yo'q. Biz nima bo'layotganini faqat dastur nuqtai nazaridan tushuntirishimiz kerak.

Biz bularning barchasi nima bo'lishini muhokama qilamiz, lekin avval global nuqtai nazarga ega bo'lishga harakat qilaylik. Dasturning asosiy qismi quyidagicha ishlaydi.

Birinchidan, biz "sbi PORTD, 4" bilan PORTD ning 4 -bitini o'rnatdik, bu 1 -ni PD4 -ga yuboradi, bu esa bu pimdagi kuchlanishni 5V ga qo'yadi. Bu LEDni yoqadi. Keyin biz sekundiga 1/2 hisoblanadigan "kechiktirish" kichik dasturiga o'tamiz (buni keyinroq tushuntiramiz). Keyin biz PORTD -da PD4 -ni 0V ga o'rnatadigan va shu sababli LEDni o'chiradigan 4 -chi milt -milt qaytamiz. Keyin yana 1/2 soniya kechiktiramiz va yana "rjmp miltillash" bilan miltillash boshiga qaytamiz.

Siz ushbu kodni ishga tushirishingiz va u nima qilish kerakligini ko'rishingiz kerak.

Va u erda sizda bor! Bu kodning hammasi jismonan bajaradi. Mikrokontroller nima qilayotganining ichki mexanikasi biroz ko'proq ishtirok etadi va shuning uchun biz bu darslikni qilamiz. Shunday qilib, keling, har bir bo'limni navbat bilan muhokama qilaylik.

4 -qadam:.org Assembler direktivalari

Biz oldingi darsliklarimizda.nolist,.list,.include va.def assembler ko'rsatmalari nima qilishini allaqachon bilamiz, shuning uchun avval 4 kod satrini ko'rib chiqaylik:

.org 0x0000

jmp Reset.org 0x0020 jmp overflow_handler

. Org bayonoti assambleyaga "Dastur xotirasida" keyingi bayonotni qaerga qo'yish kerakligini aytadi. Sizning dasturingiz bajarilayotganda "Dastur hisoblagichi" (kompyuter sifatida qisqartirilgan) bajarilayotgan satrning manzilini o'z ichiga oladi. Shunday qilib, bu holda, kompyuter 0x0000 bo'lsa, u xotirada "jmp Reset" buyrug'ini ko'radi. Biz jmp Reset -ni o'sha joyga qo'yishni istaymiz, chunki dastur ishga tushganda yoki chip qayta tiklansa, kompyuter shu nuqtada kodni bajarishni boshlaydi. Ko'rib turganimizdek, biz unga "Qayta tiklash" deb nomlangan bo'limga darhol "o'tish" kerakligini aytdik. Nega bunday qildik? Bu shuni anglatadiki, yuqoridagi oxirgi ikkita satr shunchaki o'tkazib yuborilgan! Nima uchun?

Xo'sh, bu erda narsalar qiziqarli bo'ladi. Endi siz ushbu qo'llanmaning birinchi sahifasida ko'rsatgan ATmega328p ma'lumotlar jadvaliga ega pdf ko'rish vositasini ochishingiz kerak bo'ladi (shuning uchun "sizga kerak bo'ladi" bo'limining 4 -bandi). Agar sizning ekraningiz juda kichkina bo'lsa yoki sizda juda ko'p oyna ochilgan bo'lsa (menda bo'lgani kabi), men nima qilsam, buni Ereader yoki Android telefoningizga qo'yishingiz mumkin. Agar siz montaj kodini yozishni rejalashtirmoqchi bo'lsangiz, siz uni doimo ishlatasiz. Qizig'i shundaki, barcha mikrokontollerlar bir -biriga o'xshash tarzda tashkil etilgan, shuning uchun siz ma'lumotlar jadvallarini o'qishga va ulardan kodlashga o'rganganingizda, boshqa mikrokontroller uchun ham xuddi shunday qilish deyarli ahamiyatsiz bo'ladi. Shunday qilib, biz atmega328p emas, balki qandaydir ma'noda barcha mikrokontrollerlardan foydalanishni o'rganyapmiz.

Xo'sh, ma'lumotlar jadvalining 18-sahifasiga o'ting va 8-2-rasmga qarang.

Mikrokontrollerdagi dastur xotirasi shunday o'rnatiladi. Siz ko'rishingiz mumkinki, u 0x0000 manzili bilan boshlanadi va ikki qismga bo'lingan; dasturning flesh -bo'limi va yuklashning flesh -bo'limi. Agar siz 277-jadvalga 27-14-jadvalga qisqacha murojaat qilsangiz, dasturning flesh-bo'limi 0x0000 dan 0x37FF gacha, yuklash chirog'i esa qolgan joylarni 0x3800 dan 0x3FFF gacha egallashini ko'rasiz.

1 -mashq: Dastur xotirasida nechta joy bor? Ya'ni 3FFFni kasrga aylantiring va 0 ga sanashni boshlaganimiz uchun 1 qo'shing. Har bir xotira joyining kengligi 16 bit (yoki 2 bayt) bo'lgani uchun xotira baytlarining umumiy soni qancha? Endi kilobaytda 2^10 = 1024 bayt borligini eslab, uni kilobaytga aylantiring. Yuklash chirog'i bo'limi 0x3800 dan 0x37FF gacha, bu qancha kilobayt? Bizning dasturimizni saqlash uchun qancha kilobayt xotira qoladi? Boshqacha aytganda, bizning dasturimiz qanchalik katta bo'lishi mumkin? Nihoyat, bizda nechta kod satri bo'lishi mumkin?

Xo'sh, endi biz flesh -dastur xotirasini tashkil qilish haqida hamma narsani bilganimiz uchun.org bayonotlarini muhokama qilishni davom ettiramiz. Biz ko'ramizki, 0x0000 xotira birinchi joyida Reset deb nomlangan bo'limimizga o'tish bo'yicha ko'rsatma mavjud. Endi biz ".org 0x0020" bayonoti nima qilishini ko'ramiz. Unda aytilishicha, biz keyingi satrda ko'rsatma 0x0020 xotira joyiga joylashtirilishini xohlaymiz. Biz bergan ko'rsatma, bizning kodimizda "overflow_handler" deb yozilgan bo'limga o'tish … endi nima uchun biz bu sakrashni 0x0020 xotira joyiga joylashtirishni talab qilamiz? Buni bilish uchun biz ma'lumotlar jadvalining 65-sahifasiga o'ting va 12-6-jadvalga qaraymiz.

12-6-jadval-"Vektorlarni tiklash va uzilishlar" jadvali bo'lib, u "uzilish" olganda kompyuter qayerga ketishini aniq ko'rsatadi. Masalan, agar siz 1-sonli Vektor raqamiga qarasangiz, uzilishning "manbai" "RESET" bo'lib, u "Tashqi pin, Quvvatni qayta o'rnatish, Qora rangni qayta tiklash va Watchdog tizimini tiklash" ma'nosini beradi. Bunday narsalar bizning mikrokontrolderimiz bilan sodir bo'ladi, kompyuter 0x0000 dastur xotirasida dasturimizni bajarishni boshlaydi. Bizning.org direktivasi haqida nima deyish mumkin? Xo'sh, biz 0x0020 xotira joyiga buyruq berdik va agar siz jadvalga qarasangiz, agar Taymer/Counter0 to'lib ketsa (TIMER0 OVFdan kelsa), u 0x0020 joyidagi hamma narsani bajaradi. Shunday qilib, bu sodir bo'lganda, kompyuter "overflow_handler" deb nomlangan joyga o'tadi. Yaxshi, to'g'rimi? Bir daqiqadan so'ng nima uchun bunday qilganimizni ko'rasiz, lekin avval darsning bu bosqichini chetga surib tugatamiz.

Agar biz o'z kodimizni yanada toza va tartibli qilishni xohlasak, biz hozir muhokama qilayotgan 4 qatorni quyidagilar bilan almashtirishimiz kerak (66 -betga qarang):

.org 0x0000

rjmp tiklash; Kompyuter = 0x0000 reti; Kompyuter = 0x0002 reti; Kompyuter = 0x0004 reti; Kompyuter = 0x0006 reti; Kompyuter = 0x0008 reti; Kompyuter = 0x000A… reti; Kompyuter = 0x001E jmp overflow_handler: Kompyuter = 0x0020 reti: Kompyuter = 0x0022… reti; Kompyuter = 0x0030 reti; Kompyuter = 0x0032

Shunday qilib, agar ma'lum bir uzilish sodir bo'lsa, u "reti" bo'ladi, bu "uzilishdan qaytish" degan ma'noni anglatadi va boshqa hech narsa bo'lmaydi. Ammo, agar biz bu uzilishlarni hech qachon "yoqmasak", ular ishlatilmaydi va biz dastur kodini bu joylarga qo'yishimiz mumkin. Hozirgi "blink.asm" dasturida biz faqat timer0 to'lg'azishining uzilishini yoqamiz (va, albatta, har doim yoqilgan qayta tiklash uzilishi) va shuning uchun biz boshqalarni bezovta qilmaymiz.

Timer0 to'lg'azish uzilishini qanday "yoqish" mumkin? … bu bizning darslikdagi keyingi qadamimiz.

5 -qadam: Taymer/Hisoblagich 0

Taymer/hisoblagich 0
Taymer/hisoblagich 0

Yuqoridagi rasmga qarang. Bu "kompyuter" ning qaror qabul qilish jarayoni, agar tashqi ta'sir bizning dasturimiz oqimini "to'xtatsa". Tashqaridan uzilish sodir bo'lganligi to'g'risida signal kelganida qiladigan birinchi narsa, biz bunday uzilishlar uchun "uzilishni yoqish" bitini o'rnatganligimizni tekshirish. Agar bizda yo'q bo'lsa, u bizning keyingi kod qatorimizni bajarishda davom etadi. Agar biz ma'lum bir uzilishni yoqish bitini o'rnatgan bo'lsak (0 o'rniga bu bitda 1 bo'lishi kerak), u holda biz "global uzilishlar" ni yoqib qo'yganimizni tekshiramiz, aks holda u keyingi qatorga o'tadi. kodni kiriting va davom eting. Agar biz global uzilishlarni ham faollashtirgan bo'lsak, u holda bu turdagi uzilishlar (12-6-jadvalda ko'rsatilgandek) dastur xotirasi joylashgan joyga o'tadi va biz u erda qo'ygan buyruqlarimizni bajaradi. Keling, bularning barchasini kodimizda qanday amalga oshirganimizni ko'rib chiqaylik.

Bizning kodimizning etiketlangan bo'limini tiklash quyidagi ikki satrdan boshlanadi:

Qayta o'rnatish:

ldi temp, 0b00000101 TCCR0B, temp

Biz bilganimizdek, bu tempdan keyin (ya'ni R16) yuklanadi, bu raqam 0b00000101. Keyin bu raqamni "out" buyrug'i yordamida TCCR0B deb nomlangan registrga yozib qo'yadi. Bu registr nima? Ma'lumotlar varag'ining 614 -sahifasiga o'tamiz. Bu jadvalning o'rtasida, barcha registrlar umumlashtiriladi. 0x25 manzilida siz TCCR0B ni topasiz. (Endi siz kodning sharhlanmagan versiyasida "0x25, r16" qatori qaerdan kelganini bilasiz). Biz yuqoridagi kod segmentiga ko'ra, 0 -bit va 2 -bitni o'rnatdik va qolganlarini tozaladik. Jadvalga qarab, bu CS00 va CS02 ni o'rnatganimizni bildiradi. Endi ma'lumotlar jadvalining "PWM bilan 8-bitli taymer/Counter0" bo'limiga o'tamiz. Xususan, ushbu bobning 107 -sahifasiga o'ting. Siz "Taymer/Hisoblagichni nazorat qilish registri B" (TCCR0B) registrining xuddi shu tavsifini ko'rasiz, biz uni ro'yxatga olish jadvalining jadvalida ko'rdik (shuning uchun biz bu erga to'g'ridan -to'g'ri kelishimiz mumkin edi, lekin men sizning xulosa jadvallaridan qanday foydalanishni ko'rishingizni xohlardim. kelajakda ma'lumot olish uchun). Ma'lumotlar varag'i ushbu registrdagi har bir bit va ular nima qilayotganini tavsiflashni davom ettiradi. Biz hozircha bularning barchasini o'tkazib yuboramiz va sahifani 15-9-jadvalga o'tkazamiz. Jadvalda "Vaqtni tanlash bit tavsifi" ko'rsatilgan. Endi biz o'sha registrda biz o'rnatgan bitlarga mos keladigan chiziqni topmaguningizcha, jadvalga qarang. Chiziqda "clk/1024 (oldindan hisoblagichdan)" yozilgan. Buning ma'nosi shundaki, biz Timer/Counter0 (TCNT0) protsessor chastotasi 1024 ga bo'linadigan tezlikni belgilashini xohlaymiz. Bizda mikrokontrolerimiz 16 MGtsli kristalli osilator bilan oziqlangan, demak, bizning protsessorimiz ko'rsatmalarni bajaradigan tezlikni bildiradi. Sekundiga 16 million ko'rsatma. Shunday qilib, bizning TCNT0 hisoblagichimiz tezligi sekundiga 16 million/1024 = 15625 marta bo'ladi (soatlarning turli xil bitlarini sinab ko'ring va nima bo'lishini ko'ring - bizning falsafani eslaysizmi?). Keling, 15625 raqamini xotiramizda saqlaylik va keyingi ikkita kod satriga o'tamiz:

ldi temp, 0b00000001

sts TIMSK0, harorat

Bu TIMSK0 deb nomlangan registrning 0 -bitini o'rnatadi va qolganlarini tozalaydi. Agar siz ma'lumotlar varag'ining 109 -betiga nazar tashlasangiz, TIMSK0 "Taymer/hisoblagichni kesish niqobi 0" degan ma'noni anglatishini ko'rasiz va bizning kodimiz TOIE0 deb nomlangan 0 -bitni o'rnatgan, u "Taymer/Counter0 to'lib ketishining uzilishini yoqish" degan ma'noni anglatadi. … Mana! Endi bu nima haqida ekanligini ko'rasiz. Endi biz rasmning yuqorisidagi birinchi qaroridan xohlaganimizdek "uzilishlarni yoqish bitini sozlash" ga egamiz. Shunday qilib, endi biz "global uzilishlar" ni yoqishimiz kerak va bizning dasturimiz bunday uzilishlarga javob bera oladi. Biz qisqa vaqt ichida global uzilishlarga ruxsat beramiz, lekin buni qilishdan oldin sizni nimadir chalkashtirib yuborgan bo'lishi mumkin.. nima uchun men "sts" buyrug'ini odatdagi "chiqib ketish" o'rniga TIMSK0 registriga nusxalash uchun ishlatganman?

Meni ko'rganingizda, siz ko'rmagan ko'rsatmalarni ishlatasiz, birinchi navbatda ma'lumotlar sahifasida 616 -sahifaga o'ting. Bu "Ko'rsatmalar to'plamining qisqacha mazmuni". Endi men ishlatgan "STS" ko'rsatmasini toping. Unda aytilishicha, bu R reestridan (biz R16 ishlatganmiz) va "SRAMga to'g'ridan -to'g'ri saqlash" k manzilidan raqamni oladi (bizning holatimizda TIMSK0 tomonidan berilgan). Xo'sh, nega biz TIMSK0 -da saqlash uchun 2 soatlik tsiklga ega bo'lgan "sts" dan foydalanishimiz kerak edi (jadvalning oxirgi ustuniga qarang) va oldin TCCR0B -da saqlash uchun faqat bitta soat tsikliga ega bo'lgan "chiqish" kerak edi? Bu savolga javob berish uchun biz 614 -betdagi ro'yxatga olish jadvalining jadvaliga qaytishimiz kerak. Siz ko'rasiz, TCCR0B registri 0x25 manzilda, lekin (0x45). Bu shuni anglatadiki, bu SRAM -dagi registr, lekin u "port" (yoki kirish -chiqish registri) deb nomlangan ma'lum turdagi registrdir. Agar siz "chiqish" buyrug'i yonidagi ko'rsatmalarni yig'ish jadvaliga qarasangiz, u R16 kabi "ishchi registrlardan" qiymatlarni olib, ularni PORTga yuborishini ko'rasiz. Shunday qilib, biz TCCR0B -ga yozishda "out" dan foydalanishimiz va o'zimizni soat aylanishini saqlab qolishimiz mumkin. Ammo endi ro'yxat jadvalidan TIMSK0 ni qidiring. Siz uning 0x6e manziliga ega ekanligini ko'rasiz. Bu portlar doirasidan tashqarida (bu faqat SRAM -ning birinchi 0x3F joylari) va shuning uchun siz sts buyrug'ini ishlatishga va uni bajarish uchun ikkita CPU soat tsiklini bajarishga qaytishingiz kerak. Iltimos, hozir 615 -betdagi ko'rsatmalarni qisqacha jadvalining oxiridagi 4 -eslatmani o'qing. E'tibor bering, PORTD kabi barcha kirish va chiqish portlarimiz jadvalning pastki qismida joylashgan. Masalan, PD4-0x0b manzilidagi 4 bit (endi siz sharhlanmagan kodimdagi barcha 0x0b narsalar qayerdan kelganini ko'rasiz!).. mayli, tez savol: "sts" ni "tashqariga" o'zgartirdingizmi va nima bo'lganini sodir bo'ladimi? Bizning falsafani eslang! sindirib tashla! shunchaki so'zlarimni qabul qilmang.

Xo'sh, davom etishdan oldin, bir daqiqaga ma'lumotlar sahifasining 19 -sahifasiga o'ting. Siz ma'lumotlar xotirasi (SRAM) rasmini ko'rasiz. SRAM -dagi birinchi 32 ta registr (0x0000 dan 0x001F gacha) R0 dan R31 gacha bo'lgan "umumiy maqsadli ishchi registrlar" bo'lib, biz har doim o'z kodimizda o'zgaruvchi sifatida foydalanamiz. Keyingi 64 ta registr-bu 0x005f gacha bo'lgan kirish-chiqish portlari (ya'ni, biz aytganlar, ro'yxat jadvalida ularning yonida qavssiz manzillar bor, biz "sts" o'rniga "out" buyrug'idan foydalanishimiz mumkin) SRAMning keyingi bo'limi 0x00FF manziligacha bo'lgan umumiy jadvaldagi boshqa barcha registrlarni o'z ichiga oladi, qolganlari esa ichki SRAM. Keling, bir soniya uchun 12 -betga o'taylik. U erda biz doimo o'zgaruvchilar sifatida ishlatadigan "umumiy maqsadli ishchi registrlar" jadvalini ko'rasiz. Siz R0 dan R15 gacha, keyin R16 dan R31 gacha bo'lgan qalin chiziqni ko'rasizmi? Shuning uchun biz har doim R16-ni eng kichigi sifatida ishlatamiz va men keyingi darsda unga biroz ko'proq kiraman, bu erda bizga uchta 16-bitli bilvosita manzil registrlari kerak bo'ladi, X, Y va Z. bunga hozircha kiring, chunki bizga hozir kerak emas va biz bu erda etarlicha botib qolganmiz.

Ma'lumotlar sahifasining bir sahifasini 11 -sahifaga qaytaring. Siz SREG registrining diagrammasini o'ng yuqori burchakda ko'rasizmi? Ko'ryapsizmi, bu registrning 7 -biti "Men" deb nomlangan. Endi sahifaga o'ting va Bit 7 tavsifini o'qing. vajjaj! Bu global uzilishni yoqish biti. Yuqoridagi diagrammadagi ikkinchi qarorni qabul qilish va dasturimizda taymer/hisoblagichning to'lib -toshishiga to'sqinlik qilish uchun biz shunday sozlashimiz kerak. Shunday qilib, bizning dasturimizning keyingi qatori quyidagicha o'qilishi kerak:

sbi SREG, men

bu SREG registrida "I" deb nomlangan bitni o'rnatadi. Biroq, biz ko'rsatmalarni ishlatdik

sei

uning o'rniga Bu bit dasturlarda shunchalik tez o'rnatiladiki, ular buni oddiy yo'l bilan qilishgan.

Xop! Endi bizda "jmp overflow_handler" har safar sodir bo'lganda bajarilishi uchun ortiqcha uzilishlar tayyor.

Davom etishdan oldin, SREG registrini (Status Register) tezda ko'rib chiqing, chunki bu juda muhim. Bayroqlarning har biri nimani anglatishini o'qing. Xususan, biz ishlatadigan ko'plab ko'rsatmalar har doim bu bayroqlarni o'rnatadi va tekshiradi. Masalan, keyinchalik biz "CPI" buyrug'idan foydalanamiz, bu "darhol solishtirish" degan ma'noni anglatadi. Ushbu ko'rsatma uchun ko'rsatmalarni qisqacha jadvalini ko'rib chiqing va "bayroqlar" ustunida qancha bayroq o'rnatilganligini bilib oling. Bularning barchasi SREG -dagi bayroqlar va bizning kodimiz ularni o'rnatadi va ularni doimiy tekshirib turadi. Tez orada misollarni ko'rasiz. Nihoyat, kodning ushbu bo'limining oxirgi qismi:

clr temp

TCNT0 tashqarisida, DDRD 4, temp sbi

Bu erda oxirgi satr juda aniq. Bu PortD uchun ma'lumotlar yo'nalishi registrining 4 -bitini o'rnatadi, bu PD4 -ni chiqishiga olib keladi.

Birinchisi, o'zgarmaydigan tempni nolga o'rnatadi va keyin uni TCNT0 registriga ko'chiradi. TCNT0 - bu bizning taymerimiz/hisoblagichimiz0. Bu uni nolga o'rnatadi. Kompyuter bu satrni bajarishi bilan taymer0 noldan boshlanadi va har soniyada 15625 marta hisoblab chiqadi. Muammo shundaki: TCNT0-"8 bitli" registr, to'g'rimi? Xo'sh, 8-bitli registrda saqlanishi mumkin bo'lgan eng katta raqam nima? Xo'sh, 0b11111111. Bu 0xFF raqami. Qaysi 255. Xo'sh, nima bo'lishini ko'ryapsizmi? Taymer sekundiga 15625 marta ko'payadi va har safar 255 ga yetganda "to'lib ketadi" va yana 0 ga qaytadi. Nolga qaytganda, u Taymerni to'ldirish uzilishi signalini yuboradi. Kompyuter buni oladi va hozircha nima qilayotganini bilasizmi? Ha. U 0x0020 dastur xotirasi manziliga o'tadi va u erda topilgan ko'rsatmani bajaradi.

Ajoyib! Agar siz hali ham men bilan bo'lsangiz, demak siz tinimsiz qahramonsiz! Davom etamiz…

6 -qadam: To'ldirish ishlovchisi

Keling, taymer/counter0 registri faqat to'lib ketgan deb taxmin qilaylik. Biz bilamizki, dastur uzilish signalini oladi va 0x0020 ni bajaradi, bu dastur hisoblagichiga, kompyuterga "overflow_handler" yorlig'iga o'tishni aytadi, biz bu yorliqdan keyin yozgan kodimiz:

overflow_handler:

inc overflows cpi overflows, 61 brne PC+2 clr overflows reti

U qiladigan birinchi narsa - "to'lib toshish" o'zgaruvchisini ko'paytirish (bu bizning umumiy maqsadli R17 ishchi registri) va keyin to'lg'azish tarkibini 61 raqami bilan "taqqoslaydi". Cpi buyrug'ining ishlash usuli shunchaki ayirishdir. ikkita raqam va agar natija nol bo'lsa, u SREG registrida Z bayrog'ini o'rnatadi (men sizga aytardimki, biz bu registrni doim ko'rib turamiz). Agar ikkita raqam teng bo'lsa, Z bayrog'i 1 bo'ladi, agar ikkita raqam teng bo'lmasa, u 0 bo'ladi.

Keyingi qatorda "brne PC+2" yozilgan, bu "teng bo'lmasa filial" degan ma'noni anglatadi. Asosan, u SREG -dagi Z bayrog'ini tekshiradi va agar u bitta bo'lmasa (ya'ni, ikkita raqam teng bo'lmasa, nol bayroq o'rnatilsa), shaxsiy kompyuter PC+2 ga o'tadi, ya'ni u keyingi o'tkazib yuboriladi. chiziq va to'g'ridan -to'g'ri "reti" ga o'tadi, u uzilishdan kodni joyiga qaytadi. Agar brne ko'rsatmasi nol bayroqchada 1 ni topsa, u shoxlamaydi va uning o'rniga keyingi satrda davom etadi.

Bularning barchasi qanday natijaga olib keladi?

Ko'ryapmizki, har safar taymer oshib ketganda, bu ishlovchi "to'lib toshish" qiymatini birdaniga oshiradi. Shunday qilib, "toshib ketish" o'zgarmaydigan to'lqinlar sonini hisoblab chiqadi. Qachonki raqam 61 ga yetsa, biz uni nolga qaytaramiz.

Endi nega biz dunyoda bunday qilardik?

Ko'ramiz. Eslatib o'tamiz, bizning protsessorimiz uchun soat tezligi 16 MGts ni tashkil qiladi va biz uni TCCR0B yordamida "oldindan o'lchaganmiz", shuning uchun taymer faqat soniyada 15625 soniya o'ngda sanaladimi? Va har safar taymer 255 raqamiga yetganda, u toshib ketadi. Demak, u sekundiga 15625/256 = 61,04 marta oshib ketadi. Biz to'lqinlar sonini o'zgarmaydigan "to'lqinlar" bilan kuzatib boramiz va bu raqamni 61 bilan taqqoslaymiz. Demak, "to'kish" har soniyada bir marta 61 ga teng bo'ladi! Shunday qilib, bizning ishlovchi har soniyada bir marta "to'lib toshish" ni nolga qaytaradi. Shunday qilib, agar biz "to'lib toshish" o'zgaruvchisini kuzatib boradigan bo'lsak va u har safar nolga qaytganini hisobga olsak, biz real vaqtda soniya soniya hisoblab chiqardik (E'tibor bering, keyingi darsda biz qanday aniqroq bo'lishini ko'rsatamiz. millisekundlarda kechikish, xuddi Arduino "kechiktirish" tartibi qanday ishlaydi).

Endi biz taymerni to'ldirish uzilishlarini "ko'rib chiqdik". Bu qanday ishlashini tushunganingizga ishonch hosil qiling va keyin biz bu haqiqatdan foydalanadigan keyingi bosqichga o'tamiz.

7 -qadam: kechiktirish

Endi biz ko'rdikki, "overflow_handler" taymerining to'lg'azish to'xtatuvchisi tartibini "to'kish" o'zgaruvchisini soniyada bir marta nolga o'rnatamiz, biz bu faktdan "kechikish" kichik dasturini loyihalashda foydalanishimiz mumkin.

Kechikishimiz ostida quyidagi kodni ko'rib chiqing: yorliq

kechikish:

clr overflows sec_count: cpi overflows, 30 brne sec_count ret

Biz har safar dasturni kechiktirish kerak bo'lganda, bu kichik dasturni chaqiramiz. Uning ishlash usuli shundaki, u avval "to'lib toshish" o'zgaruvchisini nolga o'rnatadi. Keyin u "sec_count" deb nomlangan maydonga kiradi va to'lg'azishlarni 30 bilan taqqoslaydi, agar ular teng bo'lmasa, sek_count yorlig'iga qaytadi va yana va yana taqqoslaydi va ular oxirigacha teng bo'lguncha. bizning taymerda uzilishlarni boshqaruvchi o'zgaruvchan to'lqinlarni oshirishni davom ettirmoqda, shuning uchun biz har safar bu erga borganimizda o'zgaradi. Oxir -oqibat to'lqinlar 30 ga teng bo'lsa, u pastadirdan chiqadi va biz kechikish deb nomlangan joyga qaytadi: aniq natija 1/2 soniya kechikish

2 -mashq: overflow_handler tartibini quyidagicha o'zgartiring:

overflow_handler:

Inc reti -dan oshib ketadi

va dasturni ishga tushiring. Boshqa narsa bormi? Nega yoki nima uchun?

8 -qadam: Ko'z oching

Nihoyat, miltillash tartibini ko'rib chiqaylik:

miltillash:

sbi PORTD, 4 chaqiruv kechikishi cbi PORTD, 4 rcall kechikish rjmp milt -milt

Avval biz PD4 -ni yoqamiz, keyin kechikish dasturini chaqiramiz. Biz rcall -dan foydalanamiz, shunda kompyuter "ret" so'zini olganda, u rcall -dan keyingi qatorga qaytadi. Keyin biz ko'rib turganimizdek, to'lg'azish o'zgaruvchisida 30 ta kechikish tartibi kechiktiriladi va bu deyarli 1/2 soniya, keyin biz PD4ni o'chirib qo'yamiz, yana 1/2 soniyani kechiktiramiz va yana boshiga qaytamiz.

Aniq natija - miltillovchi LED!

O'ylaymanki, endi siz "miltillash" assambleyadagi eng yaxshi "salom dunyo" dasturi emasligiga qo'shilasiz.

Mashq 3: Dasturdagi turli parametrlarni shunday o'zgartiringki, LED har xil tezlikda sekundiga 4 marta yonib tursin va hokazo. 4 -mashq: LEDni har xil vaqt yonishi va o'chishi uchun o'zgartiring. Masalan, 1/4 soniya yoniq va keyin 2 soniya yoki shunga o'xshash. 5 -mashq: TCCR0B soatini tanlash bitlarini 100 ga o'zgartiring va keyin stolga ko'tarilishni davom ettiring. Qaysi vaqtda 1 -darslik "hello.asm" dasturidan farq qilmaydi? 6 -mashq (ixtiyoriy): Agar sizda 4 MGts yoki 13,5 MGts yoki boshqa kristalli osilator bo'lsa, 16 MGtsli osilatorni o'zgartiring. non panelida yangisini ko'ring va bu LEDning miltillash tezligiga qanday ta'sir qilishini ko'ring. Endi siz aniq hisob -kitoblarni amalga oshirishingiz va bu stavkaga qanday ta'sir qilishini oldindan bilib olishingiz kerak.

9 -qadam: Xulosa

Sizni o'ldirganlar uchun, tabriklaymiz!

Men o'qish va tajriba o'tkazishdan ko'ra ko'proq o'qish va yuqoriga qarab turish juda qiyin ekanligini tushunaman, lekin umid qilamanki, siz quyidagi muhim narsalarni o'rgandingiz:

  1. Dastur xotirasi qanday ishlaydi
  2. SRAM qanday ishlaydi
  3. Registrlarni qanday qidirish kerak
  4. Qanday qilib ko'rsatmalarni ko'rib chiqish va ular nima qilayotganini bilish
  5. To'xtatishni qanday amalga oshirish kerak
  6. CP kodni qanday bajaradi, SREG qanday ishlaydi va uzilishlar paytida nima bo'ladi
  7. Qanday qilib looplar, sakrashlar va kodda sakrash kerak
  8. Ma'lumotlar varag'ini o'qish qanchalik muhim!
  9. Atmega328p mikrokontroller uchun bularning barchasini qanday qilishni bilganingizdan so'ng, bu sizni qiziqtirgan har qanday yangi tekshirgichlarni o'rganish uchun nisbiy tortishish bo'ladi.
  10. Qanday qilib CPU vaqtini real vaqtga o'zgartirish va uni kechiktirish tartibida ishlatish kerak.

Endi bizda juda ko'p nazariyalar mavjud bo'lib, biz yaxshiroq kod yozish va murakkab narsalarni boshqarish imkoniyatiga egamiz. Shunday qilib, keyingi darsda biz aynan shunday qilamiz. Biz murakkabroq, qiziqroq sxemani tuzamiz va uni qiziqarli yo'llar bilan boshqaramiz.

7 -mashq: Kodni turli yo'llar bilan "sindirish" va nima bo'lishini ko'ring! Ilmiy qiziquvchan chaqaloq! Boshqa kimdir idishlarni to'g'ri yuva oladimi? 8-mashq: ro'yxat faylini yaratish uchun "-l" variantidan foydalanib kodni yig'ing. Ya'ni "avra -l blink.lst blink.asm" va ro'yxat faylini ko'rib chiqing. Qo'shimcha kredit: Men boshida bergan sharhlanmagan kod va keyinchalik muhokama qilinadigan sharhlangan kod farq qiladi! Kodning bir qatori boshqacha. Topa olasizmi? Nega bu farq muhim emas?

Umid qilamanki, siz xursand bo'ldingiz! Keyingi safar ko'rishguncha…

Tavsiya: