Агуулгын хүснэгт:

AVR Assembler заавар 3: 9 алхам
AVR Assembler заавар 3: 9 алхам

Видео: AVR Assembler заавар 3: 9 алхам

Видео: AVR Assembler заавар 3: 9 алхам
Видео: Замена отопления в новостройке. Подключение. Опрессовка. #17 2024, Долдугаар сарын
Anonim
AVR ассемблерийн заавар 3
AVR ассемблерийн заавар 3

3 -р хичээлд тавтай морилно уу!

Эхлэхээсээ өмнө философийн нэг зүйлийг хэлмээр байна. Эдгээр зааварчилгаанд бидний үүсгэж буй схемүүд болон кодыг туршиж үзэхээс бүү ай. Ойролцоох утсыг сольж, шинэ бүрэлдэхүүн хэсгүүдийг нэмж, бүрэлдэхүүн хэсгүүдийг гаргаж, кодын мөрүүдийг өөрчилж, шинэ мөр нэмж, мөрүүдийг устгаад юу болохыг хараарай! Аливаа зүйлийг эвдэх нь маш хэцүү бөгөөд хэрэв та эвдэх юм бол хэнд хамаатай юм бэ? Бидний ашиглаж байгаа зүйл, түүний дотор микроконтроллер нь маш үнэтэй биш бөгөөд бүх зүйл хэрхэн бүтэлгүйтэх нь үргэлж сургамжтай байдаг. Дараагийн удаа юу хийх ёсгүйг олж мэдээд зогсохгүй, хамгийн гол нь яагаад хийхгүй байгаагаа мэдэх болно. Хэрэв та надтай адилхан хүн байсан бол, та хүүхэд байхдаа шинэ тоглоом авч байхдаа удалгүй түүнийг хэсэг хэсгээр нь худалдаж авснаар юу зөв оногдсоныг олж мэдэв үү? Заримдаа тоглоомыг нөхөж баршгүй эвдэрч гэмтсэн ч тийм ч их асуудал үүсгэхгүй. Хүүхдийг сониуч зангаа хугарсан тоглоом хүртэл судлахыг зөвшөөрөх нь түүнийг аяга таваг угаагчийн оронд эрдэмтэн эсвэл инженер болгон хувиргадаг.

Өнөөдөр бид маш энгийн хэлхээг холбож, дараа нь онолын хувьд жаахан хүндрэх болно. Уучлаарай, гэхдээ бидэнд багаж хэрэгсэл хэрэгтэй байна! Бид үүнийг 4 -р хичээл дээр нөхөх болно гэж амлаж байна, энд бид илүү ноцтой хэлхээний ажил хийх бөгөөд үр дүн нь үнэхээр гайхалтай байх болно. Гэсэн хэдий ч эдгээр бүх хичээлийг хийх арга нь маш удаан, тунгаан бодох байдлаар хийгддэг. Хэрэв та зүгээр л хагалж, хэлхээг бүтээж, кодыг хуулж буулгаад дараа нь ажиллуулбал энэ нь ажиллах болно, гэхдээ та юу ч сурахгүй. Та мөр бүрийн талаар бодох хэрэгтэй. Түр зогсоох. Туршилт. Зохион бүтээх. Хэрэв та үүнийг ингэж хийвэл 5 -р хичээлийн төгсгөлд та гайхалтай зүйл бүтээхээ больж, нэмэлт сургалт шаардлагагүй болно. Үгүй бол та сурч, бүтээхээс илүү зүгээр л харж байна.

Ямар ч тохиолдолд хангалттай философи, эхэлцгээе!

Энэхүү гарын авлагад танд хэрэгтэй болно:

  1. таны загварчлалын самбар
  2. LED
  3. холбох утас
  4. 220-330 ом орчим эсэргүүцэл
  5. Зааварчилгааны гарын авлага: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. Мэдээллийн хуудас: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. өөр болор осциллятор (заавал биш)

Хичээлүүдийн бүрэн цуглуулгын линк энд байна:

Алхам 1: Хэлхээ байгуулах

Хэлхээ байгуулах
Хэлхээ байгуулах

Энэхүү гарын авлага дахь схем нь маш энгийн. Бид үндсэндээ "анивчих" програм бичих гэж байгаа тул бидэнд хэрэгтэй зүйл бол дараахь зүйл юм.

LED -ийг PD4, дараа нь 330 ом эсэргүүцэлтэй, дараа нь газардуул. өөрөөр хэлбэл

PD4 - LED - R (330) - GND

тэгээд л боллоо!

Энэ онол нь хүнд хэцүү байх болно …

Алхам 2: Бидэнд яагаад тайлбар, M328Pdef.inc файл хэрэгтэй байна вэ?

Нэвтрэх файл, тайлбар яагаад хэрэгтэй байгааг харуулахаас эхлэх хэрэгтэй гэж би бодож байна. Тэдгээрийн аль нь ч шаардлагагүй бөгөөд та кодыг тэдгээргүйгээр бичих, угсрах, байршуулах боломжтой бөгөөд энэ нь маш сайн ажиллах болно (хэдийгээр файл оруулахгүйгээр та угсрагчаас зарим гомдол хүлээж авах боломжтой боловч алдаа гардаггүй)

Энд би өнөөдөр бичих гэж байгаа код байна, гэхдээ би сэтгэгдэл болон оруулах файлыг хассан болно.

.төхөөрөмж ATmega328P

.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: sbi 0x04 b: sbi 0x04 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

үнэхээр энгийн, тийм үү? Хаха Хэрэв та энэ файлыг угсарч, байршуулсан бол LED нь секундэд 1 удаа анивчихад 1/2 секундын турш анивчих бөгөөд 1/2 секундын хооронд түр зогсоох болно.

Гэсэн хэдий ч энэ кодыг харахад гэгээрүүлэх нь бараг боломжгүй юм. Хэрэв та ингэж код бичих байсан бол ирээдүйд үүнийг өөрчлөх эсвэл дахин ашиглахыг хүсч байвал танд хэцүү байх болно.

Тиймээс сэтгэгдлээ тавьж, файлыг буцааж оруулснаар үүнийг ойлгох боломжтой болно.

Алхам 3: Blink.asm

Өнөөдөр бидний хэлэлцэх код энд байна:

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

; бичсэн: 1o_o7; огноо:; хувилбар: 1.0; файлыг дараах байдлаар хадгалсан: blink.asm; AVR -ийн хувьд: atmega328p; цагийн давтамж: 16MHz (заавал биш); **********************************; Хөтөлбөрийн функц: ---------------------; LED анивчихад хэдэн секунд тоолох;; PD4 - LED - R (330 ом) - GND;; --------------------------------------.nolist.include "./m328Pdef.inc".list; ==============; Тунхаглал:.def temp = r16.def overflows = r17.org 0x0000; санах ойн (PC) дахин тохируулагчийн байршил rjmp Дахин тохируулах; jmp нь 2 cpu цикл, rjmp нь зөвхөн 1; хэрэв та 8 к байтаас дээш үсрэх шаардлагагүй бол; танд зөвхөн rjmp хэрэгтэй. Тиймээс зарим микроконтроллерууд зөвхөн; rjmp байх ба jmp биш.org 0x0020; Timer0 халих зохицуулагчийн санах ойн байршил rjmp overflow_handler; timer0 халих тасалдал гарсан тохиолдолд энд очих; ============ Reset: ldi temp, 0b00000101 out TCCR0B, temp; Clock Selector Bits CS00, CS01, CS02 -ийг 101 болгож тохируулах; энэ нь Timer Counter0, TCNT0 -ийг FCPU/1024 горимд оруулдаг; тиймээс энэ нь CPU -ийн давтамж/1024 ldi temp, 0b00000001 sts TIMSK0, temp -ийг шалгадаг; Timer Overflow Interrupt Enable (TOIE0) битийг тохируулах; Таймер тасалдлын маскын бүртгэлийн бүртгэл (TIMSK0) sei; дэлхийн тасалдлыг идэвхжүүлэх - "sbi SREG, I" clr temp out TCNT0, temp; таймер/тоолуурыг 0 sbi DDRD, 4 болгон эхлүүлэх; PD4 -ийг гаралтанд тохируулах; =====================; Програмын үндсэн хэсэг: анивчих: sbi PORTD, 4; PD4 дуудлагын саатал дээр LED асаах; саатал 1/2 секундын cbi байх болно PORTD, 4; PD4 дуудлагын саатал дээр LED унтраах; саатал 1/2 секундын rjmp анивчих болно; эхлэх саатал руу буцах давталт: clr overflows; халих хэмжээг 0 sec_count болгож тохируулах: cpi overflows, 30; халих тоо болон 30 brne sec_count -ийг харьцуулах; тэнцүү биш бол салбар руу буцах sec_count; хэрэв 30 халалт үүссэн бол буцаж анивчлаа. overflow_handler: inc overflows; халих хувьсагч cpi халих 1 -ийг нэмнэ, 61; 61 brne PC+2 -той харьцуулах; Програмын тоолуур + 2 (дараагийн мөрийг алгасах), хэрэв тэнцүү биш бол clr халих; хэрэв 61 удаа халих тохиолдол гарвал тоолуурыг тэг сүлжээнд дахин тохируулах; тасалдалаас буцах

Таны харж байгаагаар миний сэтгэгдлүүд одоо арай товч байна. Зааварчилгааны багц дахь ямар командууд байгааг бид мэдсэний дараа үүнийг тайлбар дээр тайлбарлах шаардлагагүй болно. Бид юу болж байгааг хөтөлбөрийн үүднээс л тайлбарлах хэрэгтэй.

Энэ бүхэн юу хийдэг талаар бид хэсэгчлэн ярилцах болно, гэхдээ эхлээд дэлхийн өнцгөөс харахыг хичээцгээе. Хөтөлбөрийн үндсэн хэсэг нь дараах байдлаар ажилладаг.

Эхлээд бид PORTD -ийн 4 -р битийг "sbi PORTD, 4" -ээр тохируулсан бөгөөд энэ нь 1 -ийг PD4 рүү илгээдэг бөгөөд энэ зүү дээрх хүчдэлийг 5V болгоно. Энэ нь LED асах болно. Дараа нь бид "хоцрогдох" дэд програм руу шилжиж, 1/2 секундыг тооцдог (үүнийг яаж хийхийг дараа нь тайлбарлах болно). Дараа нь бид PORTD дээр анивчдаг 4 -р бит рүү буцаж очдог бөгөөд энэ нь PD4 -ийг 0V болгож, улмаар LED -ийг унтраана. Дараа нь бид дахин 1/2 секундын турш хойшлуулж, дараа нь "rjmp анивчих" -аар дахин анивчих эхлэл рүү буцна.

Та энэ кодыг ажиллуулж, энэ нь хийх ёстой зүйлээ хийж байгааг харах ёстой.

Тэнд танд байна! Энэ бол физик байдлаар хийдэг бүх код юм. Микроконтроллерын хийж буй дотоод механикууд арай илүү оролцдог тул бид энэ хичээлийг хийж байна. Тиймээс хэсэг бүрийг ээлжлэн хэлэлцье.

Алхам 4:.org Ассемблерын удирдамж

Өмнөх хичээлүүдээс.nolist,.list,.include,.def ассемблерийн удирдамж юу хийдэгийг бид аль хэдийн мэддэг болсон тул эхлээд дараа нь гарч ирэх 4 мөрийн кодыг авч үзье.

.org 0x0000

jmp Reset.org 0x0020 jmp overflow_handler

. Org мэдэгдэл нь ассемблерт "Програмын санах ой" хэсэгт дараагийн мэдэгдлийг хаана оруулахыг хэлдэг. Таны програмыг ажиллуулж байх үед "Програмын тоолуур" (PC хэлбэрээр хураангуйлагдсан) нь одоо хэрэгжиж буй мөрийн хаягийг агуулдаг. Тиймээс, энэ тохиолдолд компьютер 0x0000 байх үед санах ойн байршилд байрлах "jmp Reset" командыг харах болно. Энэ байршилд jmp Reset хийхийг хүссэн шалтгаан нь програм эхлэх эсвэл чипийг дахин тохируулах үед компьютер энэ цэг дээр код ажиллуулж эхэлдэгтэй холбоотой юм. Тиймээс, бидний харж байгаагаар бид үүнийг "Дахин тохируулах" гэсэн хэсэг рүү нэн даруй "үсрэх" гэж хэлсэн. Бид яагаад үүнийг хийсэн юм бэ? Энэ нь дээрх сүүлийн хоёр мөрийг алгасаж байна гэсэн үг юм! Яагаад?

Эндээс л бүх зүйл сонирхолтой болдог. Та одоо энэ гарын авлагын эхний хуудсан дээр зааж өгсөн ATmega328p өгөгдлийн хүснэгт бүхий pdf үзүүлэгчийг нээх хэрэгтэй болно (ийм учраас "танд хэрэгтэй болно" хэсгийн 4 -р зүйл байна). Хэрэв таны дэлгэц хэт жижиг, эсвэл танд хэт олон цонх нээгдсэн бол (миний хувьд) миний хийж байгаа зүйлийг Ereader эсвэл Андройд утсан дээрээ хийж болно. Хэрэв та угсрах код бичихээр төлөвлөж байгаа бол үүнийг үргэлж ашиглах болно. Хамгийн гайхалтай зүйл бол бүх микроконтроллерууд ижил төстэй байдлаар зохион байгуулагдсан байдаг тул та өгөгдлийн хүснэгтийг уншиж, кодлоход дасаж эхэлмэгц өөр микроконтроллерын хувьд үүнийг хийх нь бараг л утгагүй болно. Тиймээс бид зөвхөн atmega328p биш харин бүх микроконтроллерыг хэрхэн ашиглахыг сурч байна.

За, мэдээллийн хүснэгтийн 18-р хуудсыг үзээд 8-2-р зургийг үзнэ үү.

Микроконтроллер дахь Програмын санах ойг ингэж тохируулдаг. Энэ нь 0x0000 хаягаар эхэлж, хоёр хэсэгт хуваагдсан болохыг та харж байна. програмын флаш хэсэг болон ачаалах флаш хэсэг. Хэрэв та 277-р хүснэгт 27-14-ийг товчхон үзвэл програмын флаш хэсэг нь 0x0000-аас 0x37FF хүртэлх хэмжээтэй, ачаалах флаш хэсэг нь 0x3800-аас 0x3FFF хүртэлх үлдсэн байршлыг эзэлдэг болохыг харах болно.

Дасгал 1: Програмын санах ойд хэдэн байршил байдаг вэ? Өөрөөр хэлбэл 3FFF -ийг аравтын бутархай болгон хөрвүүлж, 0 -ээр тоолж эхэлснээс хойш 1 -ийг нэмнэ үү. Санах ойн байршил бүр 16 бит (эсвэл 2 байт) өргөнтэй байдаг тул санах ойн нийт байтын тоо хэд вэ? Одоо үүнийг килобайт болгон хөрвүүл, нэг килобайтад 2^10 = 1024 байт байдгийг санаарай. Ачаалах флаш хэсэг нь 0x3800 -аас 0x37FF хооронд хэлбэлздэг, энэ хэдэн килобайт вэ? Програмаа хадгалахын тулд хэдэн килобайт санах ой үлдсэн бэ? Өөрөөр хэлбэл, манай хөтөлбөр хэр том байж болох вэ? Эцэст нь хэлэхэд бид хэдэн мөр кодтой байж болох вэ?

За, одоо бид флэш програмын санах ойн зохион байгуулалтын талаар бүх зүйлийг мэдэж байгаа тул.org мэдэгдлийн талаар үргэлжлүүлэн ярилцъя. Санах ойн анхны байршил 0x0000 нь Reset гэж нэрлэсэн хэсэг рүүгээ орох зааварчилгаа агуулсан болохыг бид харж байна. Одоо бид ".org 0x0020" мэдэгдэл юу хийж байгааг харж байна. Дараагийн мөрийн зааврыг санах ойн 0x0020 байршилд байрлуулахыг бид хүсч байна. Бидний оруулсан заавар бол манай кодын "overflow_handler" гэж бичсэн хэсэг рүү шилжих явдал юм … яагаад бид энэ үсрэлтийг 0x0020 санах ойн байршилд байрлуулахыг шаардах болов? Үүнийг мэдэхийн тулд бид мэдээллийн хүснэгтийн 65-р хуудсыг үзээд 12-6-р хүснэгтийг үзнэ үү.

Хүснэгт 12-6 нь "Дахин тохируулах, таслах" хүснэгт бөгөөд "тасалдал" хүлээн авснаар компьютер яг хаашаа явахыг харуулав. Жишээлбэл, хэрэв та Векторын дугаар 1-ийг үзвэл тасалдлын "эх үүсвэр" нь "RESET" бөгөөд үүнийг "Гадаад зүү, асаалттай дахин тохируулах, хүрэн гарч дахин тохируулах, харуулын системийг дахин тохируулах" гэсэн утгатай бөгөөд хэрэв байгаа бол Манай микроконтроллерт ийм зүйл тохиолддог бол компьютер 0x0000 програмын санах ойн байршилд манай програмыг ажиллуулж эхэлдэг. Тэгвэл манай.org удирдамжийн талаар юу хэлэх вэ? Бид 0x0020 санах ойн байршилд командыг байрлуулсан бөгөөд хэрэв та хүснэгтийг доошоо харвал Timer/Counter0 -ийн халих тохиолдол гарвал (TIMER0 OVF -ээс ирдэг) 0x0020 байршилд байгаа бүх зүйлийг гүйцэтгэх болно. Ийм зүйл тохиолдоход компьютер бидний "overflow_handler" гэж тэмдэглэсэн цэг рүү үсрэх болно. Хөргөх үү? Та яагаад үүнийг хийснийг нэг минутын дараа харах болно, гэхдээ эхлээд энэ хичээлийн алхамыг хажуу тийш нь дуусгая.

Хэрэв бид кодоо илүү цэгцтэй, эмх цэгцтэй болгохыг хүсч байгаа бол одоо хэлэлцэж буй 4 мөрийг дараах байдлаар солих ёстой (66 -р хуудсыг үзнэ үү):

.org 0x0000

rjmp дахин тохируулах; PC = 0x0000 рети; PC = 0x0002 рети; PC = 0x0004 рети; PC = 0x0006 тор; PC = 0x0008 рети; PC = 0x000A… reti; PC = 0x001E jmp overflow_handler: PC = 0x0020 reti: PC = 0x0022… reti; PC = 0x0030 рети; PC = 0x0032

Тиймээс, хэрэв тасалдал гарсан бол энэ нь "тасалдалаас буцах" гэсэн утгатай "reti" болно, өөр юу ч болохгүй. Гэхдээ хэрэв бид эдгээр янз бүрийн тасалдлыг хэзээ ч "идэвхжүүлээгүй" бол тэдгээрийг ашиглахгүй бөгөөд бид эдгээр цэгүүдэд програмын кодыг оруулах боломжтой болно. Одоогийн "blink.asm" хөтөлбөрт бид зөвхөн timer0 халих тасалдлыг идэвхжүүлэх болно (мөн мэдээж үргэлж идэвхждэг дахин тохируулах тасалдал), тиймээс бид бусадтай санаа зовохгүй байх болно.

Дараа нь бид timer0 халих тасалдлыг хэрхэн "идэвхжүүлэх" вэ? … энэ бол энэ хичээлийн дараагийн алхам юм.

Алхам 5: Таймер/Тоолуур 0

Таймер/Тоологч 0
Таймер/Тоологч 0

Дээрх зургийг үзээрэй. Энэ бол гадны ямар нэгэн нөлөө манай хөтөлбөрийн урсгалыг "тасалдуулах" үед "PC" -ийн шийдвэр гаргах үйл явц юм. Тасалдал гарсан гэсэн дохиог гаднаас авахад хамгийн түрүүнд хийх зүйл бол бид ийм тасалдлын хувьд "тасалдал идэвхжүүлэх" битийг тохируулсан эсэхийг шалгах явдал юм. Хэрэв бид чадаагүй бол энэ нь бидний дараагийн кодын мөрийг үргэлжлүүлэн ажиллуулна. Хэрэв бид тухайн тасалдлын идэвхжүүлэх битийг тохируулсан бол (энэ битийн байрлалд 0 -ийн оронд 1 байх ёстой) энэ нь бид "дэлхийн тасалдал" -ыг идэвхжүүлсэн эсэхийг идэвхжүүлсэн эсэхийг шалгах болно, эс тэгвээс энэ нь дараагийн мөр рүү дахин орох болно. код оруулаад үргэлжлүүлнэ үү. Хэрэв бид дэлхийн тасалдалуудыг идэвхжүүлсэн бол энэ төрлийн тасалдлын програмын санах ойн байршилд очно (Хүснэгт 12-6-д харуулав), тэнд өгсөн бүх тушаалыг гүйцэтгэх болно. Тиймээс энэ бүхнийг коддоо хэрхэн хэрэгжүүлснийг харцгаая.

Манай кодын хаяглагдсан хэсгийг дахин тохируулах нь дараах хоёр мөрөөс эхэлнэ.

Дахин тохируулах:

ldi temp, 0b00000101 гарч TCCR0B, температур

Бидний мэдэж байгаагаар энэ нь 0b00000101 гэсэн тоог шууд дагаж мөрддөг. Дараа нь энэ дугаарыг "out" командыг ашиглан TCCR0B нэртэй бүртгэлд бичнэ. Энэ бүртгэл гэж юу вэ? Мэдээллийн хүснэгтийн 614 -р хуудас руу орцгооё. Энэ нь бүх бүртгэлийг нэгтгэсэн хүснэгтийн дунд байна. 0x25 хаяг дээр та TCCR0B -ийг олох болно. (Миний тайлбарлаагүй кодын хувилбарт "0x25, r16" гэсэн мөр хаанаас гарсныг та одоо мэдэж байна). Дээрх кодын сегментээс бид 0 -р бит, 2 -р битийг тохируулаад бусад бүх зүйлийг цэвэрлэсэн болохыг харж байна. Хүснэгтээс харахад энэ нь бид CS00 ба CS02 -ийг тохируулсан гэсэн үг юм. Одоо өгөгдлийн хүснэгтийн "8 битийн таймер/ХОУХ-той Counter0" гэсэн бүлэг рүү шилжье. Ялангуяа тэр бүлгийн 107 -р хуудас руу орно уу. Бүртгэлийн хураангуй хүснэгтэд бидний харсан "Таймер/Тоолуурын хяналтын бүртгэл В" (TCCR0B) бүртгэлийн ижил тайлбарыг та харах болно (тиймээс бид энд шууд ирж болох байсан, гэхдээ хураангуй хүснэгтийг хэрхэн ашиглахыг харахыг би хүссэн юм. ирээдүйн лавлагааны хувьд). Мэдээллийн хүснэгт нь тухайн регистрийн бит тус бүрийн тайлбар, тэдний юу хийж байгааг үргэлжлүүлэн тайлбарлаж өгдөг. Бид одоохондоо энэ бүх зүйлийг алгасаад хуудсыг Хүснэгт 15-9 болгоно. Энэ хүснэгтэд "Цаг сонгох битийн тайлбар" -ыг харуулав. Одоо тэр бүртгэлд бидний оруулсан битүүдтэй тохирох мөрийг олох хүртэл тэр хүснэгтийг доошоо хараарай. Энэ мөрөнд "clk/1024 (урьдчилсан тооцоолуураас)" гэж бичжээ. Энэ нь юу гэсэн үг вэ гэвэл бид Timer/Counter0 (TCNT0) -ийг CPU давтамжийг 1024 -т хуваасан хурдтай байлгахыг хүсч байна. Манай микроконтроллер 16 МГц болор осциллятороор тэжээгддэг тул энэ нь бидний CPU -ийн зааврыг гүйцэтгэдэг хурд гэсэн үг юм. Секундэд 16 сая заавар. Тиймээс манай TCNT0 тоолуурын тэмдэглэх хурд нь секундэд 16 сая/1024 = 15625 удаа болно (өөр өөр цаг сонгож үзээд юу болохыг хараарай - манай философийг санаж байна уу?). 15625 дугаарыг дараа нь оюун ухаандаа хадгалж, дараагийн хоёр мөрийн код руу шилжицгээе.

ldi temp, 0b00000001

sts TIMSK0, температур

Энэ нь TIMSK0 гэж нэрлэгддэг бүртгэлийн 0 -р битийг тогтоож, бусад бүх зүйлийг цэвэрлэнэ. Хэрэв та өгөгдлийн хүснэгтийн 109 -р хуудсыг үзвэл TIMSK0 нь "Timer/Counter Interrupt Mask Register 0" гэсэн утгатай бөгөөд манай код нь "Timer/Counter0 Overflow Interrupt Enable" гэсэн утгатай TOIE0 гэсэн 0 -р битийг тогтоосон болохыг харах болно. … Тэнд! Энэ бүхэн юу болохыг одоо та харж байна. Одоо бид дээд хэсэгт байгаа бидний зурган дээрх анхны шийдвэрээс хүссэн шиг "тасалдах боломжийг олгодог битийн багц" байна. Тиймээс одоо бидний хийх ёстой зүйл бол "дэлхийн тасалдал" -ыг идэвхжүүлэх явдал бөгөөд манай хөтөлбөр ийм төрлийн тасалдалд хариу өгөх боломжтой болно. Бид удалгүй дэлхийн тасалдлыг идэвхжүүлэх болно, гэхдээ үүнийг хийхээсээ өмнө та ямар нэгэн зүйлд эргэлзэж байсан байж магадгүй.. яагаад би "sts" командыг ердийн "гадагшлуулах" биш харин TIMSK0 бүртгэлд хуулахыг хүссэн юм бэ?

Өмнө нь харж байгаагүй зааврыг надтай уулзах болгондоо хийх ёстой хамгийн эхний зүйл бол мэдээллийн хүснэгтийн 616 хуудсыг үзэх явдал юм. Энэ бол "Зааварчилгааны багцын хураангуй" юм. Одоо миний ашиглаж байсан "STS" зааврыг олоорой. Энэ нь R бүртгэл (бид R16 ашигладаг байсан) болон "SRAM руу шууд хадгалах" байршил k (манай тохиолдолд TIMSK0 -ээс өгсөн) дугаарыг авдаг гэж бичсэн байна. Тэгвэл бид яагаад TIMSK0 дээр хадгалахын тулд 2 цагийн мөчлөг шаарддаг (хүснэгтийн сүүлийн баганыг үзнэ үү) "sts" -г ашиглах ёстой байсан бөгөөд өмнө нь TCCR0B -д хадгалахын тулд бидэнд зөвхөн нэг цагийн мөчлөгтэй "out" хэрэгтэй байсан юм бэ? Энэ асуултанд хариулахын тулд бид 614 -р хуудасны бүртгэлийн хураангуй хүснэгт рүү буцах хэрэгтэй. Та TCCR0B бүртгэл 0x25 хаяг дээр (0x45) байгаа эсэхийг харж байна уу? Энэ нь SRAM дахь бүртгэл гэсэн үг боловч "порт" (эсвэл i/o бүртгэл) гэж нэрлэгддэг тодорхой төрлийн бүртгэл юм. Хэрэв та "гарах" командын хажууд байгаа зааварчилгааны хүснэгтийг харвал энэ нь R16 шиг "ажлын бүртгэлүүд" -ээс утгыг авч порт руу илгээдэг болохыг харах болно. Тиймээс бид TCCR0B руу бичихдээ "out" -г ашиглаж, цагийн эргэлтийг хэмнэх боломжтой. Гэхдээ одоо бүртгэлийн хүснэгтээс TIMSK0 -ийг хайж олоорой. Та 0x6e хаягтай болохыг харж байна. Энэ нь портуудын хүрээнээс гадуур (зөвхөн SRAM -ийн анхны 0x3F байршил) бөгөөд ингэснээр та sts командыг ашиглах, CPU -ийн цагийн хоёр мөчлөг хийх хэрэгтэй болно. 615 -р хуудасны зааварчилгааны хүснэгтийн төгсгөлд байгаа Тэмдэглэл 4 -ийг яг одоо уншина уу. PORTD гэх мэт бидний бүх оролт, гаралтын портууд хүснэгтийн доод хэсэгт байрладаг болохыг анхаарна уу. Жишээлбэл, PD4 бол 0x0b хаягийн 4-р бит (одоо миний тайлбарлаагүй кодонд 0x0b бүх зүйл хаанаас ирснийг та харж байна!).. за, хурдан асуулт: та "sts" -ийг "out" болгож өөрчилсөн юу болохыг харсан уу? болдог уу? Бидний философийг санаарай! эвд! Зүгээр л миний үгэнд битгий хандаарай.

За, цааш явахаасаа өмнө өгөгдлийн хүснэгтийн 19 -р хуудсыг нэг минут эргүүлээрэй. Та өгөгдлийн санах ойн (SRAM) зургийг харж байна. SRAM -ийн анхны 32 регистр (0x0000 -аас 0x001F хүртэл) нь R0 -ээс R31 хүртэлх "ерөнхий зориулалтын ажлын бүртгэлүүд" бөгөөд бид кодоо хувьсагч болгон ашигладаг. Дараагийн 64 регистр бол 0x005f хүртэлх I/O портууд (өөрөөр хэлбэл бидний ярьж байсан бүртгэлийн хүснэгтэд хаалтанд ороогүй хаягууд байгаа бөгөөд бид "sts" оронд "out" командыг ашиглаж болно) Эцэст нь SRAM -ийн дараагийн хэсэг нь хураангуй хүснэгтэд 0x00FF хүртэлх бусад бүх бүртгэлийг агуулдаг бөгөөд үлдсэн хэсэг нь дотоод SRAM юм. Одоо хурдан, 12 -р хуудсыг нэг хором эргүүлье. Та энд бидний хувьсагч болгон ашигладаг "ерөнхий зориулалтын ажлын бүртгэлүүд" -ийн хүснэгтийг харж болно. Та R0 - R15, дараа нь R16 - R31 тоонуудын хоорондох зузаан шугамыг харж байна уу? Ийм учраас бид үргэлж R16-ийг хамгийн жижиг нь болгон ашигладаг бөгөөд дараагийн хичээл дээр би үүнийг арай илүү нарийвчлан авч үзэх болно, үүнд бидэнд X, Y, Z гэсэн 16 битийн шууд бус хаягийн гурван регистр хэрэгтэй болно. Үүнийг одоохондоо аваарай, гэхдээ бидэнд одоо хэрэггүй байгаа тул энд хангалттай дарагдсан байна.

Өгөгдлийн хүснэгтийн нэг хуудсыг 11 -р хуудас руу буцаана уу. Та баруун дээд буланд SREG бүртгэлийн диаграмыг харах болно. Бүртгэлийн 7 -р битийг "Би" гэж нэрлэдэгийг та харж байна. Одоо хуудас руу ороод Bit 7 -ийн тайлбарыг уншина уу. за! Энэ бол Global Interrupt Enable бит юм. Дээрх диаграм дээрх хоёр дахь шийдвэрийг давж, манай програмд таймер/тоолуур халих тасалдал гаргахын тулд үүнийг хийх хэрэгтэй. Тиймээс манай програмын дараагийн мөрөнд дараахь зүйлийг унших ёстой.

sbi SREG, би

Энэ нь SREG бүртгэлд "I" гэж нэрлэгддэг битийг тохируулдаг. Гэсэн хэдий ч бид энэ зааврыг ашигласан болно

Сэй

оронд нь Энэ битийг програмуудад маш олон удаа суулгадаг тул үүнийг хийх хялбар аргыг л хийсэн.

За! Одоо бид "jmp overflow_handler" -ийг тохиолдох бүрт гүйцэтгэх болно.

Бид цааш явахаасаа өмнө SREG бүртгэлийг (Status Register) хурдан үзээрэй, учир нь энэ нь маш чухал юм. Туг бүр нь юу илэрхийлж байгааг уншина уу. Ялангуяа бидний ашигладаг олон зааварчилгаа эдгээр тугуудыг байнга тохируулж, шалгаж байх болно. Жишээлбэл, дараа нь бид "шууд харьцуулах" гэсэн утгатай "CPI" командыг ашиглах болно. Энэхүү зааварчилгааны зааварчилгааны хүснэгтийг үзээд "туг" баганад хичнээн туг дарсан болохыг анхаарна уу. Эдгээр нь бүгд SREG дээрх тугууд бөгөөд бидний код нь тэдгээрийг тохируулж, байнга шалгаж байх болно. Та удахгүй жишээг харах болно. Эцэст нь кодын энэ хэсгийн сүүлийн хэсэг нь:

clr temp

гарч TCNT0, temp sbi DDRD, 4

Энд байгаа сүүлийн мөр нь маш тодорхой харагдаж байна. Энэ нь PortD -ийн өгөгдлийн чиглэлийн бүртгэлийн 4 -р битийг PD4 -ийг OUTPUT болгоход хүргэдэг.

Эхнийх нь хувьсах температурыг тэг болгож, дараа нь TCNT0 бүртгэлд хуулна. TCNT0 бол манай таймер/тоолуур0. Энэ нь үүнийг тэг болгож байна. Компьютер энэ мөрийг ажиллуулмагц таймер0 тэгээс эхэлж секунд тутамд 15625 удаа тоолно. Асуудал нь ийм байна: TCNT0 бол "8 битийн" бүртгэл мөн үү? Тэгэхээр 8 битийн регистрийн хамгийн их тоо хэд байх вэ? За 0b11111111 байна. Энэ бол 0xFF тоо юм. Аль нь 255. Тэгэхээр юу болохыг харж байна уу? Цаг хэмжигч нь секундэд 15625 дахин нэмэгдэж, 255 хүрэх бүрт "хальж" дахин 0 рүү буцдаг. Энэ нь тэг рүү буцах үед таймер халих тасалдлын дохиог илгээдэг. Компьютер үүнийг авдаг бөгөөд та яг одоо юу хийж байгаагаа мэдэж байна уу? Тийм ээ. Энэ нь 0x0020 програмын санах ойн байршилд очоод тэндээс олж авсан зааврыг гүйцэтгэдэг.

Агуу их! Хэрэв та надтай хамт байгаа бол та уйгагүй супер баатар болно! Үргэлжлүүлье …

Алхам 6: Халих зохицуулагч

Тиймээс таймер/counter0 регистр дөнгөж дүүрсэн гэж үзье. Хөтөлбөр нь тасалдлын дохиог хүлээн авч 0x0020 програмыг ажиллуулдаг болохыг бид одоо мэдэж байгаа бөгөөд програмын тоолуур, компьютерт "overflow_handler" шошго руу орохыг хэлнэ үү.

overflow_handler:

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

Хамгийн эхний хийдэг зүйл бол "халих" хувьсагчийг нэмэгдүүлэх явдал юм (энэ нь бидний ерөнхий зориулалтын ажлын бүртгэл R17 юм), дараа нь халих агуулгыг 61 тоогоор "харьцуулдаг". Cpi зааварчилгааны ажиллах арга нь үүнийг зүгээр л хасах явдал юм. хоёр тоо, хэрэв үр дүн нь тэг бол энэ нь SREG бүртгэлд Z тугийг тавьдаг (энэ бүртгэлийг бид үргэлж харах болно гэж би танд хэлсэн). Хэрэв хоёр тоо тэнцүү бол Z туг нь 1, хоёр тоо тэнцүү биш бол 0 болно.

Дараагийн мөрөнд "brne PC+2" гэж бичсэн нь "тэнцүү биш бол салбар" гэсэн утгатай. Үндсэндээ энэ нь SREG дахь Z тугийг шалгадаг бөгөөд хэрэв энэ нь нэг биш бол (өөрөөр хэлбэл хоёр тоо тэнцүү биш, хэрэв тэнцүү бол тэг тугийг тохируулах болно) PC нь PC+2 руу салбарладаг бөгөөд энэ нь дараагийнхыг алгасах болно гэсэн үг юм. шугам болон шууд "reti" руу очдог бөгөөд энэ нь тасалдал ирэхэд кодонд байсан газар руу буцдаг. Хэрэв brne заавар нь тэг тугны битэнд 1 -ийг олсон бол тэр салбарлахгүй, харин дараагийн мөр рүү үргэлжлүүлэх болно.

Энэ бүхний цэвэр үр дүн юу вэ?

Цаг хэмжигч халах тоолонд энэ зохицуулагч "халих" утгыг нэгээр нэмэгдүүлж байгааг бид харж байна. Тиймээс "халих" хувьсагч нь халих тохиолдлыг тоолж байна. Энэ тоо 61 хүрэх бүрт бид үүнийг тэг болгоно.

Одоо яагаад дэлхий дээр бид үүнийг хийх болов?

Харцгаая. Бидний CPU -ийн цагийн хурд 16 МГц бөгөөд бид үүнийг TCCR0B ашиглан "урьдчилан хэмжсэн" бөгөөд ингэснээр таймер секундэд 15625 тоолох хурдаар тоолох боломжтой гэдгийг санаарай. Мөн таймер 255 гэсэн тоонд хүрэх тоолонд халих болно. Энэ нь секундэд 15625/256 = 61.04 удаа давсан гэсэн үг юм. Бид "халих" гэсэн хувьсагчтай халих тоог хянаж байгаа бөгөөд энэ тоог 61 -тэй харьцуулж байна. Тиймээс "халих" секунд тутамд 61 -тэй тэнцэх болно гэдгийг бид харж байна! Тиймээс манай зохицуулагч секунд тутамд нэг удаа "халих" -ыг тэг болгоно. Тиймээс, хэрэв бид "халих" хувьсагчийг зүгээр л хянаж, тэг рүү буцаах тоолонд нь анхаарлаа хандуулах юм бол бодит цаг хугацаанд секундээр тоолох болно (Дараагийн зааварт бид хэрхэн илүү нарийвчлалтай болохыг харуулах болно гэдгийг анхаарна уу. миллисекундын саатал нь Arduino -ийн "саатал" горимд ажилладагтай адил).

Одоо бид таймер халих тасалдлыг "зохицуулсан". Энэ нь хэрхэн ажилладагийг ойлгож, дараа нь бид энэ баримтыг ашиглах дараагийн алхам руу шилжихээ мартуузай.

Алхам 7: хойшлуулах

Манай таймер халих тасалдлын "overflow_handler" горим нь "халих" хувьсагчийг секунд тутамд нэг удаа тэг болгож байгааг бид харсан тул бид энэ баримтыг ашиглан "хоцрогдол" дэд програм зохиож болно.

Дараах кодыг манай саатал дороос хараарай: label

саатал:

clr overflows sec_count: cpi overflows, 30 brne sec_count ret

Хөтөлбөрөө хойшлуулах шаардлагатай болгонд бид энэ дэд програмыг дуудах гэж байна. Ажлын арга нь эхлээд "халих" хувьсагчийг тэг болгож тохируулдаг. Дараа нь энэ нь "sec_count" гэсэн шошготой талбарт орж, халих тоог 30 -тай харьцуулж, хэрэв тэнцүү биш бол сек_сайн шошго руу буцааж дахин тэнцүүлж, дахин тэнцүү болтол нь харьцуулна (энэ бүх цаг үргэлжлэх болно гэдгийг санаарай. Манай таймерын тасалдлын зохицуулагч нь хувьсах халих хэмжээг нэмэгдүүлсээр байгаа бөгөөд ингэснээр бид ийш тийш явах болгондоо өөрчлөгдөж байна. Халих нь 30 -тай тэнцэх үед энэ нь давталтаас гарч, бидний саатал гэж нэрлэдэг газар уруу буцна. 1/2 секундын саатал

Дасгал 2: overflow_handler горимыг дараах байдлаар өөрчилнө үү.

overflow_handler:

inc overlis reti

мөн програмыг ажиллуулна уу. Өөр зүйл байна уу? Яагаад, яагаад үгүй гэж?

Алхам 8: Нүдээ ань

Эцэст нь анивчих горимыг авч үзье.

анивчих:

sbi PORTD, 4 rcall хоцролт cbi PORTD, 4 rcall саатал rjmp анивчих

Эхлээд бид PD4 -ийг асаагаад дараа нь хойшлуулах дэд програмаа дуудна. Бид rcall -ийг ашигладаг бөгөөд ингэснээр компьютер "ret" гэсэн мэдэгдэлд ороход rcall -ийн дараах мөр рүү буцах болно. Дараа нь бидний харж байгаагаар халих хувьсагчийн 30 тоололтыг хойшлуулах нь бараг 1/2 секунд болно, дараа нь бид PD4 -ийг унтрааж, 1/2 секундын дараа хойшлуулж, дараа нь дахин эхэнд нь очно.

Үр дүн нь LED анивчдаг!

"Нүдээ анивчих" нь ассемблер хэл дээрх хамгийн сайн "сайн уу ертөнц" хөтөлбөр биш байж магадгүй гэдэгтэй одоо та санал нийлэх байх гэж бодож байна.

Дасгал 3: Хөтөлбөрт байгаа янз бүрийн параметрүүдийг өөрчил, ингэснээр LED нь өөр өөр хурдтайгаар секунд, эсвэл секундэд 4 удаа анивчдаг байх болно. Жишээлбэл, 1/4 секундын турш 2 секундын турш унтраана уу эсвэл 5 секундын турш унтраана уу. Дасгал 6 (заавал биш): Хэрэв танд 4 МГц, 13.5 МГц гэх мэт өөр болор осциллятор байгаа бол 16 МГц осциллятороо солино уу. Шинийг авахын тулд талхны тавцан дээр тавь, энэ нь LED -ийн анивчих хурданд хэрхэн нөлөөлж байгааг үзээрэй. Та одоо нарийн тооцооллыг хийж, ханшид хэрхэн нөлөөлөхийг урьдчилан хэлэх боломжтой байх ёстой.

Алхам 9: Дүгнэлт

Өдий зэрэгтэй явсан та бүхэнд баяр хүргэе!

Та утас холбож, туршиж үзэхээсээ илүү их уншиж, дээш харж байхад бөглөрөх нь маш хэцүү гэдгийг би ойлгож байна, гэхдээ та дараах чухал зүйлийг сурсан гэж найдаж байна.

  1. Програмын санах ой хэрхэн ажилладаг
  2. SRAM хэрхэн ажилладаг
  3. Бүртгэлийг хэрхэн хайх вэ
  4. Зааврыг хэрхэн хайж, юу хийж байгаагаа мэдэх
  5. Тасалдлыг хэрхэн хэрэгжүүлэх вэ
  6. CP нь кодыг хэрхэн гүйцэтгэдэг, SREG хэрхэн ажилладаг, тасалдлын үед юу болдог
  7. Код дээр хэрхэн гогцоо, үсрэлт хийх, эргэн тойронд үсрэх талаар
  8. Мэдээллийн хуудсыг унших нь хичнээн чухал вэ!
  9. Atmega328p микроконтроллерийн хувьд энэ бүгдийг хэрхэн яаж хийхээ мэдэж авснаар таны сонирхож буй шинэ хянагчийг сурч мэдэх нь харьцангуй бялуу болно.
  10. CPU -ийн цагийг хэрхэн бодит цаг болгон өөрчилж, хойшлуулах горимд ашиглах вэ.

Одоо бид илүү сайн код бичиж, илүү төвөгтэй зүйлийг хянах чадвартай олон онол байдаг. Тиймээс дараагийн хичээл дээр бид үүнийг хийх болно. Бид илүү төвөгтэй, илүү сонирхолтой хэлхээг бүтээж, хөгжилтэй байдлаар хянах болно.

Дасгал 7: Кодыг янз бүрийн аргаар "эвдэж", юу болохыг хараарай! Шинжлэх ухааны сониуч хүүхэд! Өөр хэн нэгэн аяга таваг угааж чадах уу? Дасгал 8: Жагсаалт үүсгэхийн тулд "-l" сонголтыг ашиглан кодыг цуглуулна уу. Өөрөөр хэлбэл "avra -l blink.lst blink.asm" гэж үзээд жагсаалтын файлыг үзээрэй. Нэмэлт зээл: Эхэндээ өгсөн тайлбар хийгдээгүй код, дараа нь хэлэлцсэн тайлбарласан кодууд хоорондоо ялгаатай байна! Өөр өөр кодын нэг мөр байдаг. Та олж чадах уу? Энэ ялгаа яагаад хамаагүй юм бэ?

Та хөгжилтэй байсан гэж найдаж байна! Дараагийн удаа уулзацгаая…

Зөвлөмж болгож буй: