Sadržaj:

AVR Assembler Vodič 2: 4 koraka
AVR Assembler Vodič 2: 4 koraka

Video: AVR Assembler Vodič 2: 4 koraka

Video: AVR Assembler Vodič 2: 4 koraka
Video: Лекция 4. Архитектура AVR. Ассемблер 2024, Juli
Anonim
Vodič za AVR asembler 2
Vodič za AVR asembler 2

Ovaj vodič je nastavak "AVR Assembler Tutorial 1"

Ako niste prošli vodič 1, trebali biste odmah prestati i prvo to učiniti.

U ovom vodiču nastavit ćemo proučavanje programiranja na asemblerskom jeziku atmega328p koji se koristi u Arduinu.

Trebat će vam:

  1. matična ploča Arduino ili samo obični Arduino kao u vodiču 1
  2. LED
  3. otpornik od 220 ohma
  4. dugme za pritiskanje
  5. spojne žice za stvaranje kruga na vašoj ploči
  6. Upute za postavljanje uputa: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Tehnički list: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Kompletnu zbirku mojih vodiča možete pronaći ovdje:

Korak 1: Izgradnja kruga

Izgradnja kola
Izgradnja kola

Prvo morate izgraditi sklop koji ćemo proučavati u ovom vodiču.

Evo kako je to povezano:

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

PD0 (digitalni pin 0) - tipka - GND

Možete provjeriti je li vaša LED dioda pravilno orijentirana tako što ćete je spojiti na GND umjesto na PB0. Ako se ništa ne dogodi, promijenite orijentaciju i svjetlo bi se trebalo upaliti. Zatim ga ponovno spojite na PB0 i nastavite. Slika prikazuje kako je moj arduino spojen na matičnu ploču.

Korak 2: Pisanje skupštinskog koda

Pisanje skupštinskog zakona
Pisanje skupštinskog zakona

Napišite sljedeći kôd u tekstualnu datoteku koja se zove pushbutton.asm i kompajlirajte je sa avra kao što ste to učinili u vodiču 1.

Primijetite da u ovom kodu imamo dosta komentara. Svaki put kada asembler vidi točku -zarez preskočit će ostatak retka i preći na sljedeći red. Dobra je programska praksa (posebno na asemblerskom jeziku!) Da jako komentirate svoj kôd, tako da ćete, kad se ubuduće vratite na njega, znati šta radite. Dosta ću komentirati stvari u prvih nekoliko vodiča kako bismo točno znali što se događa i zašto. Kasnije, kad postanemo bolji u montažnom kodiranju, komentirat ću stvari malo manje detaljno.

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

; napisao: 1o_o7; datum: 23. oktobar 2014.; ************************************

.nolist

.include "m328Pdef.inc".list.def temp = r16; radni registar r16 označiti kao temp rjmp Init; prvi red izvršen

U tome:

ser temp; postavite sve bitove u temp na 1. izlaz DDRB, temp; postavljanje bita kao 1 na Data Direction I/O; registar za PortB, koji je DDRB, to postavlja; pin kao izlaz, 0 bi postavilo taj pin kao ulaz; pa ovdje su svi PortB pinovi izlazi (postavljeni na 1) ldi temp, 0b11111110; učitati `neposredni 'broj u privremeni registar; da je samo ld onda drugi argument; morala bi biti memorijska lokacija umjesto DDRD -a, temp; mv temp za DDRD, rezultat je da je PD0 unos; a ostalo su izlazi clr temp; svi bitovi u temp postavljeni su na 0 out PortB, temp; postavite sve bitove (tj. pinove) u PortB na 0V ldi temp, 0b00000001; učitati trenutni broj za tempiranje Out PortD, temp; premjesti temp na PortD. PD0 ima pull -up otpornik; (tj. postavljeno na 5V) budući da ima 1 u tom bitu; ostali su 0V od 0.

Glavni:

u temp, PinD; PinD drži stanje PortD, kopirajte ovo na temp; ako je dugme spojeno na PD0 to će biti; 0 kada je dugme pritisnuto, 1 u suprotnom od; PD0 ima pull -up otpornik koji je obično na 5V izlaznom portB, temp; šalje gore pročitane 0 i 1 na PortB; to znači da želimo LED diodu priključenu na PB0,; kada je PD0 LOW, postavlja PB0 na LOW i okreće; na LED -u (budući da je druga strana LED -a; spojena na 5V i ovo će postaviti PB0 na 0V pa će struja teći) rjmp Main; petlje natrag na početak Main -a

Primijetite da ovaj put ne samo da imamo mnogo više komentara u kodu, već imamo i odjeljak zaglavlja koji daje neke informacije o tome ko ga je napisao i kada je napisan. Ostatak koda je takođe podeljen na odeljke.

Nakon što ste sastavili gornji kod, trebali biste ga učitati na mikrokontroler i provjeriti radi li. LED dioda bi se trebala uključiti dok pritisnete dugme, a zatim se ponovo ugasiti kada je pustite. Na slici sam pokazao kako to izgleda.

Korak 3: Analiza koda po liniju

Preskočit ću redove koji su samo komentari jer je njihova svrha sama po sebi razumljiva.

.nolist

.include "m328Pdef.inc".list

Ove tri linije uključuju datoteku koja sadrži definicije registra i bita za ATmega328P koji programiramo. Naredba.nolist govori asembleru da ne uključuje ovu datoteku u datoteku pushbutton.lst koju proizvodi kada je sastavite. Isključuje opciju unosa. Nakon uključivanja datoteke ponovo uključujemo opciju listinga naredbom.list. Razlog zašto to radimo je zato što je datoteka m328Pdef.inc prilično duga i ne moramo je vidjeti u datoteci liste. Naš asembler, avra, ne generira automatski datoteku liste i ako bismo je htjeli, sastavili bismo je pomoću sljedeće naredbe:

avra -l pushbutton.lst pushbutton.asm

Ako to učinite, generirat će se datoteka koja se naziva pushbutton.lst, a ako pregledate ovu datoteku, vidjet ćete da prikazuje vaš programski kod zajedno s dodatnim informacijama. Ako pogledate dodatne informacije, vidjet ćete da redovi počinju s C: nakon čega slijedi relativna adresa u heksadecatnom broju gdje se kôd nalazi u memoriji. U osnovi počinje s 000000 prvom naredbom i od tada se povećava sa svakom narednom naredbom. Druga kolona nakon relativnog mjesta u memoriji je heksadecimalni kôd za naredbu nakon kojeg slijedi heksadecimalni kôd za argument naredbe. O datotekama liste ćemo dalje raspravljati u budućim vodičima.

.def temp = r16; radni registar r16 označiti kao temp

U ovoj liniji koristimo asemblersku direktivu ".def" da definiramo varijablu "temp" kao jednaku r16 "radni registar". Registar r16 koristit ćemo kao onaj koji pohranjuje brojeve koje želimo kopirati na različite portove i registre (na koje se ne može direktno pisati).

Vježba 1: Pokušajte kopirati binarni broj izravno u port ili poseban registar poput DDRB -a i vidjeti što će se dogoditi kada pokušate sastaviti kôd.

Registar sadrži bajt (8 bita) informacija. U suštini, to je obično zbirka SR-zasuna, svaki je "bit" i sadrži 1 ili 0. O ovome (pa čak i izgradnji!) Možemo razgovarati kasnije u ovoj seriji. Možda se pitate što je "radni registar" i zašto smo odabrali r16. O tome ćemo raspravljati u budućem vodiču kada zaronimo u močvaru unutrašnjosti čipa. Za sada želim da razumijete kako raditi stvari poput pisanja koda i programiranja fizičkog hardvera. Tada ćete imati referentni okvir iz tog iskustva koji će olakšati razumijevanje svojstava memorije i registra mikrokontrolera. Shvaćam da većina uvodnih udžbenika i diskusija to čini obrnuto, ali otkrio sam da je igranje video igre neko vrijeme da biste stekli globalnu perspektivu prije čitanja priručnika s uputama mnogo lakše nego prvo čitanje priručnika.

rjmp Init; prvi red izvršen

Ova linija je "relativni skok" na oznaku "Init" i ovdje nije potrebna jer je sljedeća naredba već u Initu, ali je uključujemo za buduću upotrebu.

U tome:

ser temp; postavite sve bitove u temp na 1.

Nakon oznake Init izvršavamo naredbu "set register". Ovo postavlja svih 8 bita u registru "temp" (kojih se sjećate da je r16) na 1. Dakle, temp sada sadrži 0b11111111.

izlaz DDRB, temp; postavljanje bita kao 1 u Data Direction I/O registru

; za PortB, koji je DDRB, postavlja taj pin kao izlaz; 0 bi postavilo taj pin kao ulaz; pa ovdje su svi PortB pinovi izlazi (postavljeno na 1)

Registar DDRB (Data Direction Register for PortB) govori koji su pinovi na PortB (tj. PB0 do PB7) označeni kao ulazi, a koji kao izlazi. Budući da imamo pin PB0 spojen na našu LED diodu, a ostali nisu povezani ni na što, sve bitove ćemo postaviti na 1, što znači da su svi izlazi.

ldi temp, 0b11111110; učitati `neposredni 'broj u privremeni registar

; da je samo ld, drugi argument bi; mora biti memorijska lokacija

Ova linija učitava binarni broj 0b11111110 u registar temp.

izlaz DDRD, temp; mv temp na DDRD, rezultat je da je PD0 ulazni i

; ostalo su rezultati

Sada postavljamo Registar smjera podataka za PortD iz temp, budući da temp još uvijek sadrži 0b11111110 vidimo da će PD0 biti označen kao ulazni pin (budući da na krajnjem desnom mjestu postoji 0), a ostali su označeni kao izlazi budući da postoje 1 je na tim mestima.

clr temp; svi bitovi u temp su postavljeni na 0

izlaz PortB, temp; postavite sve bitove (tj. pinove) u PortB na 0V

Prvo "očistimo" temperaturu registra što znači postavljanje svih bitova na nulu. Zatim to kopiramo u PortB registar koji postavlja 0V na sve te pinove. Nula na PortB bitu znači da će procesor zadržati taj pin na 0V, jedan na bitu će uzrokovati da se taj pin postavi na 5V.

Vježba 2: Pomoću multimetra provjerite jesu li svi pinovi na PortB zapravo nuli. Događa li se nešto čudno s PB1? Imaš li ideju zašto bi to moglo biti? (slično donjoj vježbi 4, zatim slijedite kôd …) Vježba 3: Uklonite gornja dva retka iz koda. Da li program i dalje radi ispravno? Zašto?

ldi temp, 0b00000001; učitati trenutni broj na temp

izlaz PortD, temp; premjesti temp na PortD. PD0 je na 5V (ima pullup otpornik); budući da ima 1 u tom bitu, ostale su 0V. Vježba 4: Uklonite gornja dva retka iz koda. Da li program i dalje radi ispravno? Zašto? (Ovo se razlikuje od gore navedene vježbe 3. Pogledajte dijagram izvlačenja. Koja je zadana postavka DDRD -a za PD0? (Pogledajte stranicu 90 u listu sa podacima

Prvo "učitavamo odmah" broj 0b00000001 na temp. "Neposredni" dio postoji jer učitavamo ravan broj za temp, a ne pokazivač na memorijsku lokaciju koja sadrži broj za učitavanje. U tom slučaju jednostavno bismo koristili "ld" umjesto "ldi". Zatim šaljemo ovaj broj PortD -u koji postavlja PD0 na 5V, a ostatak na 0V.

Sada smo postavili pinove kao ulazne ili izlazne i postavili smo njihova početna stanja ili na 0V ili na 5V (LOW ili HIGH) pa ulazimo u naš program "loop".

Main: in temp, PinD; PinD drži stanje PortD, kopirajte ovo na temp

; ako je dugme spojeno na PD0, to će biti; a 0 kada je dugme pritisnuto, 1 inače od tada; PD0 ima pull -up otpornik koji je obično na 5V

Registar PinD sadrži trenutno stanje PortD pinova. Na primjer, ako ste na PD3 priključili žicu od 5 V, tada će u sljedećem ciklusu takta (što se događa 16 miliona puta u sekundi budući da imamo mikrokontroler spojen na signal takta od 16 MHz) pinD3 bit (iz trenutnog stanja PD3) bi postalo 1 umjesto 0. Dakle, u ovoj liniji kopiramo trenutno stanje pinova u temp.

izlaz PortB, temp; šalje gore pročitane 0 i 1 na PortB

; to znači da želimo da je LED spojen na PB0, pa; kada je PD0 LOW, postavit će PB0 na LOW i okrenuti se; na LED -u (druga strana LED -a je spojena; na 5V i ovo će postaviti PB0 na 0V tako da struja teče)

Sada šaljemo stanje pinova u PinD -u na izlaz PortB. To efektivno znači da će PD0 poslati 1 na PortD0 osim ako se ne pritisne dugme. U tom slučaju, budući da je gumb spojen na masu, taj pin će biti na 0V i poslat će 0 na PortB0. Sada, ako pogledate dijagram kruga, 0V na PB0 znači da će LED svijetliti jer je njegova druga strana na 5V. Ako ne pritisnemo dugme, tako da se 1 pošalje na PB0, to bi značilo da imamo 5V na PB0 i 5V na drugoj strani LED -a, pa nema razlike u potencijalu i neće teći struja, pa će LED neće svijetliti (u ovom slučaju to je LED dioda pa struja teče samo u jednom smjeru bez obzira na sve).

rjmp Main; petlje natrag na Start

Ovaj relativni skok vraća nas nazad do naše oznake Main: ponovo provjeravamo PinD i tako dalje. Svakih 16 milionitih sekundi provjerava se da li se dugme pritisne i prema tome postavlja PB0.

Vježba 5: Izmijenite kôd tako da vaša LED dioda bude spojena na PB3 umjesto na PB0 i provjerite radi li. Vježba 6: Uključite LED u GND umjesto u 5V i prema tome izmijenite kôd.

Korak 4: Zaključak

U ovom smo vodiču dodatno istražili sklopni jezik za ATmega328p i naučili kako kontrolirati LED sa tipkom. Posebno smo naučili sljedeće naredbe:

ser register postavlja sve bitove registra na 1

clr registar postavlja sve bitove registra na 0

u registru, i/o registar kopira broj iz i/o registra u radni registar

U sljedećem vodiču ćemo ispitati strukturu ATmega328p i različite registre, operacije i resurse koji se u njoj nalaze.

Prije nego nastavim s ovim vodičima, pričekat ću i vidjeti nivo interesa. Ako postoji određeni broj ljudi koji uživaju u učenju kako kodirati programe za ovaj mikroprocesor na asemblerskom jeziku, tada ću nastaviti i konstruirati složenija kola i koristiti robusniji kod.

Preporučuje se: