Talaan ng mga Nilalaman:

Tutorial sa AVR Assembler 2: 4 Mga Hakbang
Tutorial sa AVR Assembler 2: 4 Mga Hakbang

Video: Tutorial sa AVR Assembler 2: 4 Mga Hakbang

Video: Tutorial sa AVR Assembler 2: 4 Mga Hakbang
Video: Atmel Studio 7 (AVR Studio) Tutorial: How To Create & Build New Project [SUBTITLE: ALL LANGUAGES] 2024, Hulyo
Anonim
Tutorial sa AVR Assembler 2
Tutorial sa AVR Assembler 2

Ang tutorial na ito ay isang pagpapatuloy ng "AVR Assembler Tutorial 1"

Kung hindi ka pa dumaan sa Tutorial 1 dapat mong ihinto ngayon at gawin mo muna ang isang iyon.

Sa tutorial na ito ay ipagpapatuloy namin ang aming pag-aaral ng pagpupulong sa wika ng pagpupulong ng atmega328p na ginamit sa Arduino's.

Kakailanganin mong:

  1. isang breadboard Arduino o isang normal na Arduino tulad ng sa Tutorial 1
  2. isang LED
  3. isang resistor na 220 ohm
  4. isang pindutan ng push
  5. pagkonekta ng mga wire para sa paggawa ng circuit sa iyong breadboard
  6. Manu-manong Itakda ang Instuction: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Datasheet: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Ang kumpletong koleksyon ng aking mga tutorial ay matatagpuan dito:

Hakbang 1: Pagbuo ng Circuit

Pagbuo ng Circuit
Pagbuo ng Circuit

Una kailangan mong buuin ang circuit na pag-aaralan namin sa tutorial na ito.

Narito ang paraan ng pagkakakonekta nito:

PB0 (digital pin 8) - LED - R (220 ohm) - 5V

PD0 (digital pin 0) - pushbutton - GND

Maaari mong suriin na ang iyong LED ay oriented nang maayos sa pamamagitan ng pagkonekta nito sa GND sa halip na PB0. Kung walang nangyari pagkatapos ay baligtarin ang oryentasyon at ang ilaw ay dapat na magsimula. Pagkatapos ay ikonekta muli ito sa PB0 at magpatuloy. Ipinapakita ng larawan kung paano nakakonekta ang aking breadboard arduino.

Hakbang 2: Pagsulat ng Code ng Assembly

Pagsulat ng Assembly Code
Pagsulat ng Assembly Code

Isulat ang sumusunod na code sa isang text file na tinatawag na pushbutton.asm at ipagsama ito sa avra tulad ng ginawa mo sa Tutorial 1.

Pansinin na sa code na ito mayroon kaming maraming mga puna. Sa tuwing makakakita ang tagatipon ng isang kalahating titik ay lalaktawan nito ang natitirang linya at magpatuloy sa susunod na linya. Mahusay na kasanayan sa pagprograma (lalo na sa wika ng pagpupulong!) Na bigyan ng puna ang iyong code upang sa pagbalik mo dito sa hinaharap malalaman mo kung ano ang iyong ginagawa. Magkomento ako ng maraming bagay sa mga unang ilang mga tutorial upang malaman natin nang eksakto kung ano ang nangyayari at bakit. Sa paglaon, sa sandaling naging mas mahusay tayo sa pag-coding ng pagpupulong ay magkokomento ako sa mga bagay nang medyo hindi gaanong detalyado.

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

; isinulat ni: 1o_o7; petsa: Oktubre 23, 2014; ********************************

.nolist

. isama ang "m328Pdef.inc".list.def temp = r16; italaga nagtatrabaho rehistro r16 bilang temp rjmp Init; pinaandar ang unang linya

Sa loob:

ser temp; itakda ang lahat ng mga piraso sa temp sa 1's. out DDRB, temp; pagtatakda ng kaunti bilang 1 sa Direksyon ng Data na I / O; magparehistro para sa PortB, na kung saan ay DDRB, itinakda iyon; pin bilang output, isang 0 ay magtatakda ng pin na iyon bilang input; kaya narito, ang lahat ng mga PortB pin ay output (naka-set sa 1) ldi temp, 0b11111110; i-load ang numero na 'agarang' sa rehistro ng temp; kung ito ay ld lamang kung gayon ang pangalawang pagtatalo; ay dapat na isang lokasyon ng memorya sa halip out DDRD, temp; mv temp sa DDRD, ang resulta ay ang pag-input ng PD0; at ang natitira ay mga output clr temp; lahat ng mga piraso sa temp ay nakatakda sa 0's out PortB, temp; itakda ang lahat ng mga piraso (ibig sabihin, mga pin) sa PortB sa 0V ldi temp, 0b00000001; i-load ang agarang numero upang i-temp ang PortD, temp; ilipat ang temp sa PortD. Ang PD0 ay may isang pull up risistor; (ibig sabihin nakatakda sa 5V) dahil mayroon itong 1 sa kaunting iyon; ang natitira ay 0V mula noong 0's.

Pangunahing:

sa temp, PinD; PinD hawak ang estado ng PortD, kopyahin ito sa temp; kung ang pindutan ay konektado sa PD0 ito ay; 0 kapag naitulak ang pindutan, 1 kung hindi man dahil; Ang PD0 ay may isang pull up risistor ito ay karaniwang sa 5V out PortB, temp; nagpapadala ng 0 at 1 na nabasa sa itaas sa PortB; nangangahulugan ito na nais namin ang LED na konektado sa PB0,; kapag ang PD0 ay LOW, itinakda nito ang PB0 sa LOW at lumiko; sa LED (dahil ang iba pang mga bahagi ng LED ay; konektado sa 5V at itatakda nito ang PB0 sa 0V sa gayon; ang kasalukuyang daloy) rjmp Pangunahing; nag-loop pabalik sa simula ng Main

Pansinin na sa pagkakataong ito hindi lamang tayo maraming mga komento sa aming code, ngunit mayroon din kaming isang seksyon ng header na nagbibigay ng ilang impormasyon tungkol sa kung sino ang sumulat nito at kung kailan ito isinulat. Ang natitirang code ay pinaghiwalay din sa mga seksyon.

Matapos mong maipon ang code sa itaas dapat mo itong i-load sa microcontroller at makita na gumagana ito. Dapat i-on ang LED habang pinipilit mo ang pindutan at pagkatapos ay i-off muli kapag kumalas ka. Ipinakita ko kung ano ang hitsura nito sa larawan.

Hakbang 3: Pagsusuri ng Line-by-line ng Code

Lalaktawan ko ang mga linya na mga puna lamang dahil maliwanag ang kanilang layunin.

.nolist

. isama ang "m328Pdef.inc". list

Ang tatlong linya na ito ay nagsasama ng file na naglalaman ng mga kahulugan ng Rehistro at Bit para sa ATmega328P na aming pinoprogram. Sinasabi ng utos na.nolist sa assembler na huwag isama ang file na ito sa pushbutton.lst file na ginagawa nito kapag tipunin mo ito. Patayin nito ang pagpipilian sa listahan. Matapos isama ang file ay ibinalik namin ang pagpipilian sa listahan kasama ang.list na utos. Ang dahilan kung bakit ginagawa namin ito ay dahil ang m328Pdef.inc file ay medyo mahaba at hindi namin talaga ito kailangang makita sa lista ng file. Ang aming assembler, avra, ay hindi awtomatikong bumubuo ng isang listahan ng file at kung nais namin ang isa ay magtipun-tipon kami gamit ang sumusunod na utos:

avra -l pushbutton.lst pushbutton.asm

Kung gagawin mo ito makakabuo ito ng isang file na tinatawag na pushbutton.lst at kung susuriin mo ang file na ito ay makikita mo na ipinapakita nito ang iyong code ng programa kasama ang labis na impormasyon. Kung titingnan mo ang labis na impormasyon makikita mo na ang mga linya ay nagsisimula sa isang C: sinundan ng kamag-anak na address sa hex kung saan inilalagay ang memorya sa memorya. Mahalaga na nagsisimula ito sa 000000 sa unang utos at tataas mula doon sa bawat kasunod na utos. Ang pangalawang haligi pagkatapos ng kamag-anak na lugar sa memorya ay ang hex code para sa utos na sinusundan ng hex code para sa argument ng utos. Tatalakayin namin ang listahan ng mga file nang higit pa sa mga tutorial sa hinaharap.

.def temp = r16; italaga nagtatrabaho rehistro r16 bilang temp

Sa linyang ito ginagamit namin ang direktiba ng assembler na ".def" upang tukuyin ang variable na "temp" na katumbas ng r16 "working register." Gagamitin namin ang rehistro ng r16 bilang isa na nag-iimbak ng mga numero na nais naming kopyahin sa iba't ibang mga port at rehistro (na hindi maaaring direktang maisulat).

Exercise 1: Subukang kopyahin ang isang binary number nang direkta sa isang port o espesyal na rehistro tulad ng DDRB at tingnan kung ano ang mangyayari kapag sinubukan mong tipunin ang code.

Ang isang rehistro ay naglalaman ng isang byte (8 piraso) ng impormasyon. Mahalaga na ito ay karaniwang isang koleksyon ng mga SR-Latches bawat isa ay isang "bit" at naglalaman ng isang 1 o isang 0. Maaari nating pag-usapan ito (at kahit na bumuo ng isa!) Mamaya sa seryeng ito. Maaaring nagtataka ka kung ano ang isang "working register" at kung bakit pinili namin ang r16. Tatalakayin namin iyon sa isang hinaharap na tutorial kapag sumisid kami sa quagmire ng mga panloob na chip. Sa ngayon nais kong maunawaan mo kung paano gumawa ng mga bagay tulad ng pagsulat ng code at programa ng pisikal na hardware. Pagkatapos ay magkakaroon ka ng isang frame ng sanggunian mula sa karanasang iyon na gagawing mas madaling maunawaan ang memorya at magrehistro ng mga katangian ng microcontroller. Napagtanto ko na ang karamihan sa mga panimulang aklat at talakayan ay ginagawa ito sa ibang paraan ngunit nalaman ko na ang paglalaro ng video game muna sandali upang makakuha ng pandaigdigang pananaw bago basahin ang manwal ng tagubilin ay mas madali kaysa sa unang pagbasa ng manwal.

rjmp Init; pinaandar ang unang linya

Ang linyang ito ay isang "kamag-anak na pagtalon" sa label na "Init" at hindi talaga kinakailangan dito dahil ang susunod na utos ay nasa Init ngunit isinasama namin ito para magamit sa hinaharap.

Sa loob:

ser temp; itakda ang lahat ng mga piraso sa temp sa 1's.

Matapos ang Init na label ay nagpapatupad kami ng isang "set register" na utos. Itinatakda nito ang lahat ng 8 mga piraso sa rehistro na "temp" (na sa tingin mo ay r16) sa 1's. Kaya't ang temp ay naglalaman ngayon ng 0b11111111.

out DDRB, temp; pagtatakda ng kaunti bilang 1 sa rehistro ng Data Direksyon I / O

; para sa PortB, na kung saan ay DDRB, itinakda ang pin na iyon bilang output; itatakda ng isang 0 ang pin na iyon bilang input; kaya narito, ang lahat ng mga PortB pin ay mga output (nakatakda sa 1)

Ang rehistro na DDRB (Data Direction Rehistro para sa PortB) ay nagsasabi kung aling mga pin sa PortB (ibig sabihin, PB0 hanggang sa PB7) ay itinalaga bilang input at kung alin ay itinalaga bilang output. Dahil mayroon kaming pin PB0 na konektado sa aming LED at ang natitirang hindi nakakonekta sa anumang itatakda namin ang lahat ng mga piraso sa 1 ibig sabihin lahat sila ay mga output.

ldi temp, 0b11111110; i-load ang `agarang 'numero sa rehistro ng temp

; kung ito ay ld lamang kung gayon ang pangalawang pagtatalo ay gagawin; kailangang maging isang lokasyon ng memorya

Naglo-load ang linyang ito ng binary number na 0b11111110 sa temp register.

out DDRD, temp; mv temp sa DDRD, ang resulta ay ang PD0 ay input at

; ang natitira ay mga output

Itinakda namin ngayon ang Rehistro ng Direksyon ng Data para sa PortD mula sa temp, dahil ang temp ay naglalaman pa rin ng 0b11111110 nakikita namin na ang PD0 ay itatalaga bilang isang input pin (dahil mayroong isang 0 sa dulong kanan na lugar) at ang natitira ay itinalaga bilang mga output dahil mayroong 1's sa mga spot na iyon.

clr temp; lahat ng mga piraso sa temp ay nakatakda sa 0's

sa labas ng PortB, temp; itakda ang lahat ng mga piraso (ibig sabihin, mga pin) sa PortB sa 0V

Una naming "limasin" ang rehistro ng temp na nangangahulugang pagtatakda ng lahat ng mga piraso sa zero. Pagkatapos kopyahin namin iyon sa pagrehistro sa PortB na nagtatakda ng 0V sa lahat ng mga pin na iyon. Ang isang zero sa isang PortB bit ay nangangahulugang panatilihin ng processor ang pin na iyon sa 0V, isang isa sa isang maliit ay magdudulot ng pin na itakda sa 5V.

Pagsasanay 2: Gumamit ng isang multimeter upang suriin kung ang lahat ng mga pin sa PortB ay talagang zero. Mayroon bang kakaibang nangyayari sa PB1? Anumang ideya kung bakit maaaring iyon? (katulad ng Exercise 4 sa ibaba pagkatapos ay sundin ang code…) Exercise 3: Alisin ang dalawang linya sa itaas mula sa iyong code. Tamang tumatakbo pa rin ba ang programa? Bakit?

ldi temp, 0b00000001; i-load ang agarang numero sa temp

sa labas ng PortD, temp; ilipat ang temp sa PortD. Ang PD0 ay nasa 5V (may isang pullup risistor); dahil mayroon itong 1 sa bit na iyon ang natitira ay 0V. Pagsasanay 4: Alisin ang dalawang linya sa itaas mula sa iyong code. Tamang tumatakbo pa rin ba ang programa? Bakit? (Iba ito sa Ehersisyo 3 sa itaas. Tingnan ang diagram ng pin out. Ano ang default na setting ng DDRD para sa PD0? (Tingnan ang pahina 90 ng data sheet

Una naming "na-load agad" ang bilang na 0b00000001 hanggang sa temp. Ang bahagi na "agarang" ay naroroon dahil naglo-load kami ng isang tuwid na bilang sa temp kaysa sa isang pointer sa isang lokasyon ng memorya na naglalaman ng bilang na mai-load. Sa kasong iyon, gagamitin lang namin ang "ld" sa halip na "ldi". Pagkatapos ipadala namin ang numerong ito sa PortD na nagtatakda ng PD0 sa 5V at ang natitira sa 0V.

Ngayon ay itinakda namin ang mga pin bilang input o output at na-set up namin ang kanilang mga paunang estado bilang alinman sa 0V o 5V (LOW o HIGH) at sa gayon ay ipinasok namin ang aming "loop" na programa.

Pangunahing: sa temp, PinD; PinD hawak ang estado ng PortD, kopyahin ito sa temp

; kung ang pindutan ay konektado sa PD0 pagkatapos ito ay magiging; isang 0 kapag ang pindutan ay naitulak, 1 kung hindi man dahil; Ang PD0 ay may isang pull up risistor ito ay karaniwang sa 5V

Naglalaman ang rehistro na PinD ng kasalukuyang estado ng mga PortD pin. Halimbawa ay magiging isang 1 sa halip na isang 0. Kaya sa linyang ito kinopya namin ang kasalukuyang estado ng mga pin sa temp.

sa labas ng PortB, temp; nagpapadala ng 0 at 1 na nabasa sa itaas sa PortB

; nangangahulugan ito na nais namin ang LED na konektado sa PB0, kaya; kapag ang PD0 ay LOW, itatakda nito ang PB0 sa LOW at iikot; sa LED (ang iba pang mga bahagi ng LED ay konektado; sa 5V at itatakda nito ang PB0 sa 0V kaya ang kasalukuyang daloy)

Ipinadala namin ngayon ang estado ng mga pin sa PinD sa output ng PortB. Mabisa, nangangahulugan ito na ang PD0 ay magpapadala ng 1 sa PortD0 maliban kung ang pindutan ay pinindot. Sa kasong iyon dahil ang pindutan ay konektado sa lupa na ang pin ay nasa 0V at magpapadala ito ng 0 sa PortB0. Ngayon, kung titingnan mo ang circuit diagram, ang 0V sa PB0 ay nangangahulugang ang LED ay mamula-mula dahil ang kabilang panig nito ay nasa 5V. Kung hindi namin pinindot ang pindutan, upang ang isang 1 ay ipinadala sa PB0, nangangahulugan ito na mayroon kaming 5V sa PB0 at 5V din sa kabilang panig ng LED at sa gayon walang potensyal na pagkakaiba at walang kasalukuyang daloy at sa gayon ang Ang LED ay hindi mamula (sa kasong ito ito ay isang LED na kung saan ay isang diode at sa kasalukuyan ay dumadaloy lamang sa isang direksyon anuman ngunit anuman).

rjmp Pangunahing; mga loop pabalik sa Start

Ang kamag-anak na pagtalon na ito ay nag-loop sa amin pabalik sa aming Pangunahing: label at sinuri namin muli ang PinD at iba pa. Sinusuri ang bawat ika-16 milyon ng isang segundo kung ang pindutan ay pinipilit at itinatakda ang PB0 nang naaayon.

Exercise 5: Baguhin ang iyong code upang ang iyong LED ay konektado sa PB3 sa halip na PB0 at makita na gumagana ito. Pagsasanay 6: I-plug ang iyong LED sa GND sa halip na 5V at baguhin ang iyong code nang naaayon.

Hakbang 4: Konklusyon

Sa tutorial na ito ay karagdagang sinisiyasat namin ang wika ng pagpupulong para sa ATmega328p at natutunan kung paano kontrolin ang isang LED gamit ang isang pushbutton. Sa partikular natutunan namin ang mga sumusunod na utos:

itinatakda ng ser register ang lahat ng mga piraso ng isang pagrehistro sa 1's

Itinatakda ng clr register ang lahat ng mga piraso ng isang pagrehistro sa 0's

sa rehistro, ako / o nagrerehistro ng mga kopya ng numero mula sa isang i / o rehistro sa isang gumaganang rehistro

Sa susunod na tutorial susuriin namin ang istraktura ng ATmega328p at ang iba't ibang mga pagrehistro, pagpapatakbo, at mapagkukunan na nakapaloob dito.

Bago ako magpatuloy sa mga tutorial na ito hihintayin ko at makita ang antas ng interes. Kung mayroong isang bilang ng mga tao na talagang nasiyahan sa pag-aaral kung paano mag-code ng mga programa para sa microprocessor na ito sa wika ng pagpupulong pagkatapos ay magpapatuloy ako at magtatayo ng mas kumplikadong mga circuit at gagamit ng mas matatag na code.

Inirerekumendang: