Kazalo:

Vadnica za sestavljalec AVR 2: 4 koraki
Vadnica za sestavljalec AVR 2: 4 koraki

Video: Vadnica za sestavljalec AVR 2: 4 koraki

Video: Vadnica za sestavljalec AVR 2: 4 koraki
Video: LDmicro 22: платы Arduino с AVRDUDESS (программирование микроконтроллеров с помощью LDmicro) 2024, Julij
Anonim
Vadnica za sestavljalec AVR 2
Vadnica za sestavljalec AVR 2

Ta vadnica je nadaljevanje "AVR Assembler Tutorial 1"

Če niste šli skozi vadnico 1, se ustavite zdaj in to storite najprej.

V tej vadnici bomo nadaljevali s študijem programiranja montažnega jezika atmega328p, ki se uporablja v Arduinu.

Boste potrebovali:

  1. načrt Arduino ali le navaden Arduino, kot je v vadnici 1
  2. LED
  3. 220 ohmski upor
  4. potisni gumb
  5. povezovalne žice za izdelavo vezja na vaši plošči
  6. Priročnik z nastavitvenim kompletom: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Podatkovni list: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Celotno zbirko mojih vadnic najdete tukaj:

1. korak: Izdelava vezja

Gradnja vezja
Gradnja vezja

Najprej morate sestaviti vezje, ki ga bomo preučili v tej vadnici.

Tu je način povezave:

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

PD0 (digitalni pin 0) - gumb - GND

Ali je vaša LED usmerjena pravilno, lahko preverite tako, da jo namesto PB0 priključite na GND. Če se nič ne zgodi, obrnite orientacijo in lučka naj zasveti. Nato ga znova povežite s PB0 in nadaljujte. Na sliki je prikazano, kako je povezan moj arduino.

2. korak: Pisanje kode montaže

Pisanje skupščinskega kodeksa
Pisanje skupščinskega kodeksa

Naslednjo kodo zapišite v besedilno datoteko, imenovano pushbutton.asm, in jo prevedite z avra, kot ste to storili v vadnici 1.

Upoštevajte, da imamo v tej kodi veliko pripomb. Vsakič, ko sestavljalec vidi podpičje, bo preskočil preostali del vrstice in prešel na naslednjo vrstico. Dobra programska praksa (zlasti v zbirnem jeziku!) Je, da močno komentirate svojo kodo, tako da boste v prihodnosti vedeli, kaj počnete. V prvih nekaj vadnicah bom precej komentiral stvari, da bomo natančno vedeli, kaj se dogaja in zakaj. Kasneje, ko bomo postali nekoliko boljši pri kodiranju montaže, bom stvari komentiral nekoliko manj podrobno.

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

; napisal: 1o_o7; datum: 23. oktober 2014; ************************************

.nolist

.vključi "m328Pdef.inc".list.def temp = r16; delovni register r16 označiti kot temp rjmp Init; prva vrstica izvedena

V:

ser temp; nastavite vse bite v tempu na 1. izhod DDRB, temp; nastavitev bita 1 na V/I podatkovne smeri; register za PortB, ki je DDRB, to določa; pin kot izhod, 0 bi ta pin nastavil kot vhod; zato so tukaj vsi zatiči PortB izhodi (nastavljeno na 1) ldi temp, 0b11111110; naložite "takojšnjo" številko v začasni register; če bi bil samo ld, potem drugi argument; bi moral biti namesto pomnilnika mesto DDRD, temp; mv temp v DDRD, rezultat je, da je vnesen PD0; ostalo pa so izhodi clr temp; vsi biti v tempu so nastavljeni na 0 zunaj PortB, temp; nastavite vse bite (tj. zatiče) v PortB na 0V ldi temp, 0b00000001; naložite takojšnjo številko, da izklopite PortD, temp; premakni temp v PortD. PD0 ima vlečni upor; (tj. nastavljeno na 5V), saj ima 1 v tem bitu; ostali so 0V od 0.

Glavni:

v temp, PinD; PinD ima stanje PortD, kopirajte to v temp; če je gumb priključen na PD0, bo to; 0, ko pritisnete gumb, 1 drugače od takrat; PD0 ima vlečni upor, ki je običajno pri 5V izhodu PortB, temp; pošlje zgoraj prebrane 0 in 1 na PortB; to pomeni, da želimo LED priključiti na PB0,; ko je PD0 LOW, nastavi PB0 na LOW in se obrne; na LED (ker je druga stran LED; priključena na 5V in to bo postavilo PB0 na 0V tako; tok bo tekel) rjmp Main; zanke nazaj na začetek Main

Upoštevajte, da tokrat v kodi nimamo le veliko več komentarjev, ampak imamo tudi razdelek z glavo, ki vsebuje nekaj informacij o tem, kdo je napisal in kdaj je bil napisan. Preostali del kode je prav tako ločen na odseke.

Ko sestavite zgornjo kodo, jo naložite na mikrokrmilnik in preverite, ali deluje. Med pritiskom na gumb se mora prižgati LED in nato znova izklopiti, ko spustite. Kako je videti sem pokazal na sliki.

3. korak: Analiza kode po vrsticah

Preskočil bom vrstice, ki so zgolj komentarji, saj je njihov namen samoumeven.

.nolist

.vključi "m328Pdef.inc".list

Te tri vrstice vključujejo datoteko, ki vsebuje definicije registra in bitov za ATmega328P, ki ga programiramo. Ukaz.nolist pove asemblerju, naj te datoteke ne vključi v datoteko pushbutton.lst, ki jo ustvari, ko jo sestavite. Izklopi možnost seznama. Ko vključimo datoteko, z ukazom.list znova vklopimo možnost seznama. Razlog za to je, ker je datoteka m328Pdef.inc precej dolga in je v resnici ni treba videti v datoteki s seznamom. Naš asembler, avra, ne ustvari samodejno datoteke s seznamom in če jo želimo, jo sestavimo z naslednjim ukazom:

avra -l pushbutton.lst pushbutton.asm

Če to storite, bo ustvarila datoteko, imenovano pushbutton.lst, in če pregledate to datoteko, boste ugotovili, da prikazuje vašo programsko kodo skupaj z dodatnimi informacijami. Če pogledate dodatne informacije, boste videli, da se vrstice začnejo s črko C: nato sledi šestnajsti relativni naslov mesta, kjer je koda shranjena v pomnilniku. V bistvu se začne pri 000000 s prvim ukazom in se od tam naprej povečuje z vsakim naslednjim ukazom. Drugi stolpec za relativnim mestom v pomnilniku je šestnajstiška koda za ukaz, ki ji sledi šestnajstiška koda za argument ukaza. O datotekah s seznamom bomo razpravljali v prihodnjih vajah.

.def temp = r16; delovni register r16 označiti kot temp

V tej vrstici uporabljamo asemblersko direktivo ".def" za definiranje spremenljivke "temp" kot enake r16 "delovnemu registru". Register r16 bomo uporabili kot tistega, ki shranjuje številke, ki jih želimo kopirati v različna vrata in registre (v katere ni mogoče neposredno zapisati).

Vaja 1: Poskusite kopirati binarno številko neposredno v vrata ali poseben register, kot je DDRB, in poglejte, kaj se zgodi, ko poskušate sestaviti kodo.

Register vsebuje bajt (8 bitov) informacij. V bistvu gre običajno za zbirko zapahov SR, od katerih je vsaka "bit" in vsebuje 1 ali 0. O tem se lahko pogovarjamo (in celo sestavimo!) Kasneje v tej seriji. Morda se sprašujete, kaj je "delovni register" in zakaj smo izbrali r16. O tem bomo razpravljali v prihodnji vadnici, ko se potopimo v močvirje notranjosti čipa. Za zdaj želim, da razumete, kako narediti stvari, kot so pisanje kode in programska fizična strojna oprema. Potem boste imeli referenčni okvir iz te izkušnje, ki bo olajšal razumevanje pomnilniških in registrskih lastnosti mikrokrmilnika. Zavedam se, da večina uvodnih učbenikov in razprav to počne obratno, vendar sem ugotovil, da je pred igranjem priročnika z navodili za uporabo nekaj časa najprej videti globalno perspektivo, veliko lažje kot najprej prebrati priročnik.

rjmp Init; prva vrstica izvedena

Ta vrstica je "relativni skok" do oznake "Init" in tukaj ni nujno potrebna, saj je naslednji ukaz že v Initu, vendar ga vključimo za prihodnjo uporabo.

V:

ser temp; nastavite vse bite v tempu na 1.

Po oznaki Init izvedemo ukaz "set register". To nastavi vseh 8 bitov v registru "temp" (za katerega se spomnite, da je r16) na 1. Torej temp zdaj vsebuje 0b11111111.

izhod DDRB, temp; nastavite bit kot 1 v registru V/I podatkovne smeri

; za PortB, ki je DDRB, nastavi ta pin kot izhod; 0 bi nastavil ta pin kot vhod; tako da so tukaj vsi zatiči PortB izhodi (nastavljeno na 1)

Register DDRB (Data Direction Register for PortB) pove, kateri zatiči na PortB (t.j. PB0 do PB7) so označeni kot vhodni in kateri kot izhodni. Ker imamo pin PB0 povezan z našo LED, ostali pa niso povezani z ničemer, bomo vse bite nastavili na 1, kar pomeni, da so vsi izhodi.

ldi temp, 0b11111110; naložite "takojšnjo" številko v začasni register

; če bi bil samo ld, bi drugi argument; mora biti pomnilniška lokacija

Ta vrstica naloži binarno številko 0b11111110 v register temp.

iz DDRD, temp; mv temp na DDRD, rezultat je, da je PD0 vhodni in

; ostalo so rezultati

Zdaj nastavimo register smeri podatkov za PortD iz temp, saj temp še vedno vsebuje 0b11111110, vidimo, da bo PD0 označen kot vhodni pin (ker je 0 na skrajni desni točki), ostali pa kot izhodi, ker obstajajo 1 je na teh mestih.

clr temp; vsi biti v tempu so nastavljeni na 0

izhod PortB, temp; nastavite vse bite (tj. zatiče) v PortB na 0V

Najprej "počistimo" registrsko temp, kar pomeni nastavitev vseh bitov na nič. Nato to kopiramo v register PortB, ki nastavi 0V na vseh teh zatičih. Nič na bitu PortB pomeni, da bo procesor obdržal ta pin pri 0V, ena na bit bo povzročila, da bo ta pin nastavljen na 5V.

Vaja 2: Z multimetrom preverite, ali so vsi zatiči na PortB dejansko nič. Se s PB1 dogaja kaj čudnega? Imate kakšno idejo, zakaj bi to lahko bilo? (podobno kot spodaj vaja 4, nato sledite kodi …) Vaja 3: Iz kode odstranite zgornji dve vrstici. Ali program še vedno deluje pravilno? Zakaj?

ldi temp, 0b00000001; naložite takojšnjo številko na temp

ven PortD, temp; premakni temp v PortD. PD0 je pri 5V (ima upogibni upor); ker ima 1 v tem bitu, so ostale 0V. Vaja 4: Iz kode odstranite zgornji dve vrstici. Ali program še vedno deluje pravilno? Zakaj? (To se razlikuje od zgornje vaje 3. Oglejte si diagram izklopa. Kakšna je privzeta nastavitev DDRD za PD0? (Glejte stran 90 podatkovnega lista

Najprej "takoj naložimo" številko 0b00000001 na temp. "Takojšnji" del je tam, ker nalagamo pravo število navzgor, ne pa kazalec na pomnilniško mesto, ki vsebuje številko za nalaganje. V tem primeru bi namesto "ldi" preprosto uporabili "ld". Nato pošljemo to številko PortD, ki nastavi PD0 na 5V, ostalo pa na 0V.

Zdaj smo nožice nastavili kot vhodne ali izhodne, njihova začetna stanja pa nastavimo na 0V ali 5V (NIZKO ali VISOKO) in tako vstopimo v našo programsko "zanko".

Glavni: v temp, PinD; PinD ima stanje PortD, kopirajte to v temp

; če je gumb priključen na PD0, bo to; a 0, ko pritisnete gumb, 1 drugače od takrat; PD0 ima vlečni upor, ki je običajno pri 5V

Register PinD vsebuje trenutno stanje nožic PortD. Če ste na primer na PD3 priključili žico 5 V, potem pri naslednjem ciklu (kar se zgodi 16 milijonov krat na sekundo, saj imamo mikrokrmilnik priključen na signal takta 16 MHz) pin PinD3 (iz trenutnega stanja PD3) bi postala 1 namesto 0. Torej v tej vrstici kopiramo trenutno stanje nožic v temp.

izhod PortB, temp; pošlje zgoraj prebrane 0 in 1 na PortB

; to pomeni, da želimo LED priključiti na PB0, torej; ko je PD0 LOW, bo nastavil PB0 na LOW in se obrnil; na LED (druga stran LED je priključena; na 5V in to bo postavilo PB0 na 0V, tako da teče tok)

Zdaj pošljemo stanje zatičev v PinD na izhod PortB. To dejansko pomeni, da bo PD0 poslal 1 v PortD0, razen če pritisnete gumb. V tem primeru, ker je gumb priključen na ozemljitev, bo ta pin na 0V in bo poslal 0 na PortB0. Če pogledate diagram vezja, 0V na PB0 pomeni, da bo LED svetila, saj je njegova druga stran pri 5V. Če ne pritisnemo gumba, tako da se 1 pošlje na PB0, bi to pomenilo, da imamo 5V na PB0 in tudi 5V na drugi strani LED, zato ni nobene potencialne razlike in ne bo tekel tok, zato LED ne bo svetila (v tem primeru gre za LED diodo, zato tok teče samo v eno smer, ne glede na to, ne glede na to).

rjmp Main; zanke nazaj na Start

Ta relativni skok nas vrne nazaj na našo oznako Main: in ponovno preverimo PinD itd. Vsakih 16 milijonov milijardin sekunde preverjamo, ali je gumb pritisnjen, in ustrezno nastavimo PB0.

Vaja 5: Spremenite svojo kodo tako, da bo LED dioda namesto PB0 priključena na PB3 in preverite, ali deluje. Vaja 6: Priključite LED v GND namesto v 5 V in ustrezno spremenite svojo kodo.

4. korak: Zaključek

V tej vadnici smo nadalje raziskali montažni jezik za ATmega328p in se naučili, kako upravljati LED z gumbom. Zlasti smo se naučili naslednjih ukazov:

ser register nastavi vse bite v registru na 1

clr register nastavi vse bite registra na 0

v registru, v/o register kopira številko iz v/i registra v delovni register

V naslednji vadnici bomo preučili strukturo ATmega328p in različne registre, operacije in vire, ki jih vsebuje.

Preden nadaljujem s temi vajami, bom počakal in videl stopnjo zanimanja. Če obstaja veliko ljudi, ki se dejansko naučijo kodirati programe za ta mikroprocesor v zbirnem jeziku, bom nadaljeval in gradil bolj zapletena vezja in uporabil robustnejšo kodo.

Priporočena: