Sadržaj:
- Korak 1: Izgradnja kruga
- Korak 2: Pisanje koda montaže
- Korak 3: Line-by-line analiza koda
- Korak 4: Zaključak
Video: AVR asemblerski vodič 2: 4 koraka
2024 Autor: John Day | [email protected]. Zadnja promjena: 2024-01-30 09:31
Ovaj vodič je nastavak "AVR Assembler Tutorial 1"
Ako niste prošli Tutorial 1, trebali biste odmah prestati i prvo to učiniti.
U ovom ćemo vodiču nastaviti s proučavanjem programiranja na asemblerskom jeziku atmega328p koji se koristi u Arduinu.
Trebat će vam:
- matična ploča Arduino ili samo normalni Arduino kao u Vodiču 1
- LED dioda
- otpornik od 220 ohma
- pritisni gumb
- spojne žice za stvaranje kruga na vašoj ploči
- Priručnik s uputama: www.atmel.com/images/atmel-0856-avr-instruction-s…
- Tehnički list: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
Cjelovitu zbirku mojih vodiča možete pronaći ovdje:
Korak 1: Izgradnja kruga
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) - gumb - GND
Možete provjeriti je li LED ispravno orijentiran tako da ga spojite 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 ploču.
Korak 2: Pisanje koda montaže
Napišite sljedeći kôd u tekstualnu datoteku pod nazivom pushbutton.asm i kompajlirajte je s avrom kao što ste to učinili u Vodiču 1.
Uočite 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 redak. Dobra je programska praksa (osobito na asemblerskom jeziku!) Da jako komentirate svoj kôd tako da ćete, kad se ubuduće vratite na njega, znati što 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 malo bolji u kodiranju montaže, komentirat ću stvari malo manje.
;************************************
; napisao: 1o_o7; datum: 23. listopada 2014.; **********************************
.nolist
.uključuje "m328Pdef.inc".list.def temp = r16; radni registar r16 označiti kao temp rjmp Init; izvršen prvi redak
U tome:
ser temp; postavite sve bitove u temp na 1. izlaz DDRB, temp; postavljanje bita kao 1 na U/I podatkovnog smjera; 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 (postavljeno 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 su bitovi u temp postavljeni na 0 izvan 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 u 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 gumb spojen na PD0 to će biti; 0 kada je gumb pritisnut, 1 inače od; PD0 ima pull -up otpornik koji je obično na 5V izlaza PortB, temp; šalje gore očitane 0 i 1 na PortB; to znači da želimo da je LED spojen na PB0,; kad 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 to će postaviti PB0 na 0V pa; struja će teći) rjmp Main; petlje natrag na početak Main -a
Uočite da ovaj put ne samo da imamo mnogo više komentara u kodu, već imamo i odjeljak zaglavlja koji daje neke podatke o tome tko ga je napisao i kada je napisan. Ostatak koda također je podijeljen u odjeljke.
Nakon što ste sastavili gornji kod, trebate ga učitati na mikrokontroler i provjeriti radi li. LED dioda bi se trebala uključiti dok pritisnete gumb, a zatim se ponovno isključiti kad je pustite. Na slici sam pokazao kako to izgleda.
Korak 3: Line-by-line analiza koda
Preskočit ću retke koji su samo komentari jer je njihova svrha sama po sebi razumljiva.
.nolist
.uključuje "m328Pdef.inc".list
Ova tri retka 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 ponovno uključujemo opciju unosa pomoću naredbe.list. Razlog zašto to radimo je taj što je datoteka m328Pdef.inc prilično duga i ne moramo je vidjeti u datoteci s popisom. Naš asembler, avra, ne generira automatski datoteku popisa i ako bismo je htjeli, sastavili bismo je pomoću sljedeće naredbe:
avra -l tipkalo.prvo dugme.asm
Ako to učinite, generirat će se datoteka pushbutton.lst, a ako pregledate ovu datoteku, vidjet ćete da prikazuje vaš programski kod zajedno s dodatnim podacima. Ako pogledate dodatne informacije, vidjet ćete da retci počinju s C: nakon čega slijedi relativna adresa u heksadecatnom broju mjesta gdje se kôd nalazi u memoriji. U biti počinje s 000000 s prvom naredbom i od tada se povećava sa svakom narednom naredbom. Drugi stupac nakon relativnog mjesta u memoriji je heksadecimalni kôd za naredbu nakon kojeg slijedi heksadecimalni kôd za argument naredbe. O datotekama popisa ćemo dalje raspravljati u budućim vodičima.
.def temp = r16; radni registar r16 označiti kao temp
U ovom retku koristimo asemblersku direktivu ".def" za definiranje varijable "temp" jednakom r16 "radnom registru". Registar r16 koristit ćemo za pohranu brojeva koje želimo kopirati na različite portove i registre (na koje se ne može izravno zapisati).
Vježba 1: Pokušajte kopirati binarni broj izravno u priključak 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 biti, to je obično zbirka SR-zasuna, svaki je "bit" i sadrži 1 ili 0. O tome ćemo raspravljati (pa čak i izgraditi jedno!) 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. Zasad ž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 rasprava to čini obrnuto, ali otkrio sam da je igranje videoigre neko vrijeme prije stjecanja globalne perspektive prije čitanja priručnika s uputama mnogo lakše nego prvo čitanje priručnika.
rjmp Init; izvršen prvi redak
Ovaj redak je "relativni skok" do oznake "Init" i ovdje zapravo nije potreban jer je sljedeća naredba već u Initu, ali mi 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". Time se svih 8 bitova u registru "temp" (za koje pamtite da je r16) postavlja na 1. Dakle, temp sada sadrži 0b11111111.
izlaz DDRB, temp; postavljanjem bita kao 1 u U/I registru smjera podataka
; 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 s čim, 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 tada bi drugi argument; moraju biti memorijsko mjesto
Ova linija učitava binarni broj 0b11111110 u registar temp.
van DDRD, temp; mv temp za DDRD, rezultat je da je PD0 ulazni i
; ostalo su izlazi
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 mjestima.
clr temp; svi su bitovi u temp 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 bit znači da će procesor zadržati taj pin na 0V, jedan na bit ć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. Radi li program i dalje ispravno? Zašto?
ldi temp, 0b00000001; učitati trenutni broj na temp
izlaz PortD, temp; premjesti temp u 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. Radi li program i dalje ispravno? Zašto? (Ovo se razlikuje od gore navedene vježbe 3. Pogledajte dijagram isklapanja. Koja je zadana postavka DDRD -a za PD0? (Pogledajte stranicu 90 u podatkovnom listu
Prvo "učitavamo odmah" broj 0b00000001 na temp. "Neposredni" dio postoji jer učitavamo izravni broj za temp, a ne pokazivač na memorijsko mjesto koje sadrži broj za učitavanje. U tom slučaju jednostavno bismo koristili "ld", a ne "ldi". Zatim šaljemo ovaj broj PortD -u koji postavlja PD0 na 5V, a ostatak na 0V.
Sada smo postavili pinove kao ulazne ili izlazne, a njihova početna stanja smo postavili kao 0V ili 5V (NISKO ili VISOKO) pa ulazimo u našu petlju programa.
Glavni: in temp, PinD; PinD drži stanje PortD, kopirajte ovo na temp
; ako je gumb spojen na PD0, to će biti; a 0 kada se pritisne gumb, 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 priključili žicu od 5 V na PD3, tada će u sljedećem ciklusu takta (što se događa 16 milijuna puta u sekundi budući da imamo mikrokontroler spojen na signal takta od 16 MHz) pinD3 bit (iz trenutnog stanja PD3) postalo bi 1 umjesto 0. Dakle, u ovom retku 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, dakle; kad je PD0 LOW, postavit će PB0 na LOW i okrenuti se; na LED -u (druga strana LED -a je spojena; na 5V i to će postaviti PB0 na 0V tako da struja teče)
Sada šaljemo stanje pinova u PinD na izlaz PortB. U stvari, to znači da će PD0 poslati 1 na PortD0 osim ako se ne pritisne gumb. 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 budući da mu je druga strana na 5V. Ako ne pritisnemo gumb, pa se 1 pošalje na PB0, to bi značilo da imamo 5V na PB0, a također 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 natrag do naše oznake Main: ponovno provjeravamo PinD i tako dalje. Provjerava se svakih 16 milionitih dijelova sekunde pritiska li se gumb i prema tome postavlja PB0.
Vježba 5: Izmijenite svoj 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 svoj kôd.
Korak 4: Zaključak
U ovom smo vodiču dodatno istražili sklopni jezik za ATmega328p i naučili kako upravljati LED diodom pritiskom na gumb. 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 razinu interesa. Ako postoji određeni broj ljudi koji uživaju naučiti kodirati programe za ovaj mikroprocesor na asemblerskom jeziku, nastavit ću i konstruirati složenije sklopove i koristiti robusniji kod.
Preporučeni:
AVR asemblerski vodič 1: 5 koraka
AVR Assembler Vodič 1: Odlučio sam napisati niz vodiča o tome kako napisati programe na asemblerskom jeziku za Atmega328p koji je mikrokontroler koji se koristi u Arduinu. Ako ljudi ostanu zainteresirani, nastavit ću s izlaganjem otprilike tjedno dok mi ne ponestane
AVR asemblerski vodič 6: 3 koraka
AVR Assembler Tutorial 6: Dobro došli u Tutorial 6! Današnji vodič bit će kratak u kojem ćemo razviti jednostavnu metodu za prijenos podataka između jednog atmega328p i drugog pomoću dva priključka koji ih povezuju. Zatim ćemo uzeti valjak za kockice iz Vodiča 4 i Registra
AVR asemblerski vodič 8: 4 koraka
AVR Assembler Vodič 8: Dobro došli u Vodič 8! U ovom kratkom vodiču ćemo se malo udaljiti od uvođenja novih aspekata programiranja asemblerskog jezika kako bismo pokazali kako premjestiti naše komponente za izradu prototipova u zasebni "ispisani" pločica
AVR asemblerski vodič 7: 12 koraka
AVR Assembler Tutorial 7: Dobro došli u Tutorial 7! Danas ćemo prvo pokazati kako očistiti tipkovnicu, a zatim ćemo pokazati kako koristiti analogne ulazne portove za komunikaciju s tipkovnicom. To ćemo učiniti pomoću prekida i jedne žice kao ulazni. Ožičit ćemo tipkovnicu tako da
AVR asemblerski vodič 9: 7 koraka
AVR Assembler Tutorial 9: Dobro došli u Tutorial 9. Danas ćemo pokazati kako upravljati i 7-segmentnim zaslonom i 4-znamenkastim zaslonom koristeći naš kod za montažni jezik ATmega328P i AVR. Tijekom toga ćemo morati skrenuti pažnju na to kako koristiti stog