Tartalomjegyzék:

AVR összeszerelő bemutató 3: 9 lépés
AVR összeszerelő bemutató 3: 9 lépés

Videó: AVR összeszerelő bemutató 3: 9 lépés

Videó: AVR összeszerelő bemutató 3: 9 lépés
Videó: LCS3 bemutató #3 - Kihúzható fiók 2024, Július
Anonim
AVR összeszerelő oktatóanyag 3
AVR összeszerelő oktatóanyag 3

Üdvözöljük a 3 -as oktatóanyagban!

Mielőtt elkezdenénk, szeretnék egy filozófiai pontot tenni. Ne féljen kísérletezni az áramkörökkel és a kódokkal, amelyeket ezekben az oktatóanyagokban építünk fel. Cserélje ki a vezetékeket, adjon hozzá új alkatrészeket, vegye ki az alkatrészeket, változtassa meg a kódsorokat, adjon hozzá új sorokat, törölje a sorokat, és nézze meg, mi történik! Nagyon nehéz bármit megtörni, és ha mégis, kit érdekel? Semmi, amit használunk, beleértve a mikrokontrollert sem, nagyon drága, és mindig tanulságos látni, hogyan sikertelenek a dolgok. Nem csak azt fogja megtudni, hogy mit ne tegyen legközelebb, de ami még fontosabb, azt is, hogy miért nem teszi meg. Ha olyan vagy, mint én, gyerekkorodban, és új játékot kaptál, nem sokkal később darabokra kellett szedned, hogy kiderüljön, mitől lett jó? Néha a játék helyrehozhatatlanul megsérült, de nem nagy baj. Ha lehetővé teszi a gyermek számára, hogy akár a törött játékokig is felfedezze kíváncsiságát, az tudóssá vagy mérnökké változtatja mosogatógép helyett.

Ma egy nagyon egyszerű áramkört fogunk bekötni, majd kicsit belemerülünk az elméletbe. Sajnáljuk, de szükségünk van az eszközökre! Ígérem, hogy ezt pótoljuk a 4. oktatóanyagban, ahol komolyabb körépítést fogunk végezni, és az eredmény nagyon jó lesz. Mindazonáltal az összes oktatóanyag elvégzésének módja nagyon lassú, elmélkedő. Ha csak szántja magát, felépíti az áramkört, másolja és illessze be a kódot, majd futtassa, akkor biztos, hogy működni fog, de nem fog tanulni semmit. Gondolkodni kell minden soron. Szünet. Kísérlet. Feltalálni. Ha így teszel, akkor az ötödik bemutató végére leállsz a jó dolgok építésével, és nincs szükség több korrepetálásra. Ellenkező esetben egyszerűen figyel, nem pedig tanul és alkot.

Mindenesetre elég filozófia, kezdjük el!

Ebben az oktatóanyagban szüksége lesz:

  1. a prototípus -tábláját
  2. egy LED
  3. összekötő vezetékek
  4. 220-330 ohm körüli ellenállás
  5. A használati utasítás: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. Az adatlap: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. egy másik kristály oszcillátor (opcionális)

Itt található egy link az oktatóanyagok teljes gyűjteményéhez:

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

Az áramkör építése
Az áramkör építése

A bemutató áramköre rendkívül egyszerű. Lényegében meg fogjuk írni a "villog" programot, így csak a következőkre van szükségünk.

Csatlakoztasson egy LED -et a PD4 -hez, majd egy 330 ohmos ellenálláshoz, majd a földeléshez. azaz

PD4 - LED - R (330) - GND

és ennyi!

Az elmélet azonban nagyon nehéz lesz…

2. lépés: Miért van szükségünk a megjegyzésekre és az M328Pdef.inc fájlra?

Szerintem kezdjük azzal, hogy bemutatjuk, miért hasznosak az include fájl és a megjegyzések. Egyikre sincs szükség, és nélkülük ugyanúgy írhat, összeállíthat és feltölthet kódot, és tökéletesen fog futni (bár az include fájl nélkül panaszokat kaphat az összeszerelőtől - de nincs hiba)

Íme a kód, amelyet ma írni fogunk, kivéve, hogy eltávolítottam a megjegyzéseket és az include fájlt:

.eszköz ATmega328P

.org 0x0000 jmp a.org 0x0020 jmp ea: ldi r16, 0x05 out 0x25, r16 ldi r16, 0x01 sts 0x6e, r16 sei clr r16 out 0x26, r16 sbi 0x0a, 0x04 sbi 0x0b, 0x04 b: sbi 0x0b, cxx cbi 0x0b, 0x04 rcall c rjmp bc: clr r17 d: cpi r17, 0x1e brne d ret e: inc r17 cpi r17, 0x3d brne PC+2 clr r17 reti

