Мазмуну:

AVR Assembler үйрөткүчү 2: 4 кадам
AVR Assembler үйрөткүчү 2: 4 кадам

Video: AVR Assembler үйрөткүчү 2: 4 кадам

Video: AVR Assembler үйрөткүчү 2: 4 кадам
Video: Лекция 4. Архитектура AVR. Ассемблер 2024, Июль
Anonim
AVR Assembler үйрөткүчү 2
AVR Assembler үйрөткүчү 2

Бул окуу куралы "AVR Assembler Tutorial 1дин" уландысы

Эгерде сиз 1 -сабактан өтпөгөн болсоңуз, анда азыр токтоп, муну биринчи жасашыңыз керек.

Бул үйрөткүчтө биз Arduino тилинде колдонулган atmega328pтин ассамблеялык программалоо боюнча изилдөөбүздү улантабыз.

Сага керек болот:

  1. нан табак Arduino же кадимки Arduino 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

Сиз LEDдин PB0 ордуна GNDге туташуу менен туура багытталганын текшере аласыз. Эгерде эч нерсе болбосо, багытын өзгөртүп, жарык күйүшү керек. Андан кийин аны PB0го кайра туташтырыңыз жана улантыңыз. Сүрөт менин ардуино панелимдин кантип туташканын көрсөтөт.

2 -кадам: Ассамблея кодексин жазуу

Ассамблея кодексин жазуу
Ассамблея кодексин жазуу

Төмөнкү кодду pushbutton.asm деп аталган текст файлына жазыңыз жана аны 1 -үйрөткүчтөгүдөй avra менен түзүңүз.

Бул коддо бизде көптөгөн комментарийлер бар экенин байкаңыз. Ассемблер үтүрлүү чекитти көргөн сайын ал саптын калган бөлүгүн өткөрүп жиберип, кийинки сапка өтөт. Келечекте ага кайтып келгенде, эмне кылып жатканыңызды билүү үчүн кодуңузга катуу комментарий берүү жакшы программалоо практикасы (өзгөчө ассамблея тилинде!). Мен эмне болуп жатканын жана эмне үчүн экенин так билишибиз үчүн, биринчи окуу куралдарында көп нерселерди комментарийлеп жатам. Кийинчерээк, биз коддоодо бир аз жакшыраак болгондон кийин, мен бир аз майда -чүйдөсүнө чейин комментарий берем.

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

; жазган: 1o_o7; дата: 23 -октябрь, 2014 -жыл; **********************************

.nolist

.include "m328Pdef.inc".list.def temp = r16; r16 жумушчу реестрин temp rjmp Init катары белгилөө; биринчи сап аткарылган

Ичинде:

ser temp; бардык биттерди темп -1ге коюңуз. чыгуу DDRB, темп; Берилиштер I/O боюнча 1 деп бир аз коюу; PortDRге катталуу, бул DDRB, муну белгилейт; pin катары чыгаруу, 0 бул пинди киргизүү катары коет; Ошентип, бул жерде, бардык PortB казыктары чыгуулар (1ге коюлган) ldi temp, 0b11111110; темп реестрине "дароо" санын жүктөө; эгер бул жөн гана лд болсо, анда экинчи аргумент; эс тутуму болушу керек, анын ордуна DDRD, temp; mv temp DDRDге, натыйжада PD0 киргизүү болуп саналат; ал эми калгандары клр темп; темптеги бардык биттер 0го PortB, temp; PortBдеги бардык биттерди (б.а. казыктарды) 0V ldi temp, 0b00000001ге коюу; дароо номурду жүктөө PortD, temp; температураны PortDге жылдырыңыз. PD0 тартылуу каршылыгына ээ; (б.а. 5Вга коюлган), анткени ал битте 1 бар; калгандары 0 -жылдардан бери 0В.

Негизги:

температурада, PinD; PinD PortD абалын кармайт, муну темпке көчүрүү; баскыч PD0 менен туташкан болсо, бул болот; 0 баскычы басылганда, 1 башкача; PD0 тартылуу каршылыгына ээ, ал адатта PortB, 5V чыгып турат; 0 жана 1дин жогорудагы көрсөткүчтөрүн PortBге жөнөтөт; бул биз PB0 менен туташкан LEDди каалайбыз дегенди билдирет; качан PD0 ТӨМӨН болсо, ал PB0ну ТӨМӨН кылып бурат; светодиоддо (светодиоддун экинчи тарабы болгондуктан; 5Вга туташкан жана бул PB0ду 0Vге коёт; ток агат) rjmp Main; Мэйндин башталышына кайтуу

Көңүл бургула, бул жолу биздин коддо дагы көптөгөн комментарийлер бар, бирок бизде аны ким жазгандыгы жана качан жазылгандыгы жөнүндө маалымат берген баш бөлүм бар. Калган коддор да бөлүмдөргө бөлүнгөн.

Жогорудагы кодду түзгөндөн кийин аны микроконтроллерге жүктөп, анын иштээрин көрүшүңүз керек. Сиз баскычты басканда LED күйүп, анан коё бергенде кайра өчүшү керек. Мен сүрөттө кандай экенин көрсөттүм.

3-кадам: Коддун сап-сап талдоосу

Мен жөн гана комментарий болгон саптарды өткөрүп жиберем, анткени алардын максаты түшүнүктүү.

.nolist

.include "m328Pdef.inc".list

Бул үч сапка биз программалап жаткан ATmega328P үчүн Регистр жана Бит аныктамалары камтылган файл кирет.. Nolist буйругу ассемблерге бул файлды сиз аны чогултуп жатканда чыгарган pushbutton.lst файлына кошпоону айтат. Бул листинг параметрин өчүрөт. Файлды кошкондон кийин.list буйругу менен листинг опциясын кайра күйгүзөбүз. Мунун себеби, m328Pdef.inc файлы абдан узун жана биз аны тизме файлынан көрүүнүн кажети жок. Биздин ассемблер, avra, автоматтык түрдө тизме файлын түзбөйт жана эгерде биз кааласак, биз төмөнкү буйрукту колдонуп чогултмакпыз:

avra -l баскычтар.lst баскычтар.asm

Эгер сиз муну кылсаңыз, анда pushbutton.lst деп аталган файл пайда болот жана эгер сиз бул файлды текшерсеңиз, анда ал сиздин программа кодуңузду кошумча маалымат менен кошо көрсөтөт. Эгерде сиз кошумча маалыматты карасаңыз, анда сызыктар C менен башталаарын көрөсүз: андан кийин код эс тутумда кайда жайгашкан алтылыкта. Негизинен ал 000000дө биринчи буйрук менен башталат жана ар бир кийинки буйрук менен ошол жерден көбөйөт. Эстутумдагы салыштырмалуу жерден кийинки экинчи тилке - бул команданын аргументи үчүн он алтылык коду, андан кийин он алты коду. Биз тизме файлдарын кийинки сабактарда талкуулайбыз.

.def temp = r16; r16 жумушчу реестрин температура катары белгилеңиз

Бул сапта "temp" өзгөрмөсүн r16 "жумушчу реестрине" барабар деп аныктоо үчүн ".def" ассемблер директивасын колдонобуз. Биз r16 регистрин ар кандай портторго жана регистрлерге көчүргүбүз келген сандарды сактай турган кат катары колдонобуз (аларды түз жазууга болбойт).

Exercise 1: бинардык номурду DDRB сыяктуу портко же атайын реестрге түз көчүрүп көрүңүз жана кодду чогултууга аракет кылганыңызда эмне болорун көрүңүз.

Реестрде байт (8 бит) маалымат камтылган. Негизинен, бул көбүнчө SR-латчтардын жыйнагы, алардын ар бири "бит" жана 1 же 0 камтыйт. Биз муну кийинчерээк ушул серияда талкуулашыбыз мүмкүн (ал тургай, бирин да кура алабыз!). Сиз "жумушчу реестр" деген эмне жана эмне үчүн r16 тандап алдык деп ойлонушуңуз мүмкүн. Биз муну келечектеги үйрөткүчтө чиптин ички баткагына чөмүлгөндө талкуулайбыз. Азырынча мен кодду жазуу жана физикалык жабдыктарды программалоо сыяктуу нерселерди кантип жасоону түшүнүшүңүздү каалайм. Андан кийин сиз микроконтроллердин эс тутумун жана регистрациялоону жеңилдете турган тажрыйбадан алынган маалыматка ээ болосуз. Мен түшүнөм, көпчүлүк кириш окуу китептери жана дискуссиялар муну тескерисинче жасашат, бирок мен инструкцияны окуудан мурун глобалдык перспективага ээ болуу үчүн видео оюнду ойноо биринчи окуу куралын окуудан алда канча оңой экенин түшүндүм.

rjmp Init; биринчи сап аткарылган

Бул линия "Init" энбелгисине "салыштырмалуу секирүү" болуп саналат жана бул жерде чынында эле зарыл эмес, анткени кийинки буйрук мурунтан эле Initте, бирок биз аны келечекте колдонуу үчүн киргизебиз.

Ичинде:

ser temp; бардык биттерди темп -1ге коюңуз.

Init этикеткасынан кийин биз "регистрди коюу" буйругун аткарабыз. Бул реестрдеги "бит" 8 биттин баарын (эсиңизде r16) 1ге коёт. Ошентип, темп азыр 0b11111111 камтыйт.

DDRB чыгып, темп; Берилиштер I/O реестринде бир аз 1 катары коюу

; PortB үчүн, бул DDRB, бул пинди чыгаруу катары коет; а 0 ошол пинди киргизүү катары коёт; Ошентип, бул жерде, бардык PortB казыктары чыгуулар (1ге коюлган)

DDRB реестри (PortB үчүн маалыматтын багыты реестри) PortBдеги кайсы казыктарды (б.а. PB7 аркылуу PB7 аркылуу) киргизүү катары белгилеп, кайсынысын чыгаруу катары белгилейт. Бизде PB0 пини LEDга туташтырылгандыктан, калгандары эч нерсеге байланышпагандыктан, биз бардык биттерди 1ге коебуз, бул алардын бардыгы.

ldi temp, 0b11111110; темп реестрине "дароо" санын жүктөө

; эгер бул жөн гана лд болсо, анда экинчи аргумент болмок; эс тутуму болушу керек

Бул линия 0b11111110 бинардык номурун темп регистрине жүктөйт.

DDRD, темп; mv temp DDRDге, натыйжада PD0 киргизүү жана

; калгандары жыйынтыктар

Азыр биз PortD үчүн маалыматтар багытынын реестрин темптен баштап койдук, анткени темп дагы эле 0b11111110 камтыйт, биз көрөбүз PD0 киргизүү пини (эң оң жакта 0 болгондуктан), ал эми калгандары чыгаруу катары дайындалган. 1 ошол жерде.

clr temp; темпте бардык биттер 0'го коюлган

PortB, темп; PortBдеги бардык биттерди (б.а. казыктарды) 0Vге коюңуз

Биринчиден, биз реестрдин температурасын "тазалайбыз", бул бардык биттерди нөлгө коюуну билдирет. Андан кийин биз муну PortB реестрине көчүрөбүз, ал ошол казыктардын бардыгына 0В орнотот. PortB битиндеги нөл бул процессор бул пинди 0Вде сактайт дегенди билдирет, бир аздан кийин бул пин 5Vга коюлат.

Exercise 2: Мультиметрди колдонуп, PortBдеги бардык казыктар чындыгында нөл экенин текшериңиз. PB1 менен кызыктай бир нерсе болуп жатабы? Эмнеге мындай болушу мүмкүн экенин билесизби? (төмөндөгү 4 -көнүгүүгө окшош, андан кийин кодду ээрчиңиз …) 3 -көнүгүү: Жогорудагы эки сапты кодуңуздан алып салыңыз. Программа дагы эле туура иштейби? Неге?

ldi temp, 0b00000001; температураны дароо жүктөө

PortD, темп; температураны PortDге жылдырыңыз. PD0 5Vда (тартылуу каршылыгы бар); анткени анын 1 битинде калгандары 0В. Exercise 4: Жогорудагы эки сапты кодуңуздан алып салыңыз. Программа дагы эле туура иштейби? Неге? (Бул жогорудагы 3 -көнүгүүдөн айырмаланат. Түзүү диаграммасын караңыз. PD0 үчүн демейки DDRD жөндөөсү кандай? (Маалымат барагынын 90 -бетин караңыз)

Адегенде биз 0b00000001 санын темпке "дароо жүктөйбүз". "Дароо" бөлүгү бар, анткени биз жүктөө үчүн номерди камтыган эс тутумуна көрсөткүчтү эмес, темпке түз санды жүктөп жатабыз. Мындай учурда биз "лди" эмес, "лд" колдонмокпуз. Андан кийин биз бул номерди PDDге жөнөтөбүз, ал PD0ну 5Vга, калгандарын 0Vга коёт.

Эми биз казыктарды киргизүү же чыгаруу катары койдук жана алардын баштапкы абалын 0V же 5V (LOW же HIGH) деп койдук, ошондуктан биз азыр программабызга "цикл" кирет.

Негизги: температурада, PinD; PinD PortD абалын кармайт, муну темпке көчүрүңүз

; баскыч PD0 менен туташкан болсо, анда бул болот; а 0 баскычы басылганда, 1 башкача; PD0 тартылуу каршылыгына ээ, адатта 5В

PinD реестри PortD казыктарынын учурдагы абалын камтыйт. Мисалы, эгер сиз PD3кө 5В зым кошсоңуз, анда кийинки саат циклинде (бул микроконтроллер 16 МГц саат сигналына туташтырылгандыктан секундасына 16 миллион жолу болот) PinD3 бит (PD3 учурдагы абалынан) 0 ордуна 1 болмок. Ошентип, бул сапта биз казандын учурдагы абалын темпке көчүрөбүз.

PortB, темп; 0 жана 1дин жогорудагы көрсөткүчтөрүн PortBге жөнөтөт

; бул биз PB0 менен туташкан LEDди каалайбыз дегенди билдирет, ошондуктан; качан PD0 ТӨМӨН болсо, ал PB0ду LOWго коюп, бурат; светодиоддо (светодиоддун экинчи тарабы туташтырылган; 5Вга жана бул PB0ду 0Vге орнотот, андыктан ток агат)

Эми биз PinDдеги пиндердин абалын PortB өндүрүшүнө жөнөтөбүз. Натыйжалуу, бул PD0 1 баскычын басылмайынча PortD0го 1 жөнөтөт дегенди билдирет. Бул учурда, баскыч жерге туташтырылгандыктан, бул пин 0В болот жана ал PortB0го 0 жөнөтөт. Эми, эгерде сиз схеманы карасаңыз, PB0 боюнча 0В диоддун башка тарабы 5В болгондон кийин жарык болот дегенди билдирет. Эгерде биз баскычты баспай турган болсок, анда PB0го 1 жөнөтүлөт, бул бизде PB0до 5В, ошондой эле LEDдин башка жагында 5В бар, демек эч кандай потенциалдуу айырма жок жана ток болбойт жана Светодиод жаркырабайт (бул учурда бул диод болгон LED, андыктан ток бир багытты көздөй агат).

rjmp Main; баштоо үчүн кайра илмек

Бул салыштырмалуу секирүү бизди Башкы: энбелгибизге кайтарат жана биз PinDди дагы бир жолу текшеребиз ж. Ар бир 16 миллиондон бир секунданын баскычы басылып жатабы же жокпу, ошого жараша PB0 орнотулаарын текшерүү.

Exercise 5: Сиздин LED PB0 ордуна PB3 менен туташып турушу үчүн кодуңузду өзгөртүңүз жана анын иштээрин көрүңүз Exercise 6: 5V ордуна GNDге LEDди сайыңыз жана ошого жараша кодуңузду өзгөртүңүз.

4 -кадам: Жыйынтык

Бул үйрөткүчтө биз ATmega328p үчүн ассемблер тилин андан ары изилдеп чыктык жана LEDди баскыч менен кантип башкарууну үйрөндүк. Атап айтканда, биз төмөнкү буйруктарды үйрөндүк:

ser register реестрдин бардык биттерин 1ге коёт

clr register реестрдин бардык биттерин 0гө коёт

реестрде, кирүү/кирүү реестри номерди киргизүү регистринен жумушчу реестрине көчүрөт

Кийинки окуу куралында биз ATmega328pдин түзүлүшүн жана андагы ар кандай реестрлерди, операцияларды жана ресурстарды карап чыгабыз.

Бул окуу куралдарын улантуудан мурун, мен күтөм жана кызыгуунун деңгээлин көрөм. Эгерде бул микропроцессордун программаларын ассемблер тилинде кантип коддоону үйрөнүүдөн ырахат алган көптөгөн адамдар бар болсо, мен андан ары татаалыраак схемаларды куруп, бекем кодду колдоном.

Сунушталууда: