Tartalomjegyzék:

AVR összeszerelő bemutató 2: 4 lépés
AVR összeszerelő bemutató 2: 4 lépés

Videó: AVR összeszerelő bemutató 2: 4 lépés

Videó: AVR összeszerelő bemutató 2: 4 lépés
Videó: Átalakulás 3...2...1 🌷🌾🌺 2024, Július
Anonim
AVR összeszerelő bemutató 2
AVR összeszerelő bemutató 2

Ez az oktatóanyag az "AVR Assembler Tutorial 1" folytatása

Ha még nem ment át az 1. oktatóanyagon, akkor most hagyja abba, és először ezt tegye meg.

Ebben az oktatóanyagban folytatjuk az Arduino -ban használt atmega328p összeszerelési nyelv programozásának tanulmányozását.

Szükséged lesz:

  1. kenyérsütő Arduino vagy csak egy normál Arduino, mint az 1. bemutatóban
  2. egy LED
  3. 220 ohmos ellenállás
  4. nyomógomb
  5. összekötő vezetékek az áramkör létrehozásához a kenyértábláján
  6. Injekciós készlet kézikönyve: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Adatlap: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Az oktatóanyagok teljes gyűjteménye itt található:

1. lépés: Az áramkör építése

A pálya építése
A pálya építése

Először létre kell hoznia az áramkört, amelyet ebben az oktatóanyagban fogunk tanulmányozni.

Itt van a csatlakoztatás módja:

PB0 (digitális tüske 8) - LED - R (220 ohm) - 5V

PD0 (digitális tüske 0) - nyomógomb - GND

A PB0 helyett a GND -hez csatlakoztatva ellenőrizheti, hogy a LED megfelelően van -e beállítva. Ha nem történik semmi, akkor fordítsa meg az irányt, és a lámpának ki kell gyulladnia. Ezután csatlakoztassa újra a PB0 -hoz, és folytassa. A képen látható, hogyan van csatlakoztatva a kenyérsütő arduino -m.

2. lépés: Az összeszerelési kódex megírása

Az összeszerelési kódex írása
Az összeszerelési kódex írása

Írja be a következő kódot a pushbutton.asm nevű szövegfájlba, és fordítsa le avrával, mint az 1. oktatóanyagban.

Vegye figyelembe, hogy ebben a kódban rengeteg megjegyzésünk van. Minden alkalommal, amikor az összeszerelő pontosvesszőt lát, kihagyja a sor többi részét, és folytatja a következő sort. Jó programozási gyakorlat (különösen az assembly nyelven!), Hogy erősen megjegyzéseket fűz a kódjához, hogy ha a jövőben visszatérjen rá, tudja, mit csinált. Nagyon sokat fogok kommentálni a dolgokat az első néhány oktatóanyagban, hogy pontosan tudjuk, mi történik és miért. Később, ha valamivel jobbak leszünk az összeszerelés kódolásában, kicsit részletesebben írom le a dolgokat.

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

; írta: 1o_o7; dátum: 2014. október 23.; ************************************

.nolista

.include "m328Pdef.inc".list.def temp = r16; jelölje ki az r16 munkaregisztert temp rjmp Init -ként; első sor végrehajtva

Benne:

ser temp; állítson be minden bitet 1 -re. ki DDRB, temp; az 1 -es bit beállítása a Data Direction I/O -n; regisztráljon a PortB -re, amely DDRB, ezt beállítja; pin kimenetként, a 0 ezt a tűt állítja be bemenetként; tehát itt minden PortB pin kimenet (1 -re állítva) ldi temp, 0b11111110; töltse be az "azonnali" számot a temp regiszterbe; ha csak ld lenne, akkor a második érv; memóriahelynek kell lennie ehelyett DDRD, temp; mv temp DDRD -re, az eredmény az, hogy a PD0 bemenet; a többi pedig clr temp kimenet; minden bit temp -ban 0 -ra van állítva PortB, temp; állítsa be a PortB összes bitjét (azaz csapját) 0V ldi temp értékre, 0b00000001; azonnali szám betöltése a PortD, temp; mozgassa a hőmérsékletet a PortD -re. A PD0 felhúzó ellenállással rendelkezik; (azaz 5V -ra állítva), mivel ebben a bitben 1 van; a többi 0V óta 0V.

Fő:

hőmérsékletben, PinD; A PinD a PortD állapotát tartalmazza, másolja ezt a temp -ba; ha a gomb a PD0 -hoz van csatlakoztatva, akkor ez lesz; 0 a gomb megnyomásakor, 1 egyébként; A PD0 felhúzó ellenállással rendelkezik, általában 5 V kimeneti porton, hőmérséklet; elküldi a fent olvasott 0 -kat és 1 -eket a PortB -nek; ez azt jelenti, hogy a LED -et a PB0 -hoz szeretnénk csatlakoztatni; ha a PD0 LOW, akkor a PB0 -t LOW -ra állítja és elfordítja; a LED -en (mivel a LED másik oldala van; 5V -ra van csatlakoztatva, és ez PB0 -t 0V -ra állítja, így áram folyni fog) rjmp Main; visszatér a Main elejére

Vegyük észre, hogy ezúttal nemcsak több megjegyzésünk van a kódunkban, hanem van egy fejlécrészünk is, amely néhány információt tartalmaz arról, hogy ki írta és mikor írta. A kód többi része is szakaszokra van osztva.

Miután összeállította a fenti kódot, töltse fel a mikrokontrollerre, és ellenőrizze, hogy működik -e. A LED -nek világítania kell, miközben megnyomja a gombot, majd újra elalszik, amikor elengedi. Megmutattam, hogy néz ki a képen.

3. lépés: A kód soronkénti elemzése

Kihagyom azokat a sorokat, amelyek pusztán megjegyzések, mivel céljuk magától értetődő.

.nolista

.include "m328Pdef.inc".list

Ez a három sor tartalmazza az általunk programozott ATmega328P regiszterét és bit definícióit tartalmazó fájlt. A.nolist parancs utasítja az összeszerelőt, hogy ne vegye be ezt a fájlt a pushbutton.lst fájlba, amelyet az összeszereléskor készít. Kikapcsolja a listázási lehetőséget. A fájl beillesztése után újra bekapcsoljuk a listázási opciót a.list paranccsal. Ezt azért tesszük, mert az m328Pdef.inc fájl meglehetősen hosszú, és nem igazán kell látnunk a listában. Az összeszerelőnk, az avra, nem generál automatikusan egy listafájlt, és ha szeretnénk egyet, akkor a következő paranccsal állítanánk össze:

avra -l nyomógomb.lst nyomógomb.asm

Ha ezt megteszi, létrehoz egy pushbutton.lst nevű fájlt, és ha megvizsgálja ezt a fájlt, akkor azt fogja találni, hogy a programkódot és további információkat jeleníti meg. Ha megnézi a további információkat, látni fogja, hogy a sorok C -vel kezdődnek: ezt követi a kód hexadecimális számában, ahol a kód a memóriában van. Lényegében 000000 -nál kezdődik az első paranccsal, és onnan növekszik minden további paranccsal. A második oszlop a memória relatív helye után a parancs hexadecimális kódja, majd a parancs argumentumának hexadecimális kódja. A listafájlokat a későbbi oktatóanyagokban tovább tárgyaljuk.

.def hőmérséklet = r16; jelölje ki az r16 munkaregisztert hőm

Ebben a sorban a ".def" összeszerelő utasítást használjuk a "temp" változó azonosítására az r16 "munkaregiszterrel". Az r16 regisztert fogjuk használni, amely tárolja azokat a számokat, amelyeket másolni szeretnénk a különböző portokra és regiszterekre (amelyekre közvetlenül nem lehet írni).

1. gyakorlat: Próbáljon meg egy bináris számot közvetlenül egy portba vagy speciális regiszterbe, például DDRB -be másolni, és nézze meg, mi történik, ha megpróbálja összeállítani a kódot.

A regiszter egy bájt (8 bit) információt tartalmaz. Lényegében általában SR-reteszek gyűjteménye, mindegyik egy "bit", és 1-et vagy 0-t tartalmaz. Ezt a sorozat későbbi szakaszában megvitathatjuk (és akár fel is építhetjük!). Lehet, hogy kíváncsi, mi az a "működő regiszter", és miért az r16 -ot választottuk. Erről egy későbbi oktatóanyagban fogunk beszélni, amikor lemerülünk a chip belső részeinek mocsarába. Egyelőre szeretném, ha megértené, hogyan kell például kódot írni és fizikai hardvert programozni. Ekkor lesz egy referenciakerete a tapasztalatból, amely megkönnyíti a mikrokontroller memória- és regisztrációs tulajdonságait. Tisztában vagyok vele, hogy a legtöbb bevezető tankönyv és beszélgetés ezt fordítva teszi, de azt tapasztaltam, hogy a játék kézikönyvének elolvasása előtt sokkal könnyebb egy videojátékot játszani, hogy átfogó képet kapjunk, mielőtt elolvasnánk a kézikönyvet.

rjmp Init; első sor végrehajtva

Ez a sor "relatív ugrás" az "Init" címkéhez, és itt nem igazán szükséges, mivel a következő parancs már az Init -ben van, de belefoglaljuk a későbbi használatra.

Benne:

ser temp; állítson be minden bitet 1 -re.

Az Init címke után végrehajtunk egy "set register" parancsot. Ezzel a "temp" regiszter 8 bitjét (amire emlékeztet, hogy r16) 1 -re állítja. Tehát a temp most 0b11111111 -et tartalmaz.

ki DDRB, temp; az adatirány I/O regiszterén egy kicsit 1 -re állítva

; a PortB esetében, amely DDRB, ezt a tűt állítja kimenetként; a 0 ezt a tűt állítja be bemenetként; tehát itt minden PortB csatlakozó kimenet (1 -re állítva)

A DDRB regiszter (adatirány -nyilvántartás a PortB -hez) megmondja, hogy a PortB -n lévő csapok (azaz PB0 -PB7) bemenetként vannak -e kijelölve, és melyek kimenetként. Mivel a PB0 csap a LED -hez van csatlakoztatva, a többi nincs csatlakoztatva semmihez, az összes bitet 1 -re állítjuk, vagyis mindegyik kimenet.

ldi temp, 0b11111110; töltse be az "azonnali" számot a temp regiszterbe

; ha csak ld lenne, akkor a második érv lenne; memóriahelynek kell lennie

Ez a sor betölti a 0b11111110 bináris számot a temp regiszterbe.

ki DDRD, temp; mv temp DDRD -re, az eredmény az, hogy a PD0 bemenet és

; a többi kimenet

Most beállítottuk a PortD adatirány -regiszterét a temp -ból, mivel a temp még mindig tartalmazza a 0b11111110 -et, úgy látjuk, hogy a PD0 -t jelölik ki bemeneti tűként (mivel 0 van a jobb szélső helyen), a többit pedig kimenetként jelölik ki, mivel vannak 1 azokon a helyeken.

clr temp; minden bit hőmérsékleten 0 -ra van állítva

ki PortB, temp; állítsa a PortB összes bitjét (azaz csapját) 0V -ra

Először "töröljük" a regiszter hőmérsékletét, ami azt jelenti, hogy az összes bitet nullára kell állítani. Ezután bemásoljuk azt a PortB regiszterbe, amely 0 V -ot állít be ezekre a tűkre. A PortB bit nullája azt jelenti, hogy a processzor 0 V -on tartja a tűt, az egy a bitnél pedig 5 V -ra állítja a tűt.

2. gyakorlat: Multiméterrel ellenőrizze, hogy a PortB összes csapja valóban nulla. Valami furcsa történik a PB1 -el? Valami ötlet, hogy miért lehet ez? (hasonlóan az alábbi 4. gyakorlathoz, majd kövesse a kódot …) 3. gyakorlat: Távolítsa el a fenti két sort a kódjából. A program továbbra is megfelelően fut? Miért?

ldi hőmérséklet, 0b00000001; azonnali szám betöltése a temp -ra

ki PortD, temp; mozgassa a hőmérsékletet a PortD -re. A PD0 5 V -on van (felhúzó ellenállással rendelkezik); mivel ebben a bitben 1 van, a többi 0V. 4. gyakorlat: Távolítsa el a fenti két sort a kódjából. A program továbbra is megfelelően fut? Miért? (Ez eltér a fenti 3. gyakorlattól. Lásd a pin out diagramot. Mi az alapértelmezett DDRD beállítás a PD0 esetében? (Lásd az adatlap 90. oldalát

Először "azonnal betöltjük" a 0b00000001 számot a temp. Az "azonnali" rész ott van, mivel egyenesen felfelé irányuló számot töltünk a temp -ba, és nem mutatót a betöltendő számot tartalmazó memóriahelyre. Ebben az esetben egyszerűen az "ld" -t használjuk az "ldi" helyett. Ezután ezt a számot elküldjük a PortD -nek, amely a PD0 -t 5V -ra, a többit 0V -ra állítja.

Most a csapokat bemenetként vagy kimenetként állítottuk be, és a kezdeti állapotukat 0V vagy 5V (LOW vagy HIGH) értékre állítottuk be, és így belépünk a program "ciklusába".

Fő: hőmérsékletben, PinD; A PinD tartja a PortD állapotát, másolja ezt a temp -ra

; ha a gomb a PD0 -hoz van csatlakoztatva, akkor ez lesz; a 0 a gomb megnyomásakor, 1 egyébként; A PD0 felhúzó ellenállással rendelkezik, általában 5 V -on

A PinD regiszter tartalmazza a PortD csapok aktuális állapotát. Például, ha egy 5 V -os vezetéket csatlakoztatott a PD3 -hoz, akkor a következő órajel ciklusban (ami másodpercenként 16 millió alkalommal történik, mivel a mikrokontrollert 16 MHz -es órajelre kapcsoltuk) a PinD3 bitet (a PD3 jelenlegi állapotából) 1 helyett 1 lett volna. Tehát ebben a sorban a csapok aktuális állapotát átmásoljuk a temp.

ki PortB, temp; elküldi a fent olvasott 0 -kat és 1 -eket a PortB -nek

; ez azt jelenti, hogy a LED -et a PB0 -hoz akarjuk csatlakoztatni, tehát; ha a PD0 alacsony, akkor a PB0 -t LOW -ra állítja, és megfordul; a LED -en (a LED másik oldala csatlakoztatva van; 5V -ra, és ez a PB0 -t 0V -ra állítja, így áram folyik)

Most elküldjük a PinD csapjainak állapotát a PortB kimenetre. Valójában ez azt jelenti, hogy a PD0 1 -et küld a PortD0 -nak, hacsak nem nyomja meg a gombot. Ebben az esetben, mivel a gomb a földhöz van csatlakoztatva, a csap 0V lesz, és 0 -t küld a PortB0 -nak. Most, ha megnézi az áramköri rajzot, a 0V a PB0 -n azt jelenti, hogy a LED világítani fog, mivel a másik oldala 5 V -nál van. Ha nem nyomjuk meg a gombot, így 1 -et küldünk a PB0 -ra, az azt jelenti, hogy 5V van a PB0 -n, és 5V a LED másik oldalán, és így nincs potenciális különbség, és nem áramlik, és így A LED nem fog világítani (ebben az esetben ez egy LED, amely dióda, és így az áram csak egy irányba áramlik, függetlenül attól).

rjmp Fő; visszatér a kezdőlapra

Ez a relatív ugrás visszavezet minket a Main: címkéhez, és újra ellenőrizzük a PinD -t stb. Minden másodperc 16. millió másodpercének ellenőrzése, hogy megnyomják -e a gombot, és ennek megfelelően állítsa be a PB0 -t.

5. gyakorlat: Módosítsa a kódot úgy, hogy a LED a PB3 helyett a PB0 -hoz csatlakozzon, és nézze meg, hogy működik -e. 6. gyakorlat: Csatlakoztassa a LED -et az 5V helyett a GND -hez, és ennek megfelelően módosítsa a kódot.

4. lépés: Következtetés

Ebben az oktatóanyagban tovább vizsgáltuk az ATmega328p összeszerelési nyelvét, és megtanultuk, hogyan lehet egy LED -et nyomógombbal vezérelni. Különösen a következő parancsokat tanultuk meg:

A Ser regiszter a regiszter összes bitjét 1 -re állítja

A clr regiszter a regiszter összes bitjét 0 -ra állítja

a regiszterben az i/o regiszter másolja a számot egy i/o regiszterből egy működő regiszterbe

A következő oktatóanyagban megvizsgáljuk az ATmega328p szerkezetét és az abban található különféle regisztereket, műveleteket és erőforrásokat.

Mielőtt folytatnám ezeket az oktatóanyagokat, várni fogok, és megnézem az érdeklődés szintjét. Ha sok ember élvezi, hogy megtanul programozni programokat ehhez a mikroprocesszorhoz az összeszerelési nyelven, akkor folytatom és bonyolultabb áramköröket fogok készíteni, és robusztusabb kódot használok.

Ajánlott: