INHOUDSOPGAWE:

AVR -samestellingstudie 2: 4 -stappe
AVR -samestellingstudie 2: 4 -stappe

Video: AVR -samestellingstudie 2: 4 -stappe

Video: AVR -samestellingstudie 2: 4 -stappe
Video: Схема АВР на двух контакторах и с реле контроля фаз 2024, November
Anonim
Tutorial vir AVR -samesteller 2
Tutorial vir AVR -samesteller 2

Hierdie handleiding is 'n voortsetting van "AVR Assembler Tutorial 1"

As u nie deur tutoriaal 1 gegaan het nie, moet u nou stop en eers die een doen.

In hierdie handleiding gaan ons voort met ons studie van die monteringstaalprogrammering van die atmega328p wat in Arduino's gebruik word.

Jy sal nodig hê:

  1. 'n broodbord Arduino of net 'n normale Arduino soos in handleiding 1
  2. 'n LED
  3. 'n weerstand van 220 ohm
  4. 'n drukknop
  5. verbindingsdrade om die stroombaan op u broodbord te maak
  6. Handleiding vir instuksies: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Gegevensblad: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Die volledige versameling van my tutoriale kan hier gevind word:

Stap 1: Bou die kring

Bou die kring
Bou die kring

Eerstens moet u die stroombaan bou wat ons in hierdie tutoriaal gaan bestudeer.

Hier is die manier waarop dit verbind word:

PB0 (digitale pen 8) - LED - R (220 ohm) - 5V

PD0 (digitale pen 0) - drukknop - GND

U kan seker maak dat u LED behoorlik georiënteerd is deur dit aan GND in plaas van PB0 te koppel. As niks gebeur nie, draai dan die rigting om en die lig moet brand. Koppel dit dan weer aan PB0 en gaan voort. Die prentjie wys hoe my broodbord -arduino verbind is.

Stap 2: Skryf die Vergaderingskode

Skryf die Vergaderingskode
Skryf die Vergaderingskode

Skryf die volgende kode in 'n tekslêer genaamd pushbutton.asm en stel dit saam met avra soos in Tutoriaal 1.

Let daarop dat ons baie opmerkings in hierdie kode het. Elke keer as die samesteller 'n kommapunt sien, slaan hy die res van die reël oor en gaan na die volgende reël. Dit is 'n goeie programmeringspraktyk (veral in die monteringstaal!) Om sterk kommentaar te lewer op u kode, sodat u in die toekoms sal weet wat u gedoen het. Ek gaan baie kommentaar lewer op die dinge in die eerste paar tutoriale, sodat ons presies weet wat aangaan en hoekom. Later, sodra ons 'n bietjie beter geword het in die samestelling van kodering, sal ek dinge in 'n bietjie minder detail lewer.

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

; geskryf deur: 1o_o7; datum: 23 Oktober 2014; ************************************

.nolist

.include "m328Pdef.inc".list.def temp = r16; wys werkregister r16 aan as temp rjmp Init; eerste reël uitgevoer

Eerste:

ser temp; stel alle stukkies in temperatuur tot 1's. uit DDRB, temp; stel 'n bietjie as 1 op die Data Direction I/O; registreer vir PortB, wat DDRB is, stel dit; pen as uitset, 'n 0 sal die pen as invoer stel; dus hier is alle PortB -penne uitsette (ingestel op 1) ldi temp, 0b11111110; laai die 'onmiddellike' nommer in die temp -register; as dit net ld was dan die tweede argument; sou 'n geheue plek in plaas van DDRD, temp; mv temp na DDRD, gevolg is dat PD0 ingevoer is; en die res is uitsette clr temp; alle stukkies in temp is ingestel op 0's uit PortB, temp; stel al die stukkies (dws penne) in PortB op 0V ldi temp, 0b00000001; laai onmiddellike nommer om PortD, temp; skuif temp na PortD. PD0 het 'n optrekweerstand; (d.w.s. ingestel op 5V) aangesien dit 'n 1 in daardie bietjie het; die res is 0V sedert 0's.

Hoof:

in temp, PinD; PinD hou die toestand van PortD, kopieer dit na temp; as die knoppie aan PD0 gekoppel is, sal dit wees; 0 as die knoppie gedruk word, 1 andersins sedert; PD0 het 'n optrekweerstand; dit is normaalweg by 5V buite PortB, temp; stuur die 0's en 1's hierbo gelees na PortB; dit beteken dat ons die LED met PB0 wil verbind; as PD0 LOW is, stel dit PB0 op LOW en draai; op die LED (aangesien die ander kant van die LED is; gekoppel aan 5V en dit sal PB0 op 0V stel; stroom sal vloei) rjmp Main; loop terug na die begin van Main

Let op dat ons hierdie keer nie net baie meer opmerkings in ons kode het nie, maar dat ons ook 'n kopstuk het wat inligting gee oor wie dit geskryf het en wanneer dit geskryf is. Die res van die kode word ook in afdelings geskei.

Nadat u bogenoemde kode saamgestel het, moet u dit op die mikrobeheerder laai en kyk of dit werk. Die LED moet aanskakel terwyl u op die knoppie druk en dan weer afskakel as u los. Ek het op die foto gewys hoe dit lyk.

Stap 3: Analise van die kode lyn-vir-reël

Ek sal die reëls wat slegs opmerkings is, oorslaan, want die doel daarvan is vanselfsprekend.

.nolist

.sluit "m328Pdef.inc".lys in

Hierdie drie reëls bevat die lêer wat die register- en bit -definisies bevat vir die ATmega328P wat ons programmeer. Die.nolist -opdrag sê aan die versamelaar om hierdie lêer nie in die pushbutton.lst -lêer op te neem wat dit produseer wanneer u dit saamstel nie. Dit skakel die lysopsie uit. Nadat ons die lêer ingesluit het, skakel ons die lysopsie weer aan met die.list -opdrag. Die rede waarom ons dit doen, is omdat die m328Pdef.inc -lêer redelik lank is en ons dit nie regtig in die lyslêer hoef te sien nie. Ons samesteller, avra, genereer nie outomaties 'n lyslêer nie, en as ons een wil hê, sal ons die volgende opdrag saamstel:

avra -l drukknop.lst drukknop.asm

As u dit doen, sal dit 'n lêer genaamd pushbutton.lst genereer, en as u hierdie lêer ondersoek, sal u sien dat dit u programkode en ekstra inligting wys. As u na die ekstra inligting kyk, sal u sien dat die reëls begin met 'n C: gevolg deur die relatiewe adres in heks waar die kode in die geheue geplaas word. Dit begin in wese by 000000 met die eerste opdrag en neem toe met elke daaropvolgende opdrag. Die tweede kolom na die relatiewe plek in die geheue is die hex -kode vir die opdrag, gevolg deur die hex -kode vir die argument van die opdrag. Ons sal lyslêers verder bespreek in toekomstige tutoriale.

.def temp = r16; noem werkregister r16 as temp

In hierdie reël gebruik ons die assembler richtlijn ".def" om die veranderlike "temp" te definieer as gelyk aan die r16 "werkregister". Ons sal register r16 gebruik as die een wat die nommers wat ons wil kopieer na verskillende hawens en registers (wat nie direk geskryf kan word nie) stoor.

Oefening 1: Probeer 'n binêre getal direk na 'n poort of spesiale register soos DDRB kopieer en kyk wat gebeur as u die kode probeer saamstel.

'N Register bevat 'n greep (8 bisse) inligting. In wese is dit gewoonlik 'n versameling SR-grendels, elkeen is 'n 'bietjie' en bevat 'n 1 of 'n 0. Ons kan dit later bespreek (en selfs bou!) Later in hierdie reeks. U wonder miskien wat 'n 'werkregister' is en waarom ons r16 gekies het. Ons sal dit in 'n toekomstige tutoriaal bespreek wanneer ons in die moeras van die binnekant van die chip duik. Ek wil nou hê dat u moet verstaan hoe u dinge moet doen, soos om kode te skryf en fisiese hardeware te programmeer. Dan het u 'n verwysingsraamwerk uit die ervaring, wat die geheue en registereienskappe van die mikrobeheerder makliker verstaanbaar sal maak. Ek besef dat die meeste inleidende handboeke en besprekings dit andersom doen, maar ek het gevind dat dit eers baie makliker is om 'n videospeletjie te speel om 'n globale perspektief te kry voordat u die handleiding lees, as om eers die handleiding te lees.

rjmp Init; eerste reël uitgevoer

Hierdie reël is 'n 'relatiewe sprong' na die etiket 'Init' en is hier nie regtig nodig nie, aangesien die volgende opdrag reeds in Init is, maar ons sluit dit in vir toekomstige gebruik.

Eerste:

ser temp; stel alle stukkies in temperatuur op 1's.

Na die Init -etiket voer ons 'n "set register" -opdrag uit. Dit stel al die 8 bisse in die register "temp" (waarvan u onthou is r16) op 1's. Temp bevat dus 0b11111111.

uit DDRB, temp; stel 'n bietjie as 1 op die Data Direction I/O -register

; vir PortB, wat DDRB is, stel die pen as uitvoer; 'n 0 sal die pen as invoer stel; dus hier is alle PortB -penne uitsette (ingestel op 1)

Die register DDRB (Data Direction Register for PortB) vertel watter penne op PortB (dws PB0 tot en met PB7) as invoer aangedui word en watter as uitset aangedui word. Aangesien die pin PB0 aan ons LED gekoppel is en die res aan niks gekoppel is nie, stel ons al die stukkies op 1, wat beteken dat dit almal uitsette is.

ldi temp, 0b11111110; laai die 'onmiddellike' nommer in die temp -register

; as dit net ld was, dan sou die tweede argument; moet 'n geheue plek wees

Hierdie reël laai die binêre getal 0b11111110 in die temp -register.

uit DDRD, temp; mv temp na DDRD, gevolg is dat PD0 ingang is en

; die res is uitsette

Nou stel ons die Data Direction Register vir PortD van temp in, aangesien temp nog steeds 0b11111110 bevat, sien ons dat PD0 as 'n invoerpen aangewys sal word (aangesien daar 'n 0 heel regs is) en die res word as uitsette aangedui, aangesien daar 1's op daardie plekke.

clr temp; alle stukkies in temp is op 0's gestel

uit PortB, temp; stel al die stukkies (dws penne) in PortB op 0V

Eerstens "maak" ons die registertemperatuur skoon, wat beteken dat al die stukkies op nul gestel word. Dan kopieer ons dit na die PortB -register wat 0V op al die penne stel. 'N Nul op 'n PortB -bit beteken dat die verwerker die pen by 0V sal hou, 'n een op 'n bietjie sal veroorsaak dat die pen op 5V gestel word.

Oefening 2: Gebruik 'n multimeter om te kyk of al die penne op PortB eintlik nul is. Is daar iets vreemds aan die gang met PB1? Enige idee hoekom dit kan wees? (soortgelyk aan oefening 4 hieronder, volg dan die kode …) Oefening 3: Verwyder die bogenoemde twee reëls uit u kode. Loop die program nog steeds korrek? Hoekom?

ldi temp, 0b00000001; laai onmiddellike nommer na temp

uit PortD, temp; skuif temp na PortD. PD0 is by 5V (het 'n pullup -weerstand); aangesien dit 'n 1 in daardie bietjie het, is die res 0V. Oefening 4: Verwyder bogenoemde twee reëls uit u kode. Loop die program nog steeds korrek? Hoekom? (Dit verskil van oefening 3 hierbo. Sien die uitteken -diagram. Wat is die standaard DDRD -instelling vir PD0? (Sien bladsy 90 van die gegewensblad

Eerstens laai ons die getal 0b00000001 onmiddellik na temp. Die 'onmiddellike' deel is daar, aangesien ons 'n reguit nommer na temp laai, eerder as 'n wyser na 'n geheue -plek met die nommer wat ons moet laai. In daardie geval sou ons eenvoudig 'ld' eerder as 'ldi' gebruik. Dan stuur ons hierdie nommer na PortD wat PD0 op 5V stel en die res op 0V.

Nou het ons die penne as invoer of uitset gestel, en ons het hul aanvanklike toestande as 0V of 5V (LAAG of HOOG) opgestel, en ons betree dus ons program "lus".

Hoof: in temp, PinD; PinD hou die toestand van PortD, kopieer dit na temp

; as die knoppie aan PD0 gekoppel is, sal dit so wees; a 0 as die knoppie gedruk word, 1 andersins sedert; PD0 het 'n optrekweerstand, gewoonlik by 5V

Die register PinD bevat die huidige toestand van die PortD -penne. As u byvoorbeeld 'n 5V -draad aan PD3 gekoppel het, dan die PinD3 -bit (vanaf die huidige toestand van PD3) by die volgende kloksiklus (wat 16 miljoen keer per sekonde gebeur, aangesien ons die mikrobeheerder gekoppel het aan 'n 16MHz -kloksignaal) sou 'n 1 word in plaas van 'n 0. Dus in hierdie reël kopieer ons die huidige toestand van die penne na temp.

uit PortB, temp; stuur die 0's en 1's hierbo gelees na PortB

; dit beteken dat ons die LED aan PB0 wil koppel; as PD0 LOW is, sal dit PB0 op LOW stel en draai; op die LED (die ander kant van die LED is gekoppel; aan 5V en dit sal PB0 op 0V stel sodat die stroom vloei)

Nou stuur ons die toestand van die penne in PinD na die PortB -uitvoer. Dit beteken effektief dat PD0 'n 1 na PortD0 sal stuur tensy die knoppie ingedruk word. Aangesien die knoppie op die grond gekoppel is, sal die pen dan op 0V wees en 'n 0 na PortB0 stuur. As u nou na die stroombaandiagram kyk, beteken 0V op PB0 dat die LED sal brand, aangesien die ander kant daarvan 5V is. As ons nie op die knoppie druk nie, sodat 'n 1 na PB0 gestuur word, beteken dit dat ons 5V op PB0 en ook 5V aan die ander kant van die LED het, en daar is dus geen potensiële verskil nie en daar sal geen stroom vloei nie, en die LED sal nie gloei nie (in hierdie geval is dit 'n LED wat 'n diode is, en die stroom vloei slegs een rigting, ongeag, maar wat ook al).

rjmp Main; loop terug na Start

Hierdie relatiewe sprong bring ons terug na ons hoof: etiket, en ons kyk weer na PinD ensovoorts. Kontroleer elke 16 miljoenste van 'n sekonde of die knoppie gedruk word en stel PB0 dienooreenkomstig in.

Oefening 5: Pas u kode aan sodat u LED gekoppel is aan PB3 in plaas van PB0 en kyk of dit werk. Oefening 6: Koppel u LED in plaas van 5V aan GND en verander u kode dienooreenkomstig.

Stap 4: Gevolgtrekking

In hierdie handleiding het ons die monteringstaal vir die ATmega328p verder ondersoek en geleer hoe om 'n LED met 'n drukknop te beheer. Ons het veral die volgende opdragte geleer:

ser register stel al die stukkies van 'n register op 1's

clr register stel al die stukkies van 'n register in op 0's

in register, kopieer i/o register die nommer van 'n i/o register na 'n werkende register

In die volgende tutoriaal ondersoek ons die struktuur van die ATmega328p en die verskillende registers, bewerkings en hulpbronne daarin.

Voordat ek met hierdie tutoriale voortgaan, wag ek en sien die belangstelling. As daar 'n aantal mense is wat dit geniet om te leer hoe om programme vir hierdie mikroverwerker in monteringstaal te kodeer, sal ek voortgaan om meer ingewikkelde stroombane te bou en meer robuuste kode te gebruik.