elég egyszerű ugye? Haha. Ha összeállította és feltöltötte ezt a fájlt, a LED másodpercenként 1 villogás sebességgel fog villogni, a villogás 1/2 másodpercig tart, és a villogások közötti szünet 1/2 másodpercig tart.

Ennek a kódnak a megtekintése azonban aligha világos. Ha ilyen kódot írna, és a jövőben módosítani vagy újrafelhasználni szeretné, akkor nehéz dolga lenne.

Tehát tegyük vissza a megjegyzéseket, és tegyük vissza a fájlt, hogy megértsük.

3. lépés: Blink.asm

Íme a kód, amelyet ma megvitatunk:

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

; írta: 1o_o7; dátum:; verzió: 1.0; fájl mentve: blink.asm; AVR esetén: atmega328p; órajel frekvencia: 16MHz (opcionális); ************************************* Program funkció: ---------------------; LED -ek villogásával számolja a másodperceket;; PD4 - LED - R (330 ohm) - GND;; --------------------------------------.nolist.include "./m328Pdef.inc".list; ==============; Nyilatkozatok:.def temp = r16.def overflows = r17.org 0x0000; memória (PC) a reset kezelő helye rjmp Reset; A jmp 2 processzoros ciklusba kerül, az rjmp pedig csak 1 -be; tehát hacsak nem kell 8k bájtnál többet ugrani; csak rjmp kell. Ezért csak néhány mikrokontroller; legyen rjmp és ne jmp.org 0x0020; a Timer0 túlcsorduláskezelő memóriahelye rjmp overflow_handler; menjen ide, ha timer0 túlcsordulás megszakad; ============ Reset: ldi temp, 0b00000101 out TCCR0B, temp; állítsa a CS00, CS01, CS02 órajelválasztó biteket 101 -re; ez az időzítő számlálót, a TCNT0 -t FCPU/1024 módba állítja; így ketyeg a CPU frekvencia/1024 ldi temp, 0b00000001 sts TIMSK0, temp; állítsa be az időzítő túlcsordulás megszakítás engedélyezése (TOIE0) bitet; az időzítő megszakítási maszk regiszter (TIMSK0) sei; globális megszakítások engedélyezése - egyenértékű az "sbi SREG, I" clr temp out TCNT0, temp; inicializálja az időzítőt/számlálót 0 sbi DDRD -re, 4; állítsa PD4 kimenetre; ======================; A program fő része: villog: sbi PORTD, 4; kapcsolja be a LED -et a PD4 rcall késleltetésén; késleltetés 1/2 másodperc cbi PORTD, 4; kapcsolja ki a LED -et a PD4 rcall késleltetésén; a késleltetés 1/2 másodperces rjmp villogás lesz; hurok vissza a start késleltetéshez: clr túlcsordul; állítsa a túlcsordulásokat 0 sec_count értékre: cpi túlcsordulások, 30; hasonlítsa össze a túlcsordulások számát és 30 brne sec_count; elágazás vissza a sec_count -hoz, ha nem egyenlő ret; ha 30 túlcsordulás történt, térjen vissza a villogó overflow_handler -hez: inc overflows; adjunk hozzá 1 -et a túlcsordulásokhoz változó cpi túlcsordulások, 61; összehasonlítás 61 brne PC+2 -vel; Program számláló + 2 (ugrás a következő sorra), ha nem egyenlő clr túlcsordulás; ha 61 túlcsordulás történt, állítsa vissza a számlálót nullára; visszatér a megszakításból

Amint látja, a megjegyzéseim most egy kicsit rövidebbek. Ha már tudjuk, hogy az utasításkészletben milyen parancsok vannak, nem kell ezt magyaráznunk a megjegyzésekben. Csak a program szempontjából kell elmagyaráznunk, hogy mi történik.

Részben megbeszéljük, hogy mindez mit tesz, de először próbáljunk meg egy globális perspektívát szerezni. A program törzse a következőképpen működik.

Először a PORTD 4. bitjét állítottuk be "sbi PORTD, 4" -vel, ez 1 -et küld a PD4 -nek, amely 5V -ra állítja a feszültséget. Ez bekapcsolja a LED -et. Ezután ugorunk a "késleltetés" alprogramhoz, amely 1/2 másodpercet számít ki (ezt később kifejtjük). Ezután visszatérünk a PORTD villogó és tiszta 4. bitjéhez, amely a PD4 -et 0V -ra állítja, és ezáltal kikapcsolja a LED -et. Ezután további 1/2 másodpercet késleltetünk, majd az "rjmp blink" jelzéssel ismét a villogás elejére ugrunk.

Futtassa ezt a kódot, és nézze meg, hogy azt teszi, amit kell.

És ott van! Ez a kód fizikailag ennyi. A mikrovezérlő belső mechanikája egy kicsit jobban érintett, és ezért csináljuk ezt az oktatóanyagot. Tehát beszéljük meg az egyes részeket sorban.

4. lépés:.org összeszerelő irányelvek

Korábbi oktatóanyagainkból már tudjuk, hogy a.nolist,.list,.include és.def assembler irányelvek mit tesznek, ezért először vessünk egy pillantást az ezt követő 4 kódsorra:

.org 0x0000

jmp Reset.org 0x0020 jmp overflow_handler

A.org utasítás megmondja az összeszerelőnek, hogy a "Programmemória" -ba hová tegye a következő utasítást. A program végrehajtása közben a "Programszámláló" (rövidítve: PC) tartalmazza az éppen végrehajtott sor címét. Tehát ebben az esetben, amikor a számítógép 0x0000 -as, akkor a "jmp Reset" parancsot fogja látni az adott memóriahelyen. Azért szeretnénk a jmp Reset -et elhelyezni az adott helyen, mert amikor a program elindul, vagy a chip visszaáll, a számítógép elkezdi végrehajtani a kódot ezen a helyen. Tehát, mint látjuk, most mondtuk, hogy azonnal "ugorjon" a "Reset" feliratú részhez. Miért tettük ezt? Ez azt jelenti, hogy a fenti utolsó két sort csak átugorjuk! Miért?

Nos, itt kezdenek érdekesek lenni a dolgok. Most meg kell nyitnia egy pdf -megtekintőt a teljes ATmega328p adatlappal, amelyre az oktatóanyag első oldalán rámutattam (ezért ez a "szükséges" szakasz 4. pontja). Ha a képernyője túl kicsi, vagy ha már túl sok ablak van nyitva (ahogy velem is történik), akkor megteheti, amit én teszek, és felteheti egy Ereaderre, vagy Android -telefonjára. Mindig ezt fogja használni, ha összeállítási kódot tervez írni. A jó dolog az, hogy minden mikrovezérlő nagyon hasonló módon van megszervezve, így ha egyszer hozzászoktat az adatlapok olvasásához és kódolásához, szinte triviálisnak találja, ha ugyanazt teszi egy másik mikrokontroller esetében. Tehát valójában megtanuljuk, hogyan kell használni az összes mikrokontrollert bizonyos értelemben, és nem csak az atmega328p -t.

Rendben, lapozzon az adatlap 18. oldalára, és nézze meg a 8-2.

A mikrokontroller programmemóriája így van beállítva. Látható, hogy 0x0000 címmel kezdődik, és két részre van osztva; egy alkalmazás flash szakasz és egy boot flash szakasz. Ha röviden hivatkozik a 277. oldalra, a 27-14. Táblázatra, akkor látni fogja, hogy az alkalmazás flash szekciója átveszi a 0x0000 és 0x37FF közötti helyeket, és a rendszerindító vaku rész a többi helyet 0x3800 és 0x3FFF között.

1. gyakorlat: Hány hely van a programmemóriában? Azaz. konvertálja a 3FFF -et tizedesre, és adjon hozzá 1 -et, mivel a számlálást 0 -nál kezdjük. Mivel minden memóriahely 16 bit (vagy 2 bájt) széles, mennyi a bájt memória összesen? Most konvertálja ezt kilobájtra, ne feledje, hogy 2^10 = 1024 bájt van egy kilobájtban. A rendszerindító flash rész 0x3800 -ról 0x37FF -re megy, hány kilobájt ez? Hány kilobájt memória marad a programunk tárolására? Más szóval, mekkora lehet a programunk? Végül hány sor kódunk lehet?

Rendben, most, hogy mindent tudunk a flash program memóriájának megszervezéséről, folytassuk a.org állítások tárgyalását. Látjuk, hogy az első 0x0000 memóriahely tartalmazza az utasításunkat, hogy ugorjunk a Reset címkével ellátott részünkre. Most látjuk, mit tesz a ".org 0x0020" utasítás. Azt mondja, hogy azt akarjuk, hogy a következő sor utasítása a 0x0020 memóriahelyre kerüljön. Az ott elhelyezett utasítás egy ugrás a kódunk egy szakaszához, amelyet "overflow_handler" -nek neveztünk el … most miért a fene kéri, hogy ezt az ugrást helyezzük el a 0x0020 memóriahelyre? Ennek kiderítéséhez lapozzunk az adatlap 65. oldalára, és vessünk egy pillantást a 12-6.

A 12-6. Táblázat a "Vektorok visszaállítása és megszakítása" táblázat, és pontosan megmutatja, hová megy a számítógép, amikor "megszakítást" kap. Például, ha az 1. számú vektort nézi. A megszakítás "forrása" a "RESET", amely "külső tű, bekapcsolás visszaállítása, barnulási alaphelyzetbe állítás és Watchdog rendszer alaphelyzetbe állítása", azaz ha van ilyen ha ezek a dolgok történnek a mikrokontrollerünkkel, a PC elkezdi végrehajtani a programunkat a 0x0000 programmemória helyen. Mi lesz akkor a.org irányelvünkkel? Nos, egy parancsot helyeztünk el a 0x0020 memóriahelyre, és ha lenéz a táblázatba, látni fogja, hogy ha egy Timer/Counter0 túlcsordulás történik (a TIMER0 OVF -ből érkezik), akkor végrehajtja a 0x0020. Tehát amikor ez megtörténik, a PC a „overflow_handler” címkével ellátott helyre ugrik. Hűvös ugye? Egy perc múlva látni fogja, miért tettük ezt, de először fejezzük be az oktatóanyag ezen lépését egy félreértéssel.

Ha azt szeretnénk, hogy a kódunk szebb és rendesebb legyen, akkor a jelenleg tárgyalt 4 sort valóban le kell cserélnünk a következővel (lásd 66. oldal):

.org 0x0000

rjmp Reset; PC = 0x0000 reti; PC = 0x0002 reti; PC = 0x0004 reti; PC = 0x0006 reti; PC = 0x0008 reti; PC = 0x000A… reti; PC = 0x001E jmp overflow_handler: PC = 0x0020 reti: PC = 0x0022… reti; PC = 0x0030 reti; PC = 0x0032

Tehát ha egy adott megszakítás bekövetkezik, az csak "visszavonul", ami azt jelenti, hogy "visszatér a megszakításból", és semmi más nem történik. De ha soha nem "engedélyezzük" ezeket a különféle megszakításokat, akkor azokat nem fogjuk használni, és programkódot helyezhetünk ezekre a helyekre. Jelenlegi "blink.asm" programunkban csak a timer0 túlcsordulás megszakítását engedélyezzük (és természetesen a reset megszakítást, amely mindig engedélyezve van), és így nem fogunk zavarni a többiekkel.

Hogyan lehet akkor "engedélyezni" a timer0 túlcsordulás megszakítását? … Ez az oktatóanyag következő lépésének tárgya.

5. lépés: Időzítő/számláló 0

Időzítő/számláló 0
Időzítő/számláló 0

Nézze meg a fenti képet. Ez a "PC" döntéshozatali folyamata, amikor valamilyen külső befolyás "megszakítja" programunk áramlását. Az első dolog, amit akkor tesz, ha kívülről kap jelet, hogy megszakítás történt, az, hogy ellenőrzi, hogy beállítottuk -e a "megszakítás engedélyezése" bitet az ilyen típusú megszakításhoz. Ha nem, akkor továbbra is végrehajtja a következő kódsorunkat. Ha beállítottuk az adott megszakítási engedélyezési bitet (tehát 1 van a bit helyén a 0 helyett), akkor ellenőrizni fogja, hogy engedélyeztük -e a "globális megszakításokat", ha nem, akkor ismét a következő sorba lép kódot, és folytassa. Ha engedélyeztük a globális megszakításokat is, akkor az az adott típusú megszakítás programmemória helyére kerül (amint az a 12-6. Táblázatban látható), és végrehajtja az ott megadott parancsokat. Lássuk tehát, hogyan valósítottuk meg mindezt a kódunkban.

A kódunk Reset címkézett része a következő két sorral kezdődik:

Visszaállítás:

ldi temp, 0b00000101 out TCCR0B, temp

Mint már tudjuk, ez betölti a temp (azaz R16) számba a közvetlenül azt követő számot, ami 0b00000101. Ezután ezt a számot a "out" paranccsal írja ki a TCCR0B nevű regiszterbe. Mi ez a nyilvántartás? Nos, térjünk át az adatlap 614. oldalára. Ez az összes regisztert összefoglaló táblázat közepén található. A 0x25 címen a TCCR0B található. (Most már tudja, honnan származik a "out 0x25, r16" sor a kód nem kommentált verziójában). A fenti kódszegmensből látjuk, hogy a 0. bitet és a 2. bitet állítottuk be, és a többit töröltük. Ha megnézi a táblázatot, láthatja, hogy ez azt jelenti, hogy beállítottuk a CS00 és a CS02 értékeket. Most térjünk át az adatlap "8 bites időzítő/számláló0 PWM-el" című fejezetéhez. Lépjen különösen az adott fejezet 107. oldalára. Ugyanazt a leírást fogja látni az "Időzítő/Számlálóvezérlő B regiszter" (TCCR0B) regiszter, amelyet az imént láttuk a regiszter összefoglaló táblázatában (tehát egyenesen ide jöhettünk volna, de szeretném, ha látná, hogyan kell használni az összefoglaló táblázatokat) későbbi hivatkozás céljából). Az adatlap továbbra is leírást ad a regiszter minden bitjéről és azok működéséről. Egyelőre kihagyjuk mindezt, és lapozzunk a 15-9. Táblázatra. Ez a táblázat az "Óra kiválasztása bitleírást" mutatja. Most nézze le a táblázatot, amíg meg nem találja azt a sort, amely megfelel azoknak a biteknek, amelyeket a regiszterben állítottunk be. A sor azt írja: "clk/1024 (előskálázóból)". Ez azt jelenti, hogy azt akarjuk, hogy az időzítő/számláló0 (TCNT0) olyan sebességgel ketyegjen, amely a CPU frekvenciája osztva 1024 -gyel. Mivel a mikrovezérlőnket egy 16 MHz -es kristályoszcillátor táplálja, ez azt jelenti, hogy a CPU végrehajtja az utasításokat 16 millió utasítás másodpercenként. Tehát az az arány, amit a TCNT0 számlálónk ketyeg, akkor 16 millió/1024 = 15625 -ször másodpercenként (próbálja ki különböző órajel -bitekkel, és nézze meg, mi történik - emlékezzen a filozófiánkra?). Tartsuk a fejünkben a 15625 számot későbbre, és térjünk át a következő két sorra:

ldi temp, 0b00000001

sts TIMSK0, temp

Ez beállítja a TIMSK0 nevű regiszter 0. bitjét, és törli a többit. Ha megnézi az adatlap 109. oldalát, látni fogja, hogy a TIMSK0 a "Timer/Counter Interrupt Mask Register 0", a kódunk pedig a 0. bitet állította be, amely a TOIE0 nevet viseli, ami "Timer/Counter0 Overflow Interrupt Enable" … Ott! Most látod, miről van szó. Most megvan a "megszakítás engedélyezése bit készlet", ahogyan azt a képünkön az első döntéstől szerettük volna. Tehát most csak annyit kell tennünk, hogy engedélyezzük a "globális megszakításokat", és a programunk képes lesz reagálni az ilyen típusú megszakításokra. Rövidesen engedélyezzük a globális megszakításokat, de mielőtt ezt megtennénk, lehet, hogy valami megzavarta.. miért a fenébe használtam az "sts" parancsot, hogy bemásoljak a TIMSK0 regiszterbe a szokásos "out" helyett?

Amikor meglát, használjon olyan utasítást, amelyet korábban nem látott, először tegye meg, hogy lapozzon az adatlap 616. oldalára. Ez az "Utasítás -összefoglaló". Most keresse meg az "STS" utasítást, amelyet használtam. Azt mondja, hogy egy számot vesz egy R regiszterből (mi az R16 -ot használtuk) és a "Store direct to SRAM" k helyre (esetünkben a TIMSK0 adta meg). Tehát miért kellett az "sts" -et használni, amely 2 óra ciklust vesz igénybe (lásd a táblázat utolsó oszlopát) a TIMSK0 -ban való tároláshoz, és csak az "out" -ra volt szükségünk, amely csak egy óraszakot vesz igénybe, a TCCR0B -ben való tároláshoz? A kérdés megválaszolásához vissza kell térnünk a regiszter összesítő táblázatunkhoz a 614 oldalon. Látja, hogy a TCCR0B regiszter a 0x25 címen, de a (0x45) címen is igaz? Ez azt jelenti, hogy ez egy regiszter az SRAM -ban, de egy bizonyos típusú "port" (vagy i/o regiszter) nevű regiszter is. Ha megnézi az utasítás összefoglaló táblázatot az "out" parancs mellett, látni fogja, hogy az értékeket vesz a "működő regiszterekből", mint például az R16, és elküldi azokat a PORT -ba. Tehát használhatjuk az "out" -t, amikor TCCR0B -re írunk, és megtakaríthatjuk magunkat egy órajel cikluson. De most nézze meg a TIMSK0 -t a regisztertáblában. Látja, hogy a címe 0x6e. Ez kívül esik a portok tartományán (amelyek csak az SRAM első 0x3F helyei), ezért vissza kell térnie az sts parancs használatához, és két CPU órajelet kell végrehajtania. Kérjük, olvassa el a 4. megjegyzést az utasítások összefoglaló táblázatának végén, 615. oldal. Vegye figyelembe azt is, hogy minden bemeneti és kimeneti portunk, például a PORTD, a táblázat alján található. Például a PD4 a 4-es bit a 0x0b címen (most látod, hogy honnan származik az összes 0x0b-es anyag a nem kommentált kódomban!). Oké, gyors kérdés: az "sts" -et "out" -ra változtattad, és nézd meg, mi történik? Emlékezz filozófiánkra! törd össze! ne csak szavamra vedd a dolgokat.

Oké, mielőtt továbblépnénk, lapozzunk egy percre az adatlap 19. oldalára. Lát egy képet az adatmemóriáról (SRAM). Az SRAM első 32 regisztere (0x0000 és 0x001F között) az "általános célú munkaregiszterek" R0 -R31, amelyeket folyamatosan használunk változókként a kódunkban. A következő 64 regiszter az I/O portok 0x005f-ig (azaz azokról, amelyekről beszéltünk, és amelyek mellett a regisztertáblában vannak azok a sorozat nélküli címek, amelyeket az "out" parancs helyett használhatunk az "sts" helyett) az SRAM következő része az összesítő táblázat összes többi regiszterét tartalmazza a 0x00FF címig, végül a többi a belső SRAM. Most gyorsan, lapozzunk egy pillanatra a 12. oldalra. Itt látható egy táblázat az "általános célú munkaregiszterekről", amelyeket mindig változóiként használunk. Látja a vastag vonalat az R0 -R15, majd az R16 -R31 számok között? Ez az a sor, amiért mindig az R16-ot használjuk a legkisebbnek, és a következő bemutatóban részletesebben foglalkozom vele, ahol szükségünk lesz a három 16 bites közvetett címregiszterre is, X, Y és Z. kezdjen bele ebbe még, bár mivel most nincs rá szükségünk, és itt kellőképpen elakadunk.

Fordítson vissza egy oldalt az adatlap 11. oldalára. Látni fogja az SREG regiszter diagramját a jobb felső sarokban? Látja, hogy a regiszter 7. bitjét "én" -nek hívják. Most menjen le az oldalon, és olvassa el a 7 -es bit leírását…. Hurrá! Ez a globális megszakítás engedélyezése bit. Ezt kell beállítanunk ahhoz, hogy a fenti diagramon a második döntést elfogadjuk, és lehetővé tegyük az időzítő/számláló túlcsordulás megszakítását programunkban. Tehát a programunk következő sorában ezt kell olvasni:

sbi SREG, I

amely beállítja az "I" nevű bitet az SREG regiszterben. Ehelyett azonban az utasítást használtuk

sei

helyette. Ez a bit olyan gyakran van beállítva a programokban, hogy egyszerűen elkészítették ezt.

Oké! Most már készen állunk a túlcsordulás -megszakításokra, így a "jmp overflow_handler" végrehajtásra kerül, amikor csak előfordul.

Mielőtt továbblépnénk, vessünk egy gyors pillantást az SREG regiszterre (Status Register), mert ez nagyon fontos. Olvassa el, hogy az egyes zászlók mit képviselnek. Különösen az általunk használt utasítások nagy része állandóan beállítja és ellenőrzi ezeket a zászlókat. Például a későbbiekben a "CPI" parancsot fogjuk használni, ami azt jelenti, hogy "azonnal összehasonlítani". Vessen egy pillantást az utasítás összefoglaló táblájához, és vegye figyelembe, hogy hány zászlót állít be a "zászlók" oszlopban. Ezek mind zászlók az SREG -ben, és a kódunk ezeket állítja be és folyamatosan ellenőrzi. Hamarosan példákat is láthat. Végül a kód ezen szakaszának utolsó része:

clr temp

ki TCNT0, temp sbi DDRD, 4

Az utolsó sor itt elég nyilvánvaló. Csak beállítja a PortD adatirány -regiszterének 4. bitjét, ami a PD4 kimenetét eredményezi.

Az első nullára állítja a hőmérséklet változót, majd másolja ki a TCNT0 regiszterbe. A TCNT0 a mi időzítőnk/számlálónk0. Ez nullára állítja. Amint a PC végrehajtja ezt a sort, az időzítő0 nulláról indul, és másodpercenként 15625 -ször számít. A probléma a következő: a TCNT0 egy "8 bites" regiszter? Tehát mi a legnagyobb szám, amelyet egy 8 bites regiszter tartalmazhat? Nos a 0b11111111 az. Ez a 0xFF szám. Melyik a 255. Tehát látod, mi történik? Az időzítő másodpercenként 15625 -ször növekszik, és minden alkalommal, amikor eléri a 255 -öt, "túlcsordul", és ismét 0 -ra tér vissza. A nullára való visszatéréssel egyidejűleg Timer Overflow Interrupt jelet küld. A PC ezt megérti, és tudod, hogy mit csinál mostanában? Igen. A program memória 0x0020 helyre megy, és végrehajtja az ott talált utasítást.

Nagy! Ha még mindig velem vagy, akkor fáradhatatlan szuperhős vagy! Folytassuk…

6. lépés: Túlcsorduláskezelő

Tegyük fel tehát, hogy az időzítő/számláló0 regiszter éppen túlcsordult. Ma már tudjuk, hogy a program megszakítási jelet kap, és 0x0020 -at hajt végre, amely azt mondja a PC -számlálónak, hogy a PC ugorjon az "overflow_handler" címkére, a következő kódot írtuk a címke után:

overflow_handler:

inc túlcsordulások cpi túlcsordulások, 61 brne PC+2 clr túlcsordulások reti

Az első dolog, amit megnövel, növeli a "túlcsordulás" változót (ez a mi nevünk az R17 általános célú munkaregiszterben), majd "összehasonlítja" a túlcsordulás tartalmát a 61. számmal. A cpi utasítás működése az, hogy egyszerűen kivon a két számot, és ha az eredmény nulla, beállítja a Z zászlót az SREG regiszterben (mondtam, hogy ezt a regisztert folyamatosan látni fogjuk). Ha a két szám egyenlő, akkor a Z zászló 1, ha a két szám nem egyenlő, akkor 0 lesz.

A következő sor "brne PC+2" -t jelent, ami azt jelenti, hogy "ág, ha nem egyenlő". Lényegében ellenőrzi a Z zászlót az SREG -ben, és ha NEM egy (azaz a két szám nem egyenlő, ha egyenlők, akkor a nulla zászló kerül beállításra), a PC elágazik PC+2 -re, vagyis kihagyja a következőt sort, és egyenesen a "reti" -re megy, amely a megszakításból visszatér a helyre, ahol a megszakítás megérkezett. Ha a brne utasítás 1 -et találna a nulla zászló bitben, akkor nem ágazna el, és ehelyett csak folytatná a következő sorral, amely clr túlcsordulásokat állít vissza 0 -ra.

Mi ennek a nettó eredménye?

Nos, látjuk, hogy minden alkalommal, amikor időzítő túlcsordul, ez a kezelő eggyel növeli a "túlcsordulások" értékét. Tehát a "túlcsordulások" változó számolja a túlcsordulások számát, ahogy előfordulnak. Amikor a szám eléri a 61 -et, visszaállítjuk nullára.

Most a világban miért tennénk ilyet?

Lássuk. Emlékezzünk vissza, hogy a processzorunk órajele 16 MHz, és a TCCR0B segítségével "előre méreteztük", hogy az időzítő csak másodpercenként 15625 számlálási sebességgel számoljon? És minden alkalommal, amikor az időzítő eléri a 255 -ös számot, túlcsordul. Ez azt jelenti, hogy másodpercenként 15625/256 = 61,04 -szer túlcsordul. A "túlcsordulások" változókkal nyomon követjük a túlcsordulások számát, és ezt a számot összehasonlítjuk a 61 -gyel. Tehát látjuk, hogy a "túlcsordulások" másodpercenként egyszer 61 lesz! Tehát kezelőnk másodpercenként egyszer nullázza a "túlcsordulásokat". Tehát ha egyszerűen figyelnénk a "túlcsordulás" változót, és tudomásul vennénk minden alkalommal, amikor nullára állítjuk, akkor másodpercenként számolunk valós időben (Ne feledje, hogy a következő oktatóanyagban megmutatjuk, hogyan lehet pontosabb késleltetés ezredmásodpercben, ugyanúgy, mint az Arduino "késleltető" rutinja).

Most "kezeltük" az időzítő túlcsordulás megszakításait. Győződjön meg róla, hogy megértette, hogyan működik ez, majd lépjen a következő lépésre, ahol ezt a tényt felhasználjuk.

7. lépés: Késleltetés

Most, hogy láttuk, hogy az időzítő túlcsordulás megszakítás kezelő "overflow_handler" rutinja minden másodpercben egyszer nullára állítja az "túlcsordulás" változót, ezt a tényt felhasználhatjuk egy "késleltetett" alprogram tervezésére.

Nézze meg a következő kódot a késleltetésünkből: label

késleltetés:

clr túlcsordulás sec_count: cpi túlcsordulás, 30 brne sec_count ret

Ezt az alprogramot minden alkalommal meghívjuk, amikor késleltetni kell a programunkat. Működése az, hogy először a "túlcsordulás" változót nullára állítja. Ezután belép egy "sec_count" feliratú területre, és összehasonlítja a túlcsordulásokat 30 -mal, ha nem egyenlők, akkor elágazik a sec_count címkéhez, és újra összehasonlítja, és újra, stb., Amíg végül egyenlők nem lesznek (ne feledje, hogy ez az egész folyamat az időzítő megszakítás kezelőnk folyamatosan növeli a változó túlcsordulásokat, így ez minden alkalommal változik, amikor itt járunk. Amikor a túlcsordulás végül 30 -at jelent, kiszáll a hurokból, és visszatér bárhová, ahol késleltetést hívtunk: a. A nettó eredmény egy 1/2 másodperces késleltetés

2. gyakorlat: Módosítsa a overflow_handler rutint a következőre:

overflow_handler:

inc túlcsordulások reti

és futtassa a programot. Van valami más? Miért vagy miért nem?

8. lépés: Pislogjon

Végül nézzük a villogási rutinot:

pislogás:

sbi PORTD, 4 rcall késleltetés cbi PORTD, 4 rcall delay rjmp villog

Először bekapcsoljuk a PD4 -et, majd meghívjuk a késleltető alprogramunkat. Az rcall -ot úgy használjuk, hogy amikor a PC "ret" utasításhoz jut, az visszatér az rcall -t követő sorba. Ezután a késleltetési rutin 30 alkalommal késlelteti a túlcsordulás változót, amint láttuk, és ez majdnem pontosan 1/2 másodperc, majd kikapcsoljuk a PD4 -et, késleltetünk még 1/2 másodpercet, majd visszatérünk az elejére.

A nettó eredmény egy villogó LED!

Azt hiszem, most már egyetért majd abban, hogy a "blink" valószínűleg nem a legjobb "hello world" program az assembly nyelven.

3. gyakorlat: Változtassa meg a program különböző paramétereit úgy, hogy a LED különböző sebességgel villogjon, mint egy másodperc vagy négyszer másodpercenként stb. Például 1/4 másodpercre bekapcsolva, majd 2 másodpercre kikapcsolva, vagy valami hasonló. 5. gyakorlat: Változtassa meg a TCCR0B órajelválasztó bitjeit 100 -ra, majd folytassa a felfelé haladást a táblázatban. Mikor válik megkülönböztethetetlenné az 1. oktatóanyag "hello.asm" programjától? 6. gyakorlat (opcionális): Ha más kristályoszcillátorral rendelkezik, például 4 MHz -es vagy 13,5 MHz -es vagy bármi más, cserélje ki a 16 MHz -es oszcillátort a kenyértábláján az újhoz, és nézze meg, hogyan befolyásolja ez a LED villogását. Most már képesnek kell lennie arra, hogy végigmenjen a pontos számításon, és pontosan megjósolhassa, hogyan befolyásolja ez az arányt.

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

Azoknak, akik keményen eljutottak idáig, gratulálunk!

Rájövök, hogy elég nehéz a fikázás, ha többet olvasol és nézel fel, mint huzalozol és kísérletezel, de remélem, megtanultad a következő fontos dolgokat:

  1. Hogyan működik a programmemória
  2. Hogyan működik az SRAM?
  3. Hogyan lehet megkeresni a nyilvántartásokat
  4. Hogyan keressük meg az utasításokat, és tudjuk, mit csinálnak
  5. Megszakítások végrehajtása
  6. Hogyan hajtja végre a CP a kódot, hogyan működik az SREG, és mi történik a megszakítások során
  7. Hogyan kell ciklusokat és ugrásokat végezni, és ugrálni a kódban
  8. Milyen fontos elolvasni az adatlapot!
  9. Ha egyszer megtudja, hogyan kell mindezt megtenni az Atmega328p mikrokontroller számára, akkor viszonylagos sütemény lesz, hogy megtanuljon minden új vezérlőt, amely érdekli.
  10. Hogyan lehet a CPU -időt valós idejűvé változtatni és használni a késleltetési rutinokban.

Most, hogy sok elméletünk van az útból, képesek vagyunk jobb kódot írni és bonyolultabb dolgokat irányítani. Tehát a következő oktatóanyagban ezt fogjuk csinálni. Építünk egy bonyolultabb, érdekesebb áramkört, és szórakoztató módon irányítjuk.

7. gyakorlat: "Törje meg" a kódot különböző módokon, és nézze meg, mi történik! Tudományos kíváncsiság baba! 8. gyakorlat: Gyűjtse össze a kódot a "-l" opcióval, hogy listafájlt hozzon létre. Azaz. "avra -l blink.lst blink.asm" és nézd meg a lista fájlt. Extra jóváírás: A megjegyzés nélküli kód, amelyet az elején adtam, és a megjegyzett kód, amelyet később tárgyalunk, eltér! Egy kódsor van, amely más. Megtalálja? Miért nem számít ez a különbség?

Remélem jól szórakozott! Viszlát legközelebb…

Ajánlott: