Sisällysluettelo:

AVR -kokoonpanon opetusohjelma 3: 9 vaihetta
AVR -kokoonpanon opetusohjelma 3: 9 vaihetta

Video: AVR -kokoonpanon opetusohjelma 3: 9 vaihetta

Video: AVR -kokoonpanon opetusohjelma 3: 9 vaihetta
Video: ЛЕГКИЙ детский кардиган с пандой крючком (с капюшоном) 🐼💝 2024, Heinäkuu
Anonim
AVR -kokoonpanon opetusohjelma 3
AVR -kokoonpanon opetusohjelma 3

Tervetuloa opetusohjelmaan numero 3!

Ennen kuin aloitamme, haluan esittää filosofisen pointin. Älä pelkää kokeilla piirejä ja koodia, joita rakennamme näissä opetusohjelmissa. Vaihda johdot ympäri, lisää uusia komponentteja, ota komponentit pois, vaihda koodirivejä, lisää uusia rivejä, poista rivejä ja katso mitä tapahtuu! On erittäin vaikeaa rikkoa mitään, ja jos teet niin ketä kiinnostaa? Mikään käyttämämme, mukaan lukien mikrokontrolleri, ei ole kovin kallista, ja on aina opettavaista nähdä, miten asiat voivat epäonnistua. Et vain tiedä, mitä älä tee seuraavalla kerralla, mutta mikä vielä tärkeämpää, tiedät miksi et tee sitä. Jos olet jotain minun kaltaistani, kun olit lapsi ja sait uuden lelun, se ei kestänyt kauan ennen kuin otit sen palasiksi nähdäksesi, mikä sai sen tikittämään oikein? Joskus lelu vaurioitui korjaamattomasti, mutta ei iso asia. Se, että lapsi saa tutkia uteliaisuuttaan jopa rikkoutuneiden lelujen kohdalla, tekee hänestä tiedemiehen tai insinöörin astianpesukoneen sijasta.

Tänään aiomme johdottaa hyvin yksinkertaisen piirin ja sitten mennä hieman raskaasti teoriaan. Pahoittelut tästä, mutta tarvitsemme työkaluja! Lupaan, että korjaamme tämän opetusohjelmassa 4, jossa teemme vakavampaa piirin rakentamista ja tulos on melko siisti. Kaikkien näiden opetusohjelmien suorittamistapa on kuitenkin hyvin hidas ja mietiskelevä. Jos vain kyntää läpi, rakenna piiri, kopioi ja liitä koodi ja suorita se sitten, se varmasti toimii, mutta et opi mitään. Sinun on harkittava jokaista riviä. Tauko. Koe. Keksiä. Jos teet sen tällä tavalla, viidennen opetusohjelman loppuun mennessä olet rakentamatta hienoja juttuja etkä tarvitse enää ohjausta. Muuten katsot vain oppimisen ja luomisen sijaan.

Joka tapauksessa tarpeeksi filosofiaa, aloitetaan!

Tässä opetusohjelmassa tarvitset:

  1. prototyyppitaulusi
  2. LED
  3. liitäntäjohdot
  4. vastus noin 220 - 330 ohmia
  5. Käyttöohjeet: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. Tietolomake: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. eri kideoskillaattori (valinnainen)

Tässä on linkki opetusohjelmien kokoelmaan:

Vaihe 1: Piirin rakentaminen

Piirin rakentaminen
Piirin rakentaminen

Tämän opetusohjelman piiri on erittäin yksinkertainen. Aiomme lähinnä kirjoittaa "vilkkua" -ohjelman, joten tarvitsemme vain seuraavan.

Kytke LED PD4: een, sitten 330 ohmin vastukseen ja sitten maahan. eli

PD4 - LED - R (330) - GND

ja siinä se!

Teoria tulee kuitenkin olemaan kova hölmöily …

Vaihe 2: Miksi tarvitsemme kommentteja ja M328Pdef.inc -tiedoston?

Mielestäni meidän pitäisi aloittaa näyttämällä, miksi sisällytystiedosto ja kommentit ovat hyödyllisiä. Mikään niistä ei ole oikeastaan välttämätön, ja voit kirjoittaa, koota ja ladata koodin samalla tavalla ilman niitä, ja se toimii täydellisesti (vaikka ilman sisällytystiedostoa saatat saada valituksia kokoonpanijalta - mutta ei virheitä)

Tässä on koodi, jonka aiomme kirjoittaa tänään, paitsi että olen poistanut kommentit ja sisällytystiedoston:

.laite 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, cx 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

aika yksinkertaista eikö? Haha. Jos olet koonnut ja ladannut tämän tiedoston, LED -valo vilkkuu nopeudella 1 välähdys sekunnissa, vilkkuminen kestää 1/2 sekuntia ja välähdysten välinen tauko kestää 1/2 sekuntia.

Tämän koodin tarkastelu ei kuitenkaan ole tuskallista. Jos kirjoittaisit tällaista koodia ja haluaisit muuttaa sitä tai käyttää sitä uudelleen tulevaisuudessa, sinulla olisi vaikeuksia.

Joten laitetaan kommentit ja sisällytetään tiedosto takaisin, jotta voimme ymmärtää sen.

Vaihe 3: Blink.asm

Tässä on koodi, josta keskustelemme tänään:

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

; kirjoittanut: 1o_o7; Päivämäärä:; versio: 1.0; tiedosto tallennettu muodossa: blink.asm; AVR: atmega328p; kellotaajuus: 16 MHz (valinnainen); ************************************* Ohjelman toiminta: ---------------------; laskee sekunteja vilkkumalla LED -valoa;; PD4 - LED - R (330 ohmia) - GND;; --------------------------------------.nolist.include "./m328Pdef.inc".list; ==============; Ilmoitukset:.def temp = r16.def overflows = r17.org 0x0000; muisti (PC) nollauskäsittelijän sijainti rjmp Reset; jmp maksaa 2 CPU -sykliä ja rjmp vain 1; joten ellet tarvitse hypätä yli 8 kt tavua; tarvitset vain rjmp: n. Siksi vain jotkin mikro -ohjaimet; on rjmp eikä jmp.org 0x0020; Timer0 -ylivuotokäsittelijän muistipaikka rjmp overflow_handler; mene tänne, jos ajastimen0 ylivuoto keskeytyy; ============ Palauta: ldi temp, 0b00000101 out TCCR0B, temp; aseta kellonvalitsimen bitit CS00, CS01, CS02 arvoon 101; tämä asettaa ajastinlaskurin0, TCNT0 FCPU/1024 -tilaan; niin se tikittää CPU -taajuudella/1024 ldi temp, 0b00000001 s TIMSK0, temp; aseta ajastimen ylivuotokeskeytyksen salliminen (TOIE0) -bitti; ajastimen keskeytysmaskirekisteristä (TIMSK0) sei; ottaa käyttöön maailmanlaajuiset keskeytykset - vastaa "sbi SREG, I" clr temp out TCNT0, temp; alustaa ajastin/laskuri 0 sbi DDRD, 4; aseta PD4 lähtöön; ======================; Ohjelman pääosa: vilkkuu: sbi PORTD, 4; kytke LED päälle PD4 -hälytysviiveessä; viive on 1/2 sekuntia cbi PORTD, 4; sammuta LED -valo PD4 -hälytysviiveestä; viive on 1/2 sekuntia rjmp vilkkuu; silmukka takaisin aloitusviiveeseen: clr ylivuoto; aseta ylivuoto 0 sekunniksi: cpi ylivuoto, 30; vertaa ylivuotojen määrää ja 30 brne sec_count; haara takaisin sek_laskuun, jos se ei ole yhtä suuri; jos 30 ylivuotoa on tapahtunut, palaa vilkkumaan overflow_handler: lisää ylivuotoja; lisää 1 ylivuotoihin muuttuva cpi -ylivuoto, 61; vertaa 61 brne PC+2: een; Ohjelmalaskuri + 2 (ohita seuraava rivi), jos se ei ole yhtä suuri clr -ylivuoto; jos 61 ylivuotoa tapahtui, nollaa laskuri nollaan reti; palata keskeytyksestä

Kuten huomaat, kommenttini ovat nyt hieman lyhyempiä. Kun tiedämme, mitä ohjejoukon komentoja meidän ei tarvitse selittää kommenteissa. Meidän on vain selitettävä, mitä tapahtuu ohjelman kannalta.

Keskustelemme siitä, mitä tämä kaikki tekee kappale kerrallaan, mutta yritetään ensin saada globaali näkökulma. Ohjelman pääosa toimii seuraavasti.

Asetamme ensin PORTDin bitin 4 "sbi PORTD, 4", tämä lähettää 1 PD4: lle, joka asettaa jännitteen 5V: iin kyseisessä tapissa. Tämä sytyttää LED -valon. Sitten siirrytään "delay" -aliohjelmaan, joka laskee 1/2 sekuntia (selitämme sen myöhemmin). Palaamme sitten vilkkuvaan ja selkeään bittiin 4 PORTD: ssä, joka asettaa PD4: n 0V: ksi ja sammuttaa siten LED: n. Viivästymme sitten vielä 1/2 sekuntia ja hyppäämme sitten takaisin vilkkumisen alkuun uudelleen "rjmp vilkkuu".

Sinun pitäisi suorittaa tämä koodi ja nähdä, että se tekee mitä pitäisi.

Ja siinä se on! Tämä on kaikki tämä koodi fyysisesti. Mikro -ohjaimen sisäinen mekaniikka on hieman enemmän mukana, ja siksi teemme tämän opetusohjelman. Joten keskustellaan jokaisesta osasta vuorotellen.

Vaihe 4:.org -kokoonpanodirektiivit

Tiedämme jo, mitä.nolist-,.list-,.include- ja.def -kokoonpanodirektiivit tekevät aiemmista opetusohjelmistoistamme, joten katsotaan ensin neljä sen jälkeen tulevaa koodiriviä:

.org 0x0000

jmp Nollaa.org 0x0020 jmp overflow_handler

. Org -lause kertoo kokoonpanijalle, mihin "Ohjelmamuistiin" sijoitetaan seuraava lause. Ohjelman suorittamisen aikana "Ohjelmalaskuri" (lyhenne PC) sisältää nykyisen suoritettavan rivin osoitteen. Joten tässä tapauksessa, kun tietokone on 0x0000, se näkee komennon "jmp Reset", joka sijaitsee kyseisessä muistipaikassa. Haluamme laittaa jmp Reset -toiminnon kyseiseen paikkaan, koska kun ohjelma käynnistyy tai siru nollataan, tietokone alkaa suorittaa koodia tässä kohdassa. Joten, kuten näemme, olemme juuri kehottaneet sitä "hyppäämään" välittömästi kohtaan "Reset". Miksi teimme niin? Tämä tarkoittaa, että kaksi viimeistä riviä ohitetaan! Miksi?

No siellähän asiat kiinnostavat. Sinun on nyt avattava pdf -katseluohjelma täydellisellä ATmega328p -lomakkeella, johon viittasin tämän opetusohjelman ensimmäisellä sivulla (siksi se on kohta 4 "tarvitset" -osiossa). Jos näyttösi on liian pieni tai sinulla on jo liian monta ikkunaa auki (kuten minulla on), voit tehdä mitä minä ja laittaa sen lukulaitteeseen tai Android -puhelimeesi. Käytät sitä koko ajan, jos aiot kirjoittaa kokoonpanokoodin. Hienoa on, että kaikki mikrokontrollit on järjestetty hyvin samankaltaisilla tavoilla, joten kun olet tottunut lukemaan tietolomakkeita ja koodaamaan niistä, huomaat, että on lähes triviaalia tehdä sama eri mikro -ohjaimelle. Joten opimme todella käyttämään kaikkia mikro -ohjaimia tietyssä mielessä eikä vain atmega328p: tä.

Okei, siirry sivulle 18 tietolomakkeessa ja katso kuva 8-2.

Mikro -ohjaimen ohjelmamuisti asetetaan näin. Näet, että se alkaa osoitteella 0x0000 ja on jaettu kahteen osaan; sovelluksen flash -osio ja käynnistyssalaosa. Jos viittaat lyhyesti sivulle 277, taulukko 27-14, näet, että sovelluksen salama-alue ottaa sijainnit 0x0000-0x37FF ja käynnistyssalama-alue ottaa jäljellä olevat sijainnit 0x3800-0x3FFF.

Harjoitus 1: Kuinka monta sijaintia ohjelmamuistissa on? Toisin sanoen Muunna 3FFF desimaalilukuun ja lisää 1, koska aloitamme laskemisen nollasta. Koska kukin muistipaikka on 16 bitin (tai 2 tavun) leveä, mikä on muistin kokonaismäärä? Muunna tämä nyt kilotavuiksi ja muista, että kilotavussa on 2^10 = 1024 tavua. Käynnistyssalaosio on 0x3800 - 0x37FF, kuinka monta kilotavua tämä on? Kuinka monta kilotavua muistia on jäljellä ohjelman käyttämiseen? Toisin sanoen, kuinka suuri ohjelmamme voi olla? Lopuksi, kuinka monta koodiriviä meillä voi olla?

Okei, nyt kun tiedämme kaiken flash -ohjelmamuistin organisoinnista, jatketaan keskustelua.org -lausunnoista. Näemme, että ensimmäinen muistipaikka 0x0000 sisältää ohjeemme siirtyä Reset -nimiseen osioon. Nyt näemme, mitä ".org 0x0020" -lause tekee. Se sanoo, että haluamme, että seuraavan rivin ohjeet sijoitetaan muistipaikkaan 0x0020. Ohje, jonka olemme asettaneet sinne, on hyppy koodimme osioon, jonka olemme merkinneet "overflow_handler" … miksi ihmeessä vaatisimme, että tämä hyppy sijoitetaan muistipaikkaan 0x0020? Selvittääksemme siirrymme sivulle 65 tietolomakkeessa ja katsomme taulukkoa 12-6.

Taulukko 12-6 on taulukko "Nollaa ja keskeytä vektorit", ja se näyttää tarkalleen mihin tietokone siirtyy, kun se saa "keskeytyksen". Jos esimerkiksi tarkastelet vektorin numeroa 1. Keskeytyksen "lähde" on "PALAUTA", joka määritellään "Ulkoinen nasta, käynnistyksen nollaus, ruskean nollaus ja Watchdog-järjestelmän nollaus", mikäli jokin Jos nämä asiat tapahtuvat mikrokontrollerillemme, tietokone alkaa suorittaa ohjelmamme ohjelman muistipaikassa 0x0000. Entä sitten.org -direktiivimme? No, asetimme komennon muistipaikkaan 0x0020 ja jos katsot taulukkoa alaspäin, näet, että jos ajastimen/laskurin0 ylivuoto tapahtuu (TIMER0 OVF: stä), se suorittaa mitä tahansa paikassa 0x0020. Joten aina kun näin tapahtuu, tietokone hyppää kohtaan, jonka merkitsimme "overflow_handler". Viileä eikö? Näet minuutin kuluttua, miksi teimme tämän, mutta ensin lopetetaan tämä opetusohjelman vaihe sivuun.

Jos haluamme tehdä koodistamme siistimmän ja siistimmän, meidän pitäisi todella korvata ne neljä riviä, joista keskustelemme parhaillaan, seuraavilla (katso sivu 66):

.org 0x0000

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

Joten jos tietty keskeytys tapahtuu, se vain "poistuu", mikä tarkoittaa "paluuta keskeytyksestä", eikä mitään muuta tapahdu. Mutta jos emme koskaan "ota käyttöön" näitä erilaisia keskeytyksiä, niitä ei käytetä ja voimme laittaa ohjelmakoodin näihin kohtiin. Nykyisessä "blink.asm" -ohjelmassamme otamme käyttöön vain timer0 -ylivuotokeskeytyksen (ja tietysti nollauksen keskeytyksen, joka on aina käytössä), joten emme häiritse muita.

Kuinka me "otamme käyttöön" timer0 -ylivuotokeskeytyksen? … Se on tämän opetusohjelman seuraavan vaiheemme aihe.

Vaihe 5: Ajastin/laskuri 0

Ajastin/laskuri 0
Ajastin/laskuri 0

Katso yllä olevaa kuvaa. Tämä on "PC": n päätöksentekoprosessi, kun jokin ulkopuolinen vaikutus "keskeyttää" ohjelmamme kulun. Ensimmäinen asia, jonka se tekee, kun se saa signaalin ulkopuolelta, että keskeytys on tapahtunut, on tarkistaa, onko meillä asetettu "keskeytyksen käyttöönotto" -bitti kyseiselle keskeytykselle. Jos emme ole, se jatkaa vain seuraavan koodirivimme suorittamista. Jos olemme asettaneet kyseisen keskeytyksen sallivan bitin (niin että siinä bittisijainnissa on 1 sijasta 0), se tarkistaa, onko "globaalit keskeytykset" otettu käyttöön vai ei, jos ei, se siirtyy jälleen seuraavalle riville koodista ja jatka. Jos olemme ottaneet käyttöön myös globaalit keskeytykset, se siirtyy kyseisen tyyppisen keskeytyksen ohjelmamuistipaikkaan (kuten taulukossa 12-6 esitetään) ja suorittaa minkä tahansa siihen asettamamme komennon. Joten katsotaanpa, kuinka olemme toteuttaneet kaiken tämän koodissamme.

Koodimme Reset -merkitty osa alkaa seuraavilla kahdella rivillä:

Nollaa:

ldi -lämpötila, 0b00000101 ulos TCCR0B, lämpötila

Kuten jo tiedämme, tämä lataa lämpötilaan (eli R16) heti seuraavan numeron, joka on 0b00000101. Sitten se kirjoittaa tämän numeron rekisteriin nimeltä TCCR0B käyttämällä "out" -komentoa. Mikä tämä rekisteri on? Siirrytään tietolomakkeen sivulle 614. Tämä on taulukon keskellä, jossa on yhteenveto kaikista rekistereistä. Osoitteesta 0x25 löydät TCCR0B. (Nyt tiedät mistä rivi "out 0x25, r16" tuli minun kommentoimattomasta koodiversiostani). Yllä olevasta koodisegmentistä näemme, että olemme asettaneet 0. bitin ja 2. bitin ja poistaneet kaikki loput. Tarkastelemalla taulukkoa näet, että tämä tarkoittaa, että olemme asettaneet CS00 ja CS02. Siirrytään nyt tietolomakkeen lukuun "8-bittinen ajastin/laskuri0 ja PWM". Siirry erityisesti kyseisen luvun sivulle 107. Näet saman kuvauksen "Ajastin/laskuriohjausrekisteri B" (TCCR0B) -rekisteristä, jonka juuri näimme rekisterin yhteenvetotaulukossa (joten olisimme voineet tulla suoraan tänne, mutta halusin, että näet kuinka käyttää yhteenvetotaulukoita jatkoa ajatellen). Tietolomake antaa edelleen kuvauksen jokaisesta rekisterin bitistä ja niiden toiminnasta. Ohitamme kaiken tämän hetken ja käännämme sivun taulukkoon 15-9. Tässä taulukossa on "Kellovalinnan bittikuvaus". Katso nyt taulukkoa alaspäin, kunnes löydät rivin, joka vastaa juuri kyseiseen rekisteriin asettamiamme bittejä. Rivillä lukee "clk/1024 (esiskaalasta)". Tämä tarkoittaa sitä, että haluamme, että ajastin/laskuri0 (TCNT0) tikittää nopeudella, joka on suorittimen taajuus jaettuna 1024. Koska meillä on mikrokontrolleri, jota ruokkii 16 MHz: n kideoskillaattori, se tarkoittaa, että suorittimen suorittama nopeus on 16 miljoonaa ohjetta sekunnissa. Joten nopeus, jonka TCNT0 -laskurimme merkitsee, on sitten 16 miljoonaa/1024 = 15625 kertaa sekunnissa (kokeile sitä eri kellovalintabiteillä ja katso mitä tapahtuu - muista filosofiamme?). Pidetään numero 15625 mielessämme myöhempää käyttöä varten ja siirrytään seuraaviin kahteen koodiriviin:

ldi -lämpötila, 0b00000001

s TIMSK0, lämpötila

Tämä asettaa TIMSK0 -nimisen rekisterin 0. bitin ja tyhjentää loput. Jos katsot tietosivun sivua 109, näet, että TIMSK0 tarkoittaa "Ajastin/laskurin keskeytysmaskirekisteri 0" ja koodimme on asettanut 0. bitin, jonka nimi on TOIE0 ja joka tarkoittaa "ajastin/laskuri0 Ylivuotokeskeytyksen salliminen" … Siellä! Nyt näet, mistä tässä on kyse. Meillä on nyt "keskeytyksen mahdollistava bittiasetus", kuten halusimme ensimmäisestä päätöksestä kuvassa ylhäällä. Joten nyt meidän tarvitsee vain ottaa käyttöön "maailmanlaajuiset keskeytykset", ja ohjelmamme pystyy vastaamaan tällaisiin keskeytyksiin. Otamme globaalit keskeytykset käyttöön pian, mutta ennen kuin teemme sen, olet saattanut olla hämmentynyt jostain.. miksi ihmeessä käytin komentoa "sts" kopioidaksesi TIMSK0 -rekisteriin tavallisen "out": n sijasta?

Aina kun näet minut, käytä ohjeita, joita et ole nähnyt ennen, sinun on ensin käännettävä sivulle 616 tietolomakkeessa. Tämä on "ohjejoukon yhteenveto". Etsi nyt ohje "STS", jota käytin. Se sanoo, että se ottaa numeron R -rekisteristä (käytimme R16: aa) ja "Store suoraan SRAM: iin" paikasta k (meidän tapauksessamme TIMSK0). Joten miksi meidän piti käyttää "sts": ää, joka kestää 2 kellojaksoa (katso taulukon viimeinen sarake) tallentaaksesi TIMSK0: een, ja tarvitsimme vain "out", joka kestää vain yhden kellosyklin, tallentaaksemme TCCR0B: hen ennen? Jotta voimme vastata tähän kysymykseen, meidän on palattava rekisterin yhteenvetotaulukkoon sivulla 614. Näetkö, että TCCR0B -rekisteri on osoitteessa 0x25, mutta myös (0x45)? Tämä tarkoittaa, että se on SRAM -rekisteri, mutta se on myös tietyn tyyppinen rekisteri, jota kutsutaan "portiksi" (tai i/o -rekisteriksi). Jos tarkastelet ohjeiden yhteenvetotaulukkoa "out" -komennon vieressä, huomaat, että se ottaa arvot "työrekistereistä", kuten R16, ja lähettää ne PORTTIIN. Voimme siis käyttää "out" -toimintoa kirjoittaessamme TCCR0B: hen ja säästää kellosyklin. Mutta nyt etsi TIMSK0 rekisteritaulukosta. Näet, että sen osoite on 0x6e. Tämä on porttien alueen ulkopuolella (jotka ovat vain SRAM: n ensimmäiset 0x3F -sijainnit), joten sinun on palattava käyttämään sts -komentoa ja suorittamaan kaksi suorittimen kellojaksoa. Lue ohjeen yhteenvetotaulukon lopussa sivulla 615 oleva huomautus 4 juuri nyt. Huomaa myös, että kaikki tulo- ja lähtöporttimme, kuten PORTD, sijaitsevat taulukon alareunassa. Esimerkiksi PD4 on bitti 4 osoitteessa 0x0b (nyt näet mistä kaikki 0x0b tavarat ovat peräisin kommentoimattomasta koodistani!) tapahtuu? Muista filosofiamme! riko se! älä vain ota sanaani asioista.

Okei, ennen kuin siirrymme eteenpäin, siirry sivulle 19 tietolomakkeessa minuutiksi. Näet kuvan datamuistista (SRAM). SRAM: n 32 ensimmäistä rekisteriä (0x0000 - 0x001F) ovat "yleiskäyttöiset rekisterit" R0 - R31, joita käytämme jatkuvasti koodimme muuttujina. Seuraavat 64 rekisteriä ovat I/O-portteja enintään 0x005f asti (eli niistä, joista puhuimme ja joiden rekisteritaulukossa on niitä haarukoimattomia osoitteita, joita voimme käyttää "out" -komennon "sts" sijaan) SRAM: n seuraava osa sisältää kaikki muut yhteenvetotaulukon rekisterit osoitteeseen 0x00FF asti, ja loput ovat SRAM: n sisäisiä. Siirrytään nyt hetkeksi sivulle 12. Siellä näet taulukon "yleiskäyttöisistä työrekistereistä", joita käytämme aina muuttujina. Näetkö paksun viivan numeroiden R0 - R15 ja sitten R16 - R31 välillä? Tämän linjan takia käytämme aina R16: ta pienimpänä, ja aion perehtyä siihen hieman enemmän seuraavassa opetusohjelmassa, jossa tarvitsemme myös kolme 16-bittistä epäsuoraa osoiterekisteriä, X, Y ja Z. ryhdy siihen vielä, vaikka emme tarvitse sitä nyt ja olemme jumissa tarpeeksi täällä.

Käännä yksi sivu takaisin lomakkeen sivulle 11. Näetkö SREG -rekisterin kaavion oikeassa yläkulmassa? Näet, että kyseisen rekisterin bittiä 7 kutsutaan "minä". Mene nyt sivulle ja lue bitin 7 kuvaus. jee! Se on Global Interrupt Enable -bitti. Tämä on asetettava, jotta voimme käydä läpi yllä olevan kaavion toisen päätöksen ja sallia ajastimen/laskurin ylivuotokeskeytykset ohjelmassamme. Joten ohjelmamme seuraavan rivin pitäisi olla seuraava:

sbi SREG, I

joka asettaa bitin nimeltä "I" SREG -rekisteriin. Tämän sijaan olemme käyttäneet ohjetta

sei

sen sijaan. Tämä bitti on asetettu niin usein ohjelmiin, että he tekivät yksinkertaisemman tavan tehdä se.

Okei! Nyt olemme saaneet ylivuotokeskeytykset valmiiksi, jotta "jmp overflow_handler" suoritetaan aina, kun niitä ilmenee.

Ennen kuin siirrymme eteenpäin, vilkaise nopeasti SREG -rekisteriä (Status Register), koska se on erittäin tärkeä. Lue, mitä kukin lippu edustaa. Erityisesti monet käyttämistämme ohjeista asettavat ja tarkistavat nämä liput koko ajan. Esimerkiksi myöhemmin käytämme komentoa "CPI", joka tarkoittaa "vertaa välittömästi". Katso tämän ohjeen yhteenvetotaulukkoa ja huomaa kuinka monta lippua se asettaa "liput" -sarakkeeseen. Nämä kaikki ovat SREG: n lippuja, ja koodimme asettaa ne ja tarkistaa ne jatkuvasti. Näet esimerkkejä pian. Lopuksi tämän koodiosan viimeinen bitti on:

clr lämpötila

ulos TCNT0, temp sbi DDRD, 4

Viimeinen rivi tässä on melko selvä. Se asettaa vain PortD: n datasuuntarekisterin neljännen bitin, jolloin PD4 on LÄHTÖ.

Ensimmäinen asettaa muuttuvan lämpötilan nollaksi ja kopioi sen sitten TCNT0 -rekisteriin. TCNT0 on ajastin/laskuri0. Tämä asettaa sen nollaksi. Heti kun tietokone suorittaa tämän rivin, ajastin0 alkaa nollasta ja laskee 15625 kertaa sekunnissa. Ongelma on tämä: TCNT0 on "8-bittinen" rekisteri, eikö? Mikä on suurin numero, johon 8-bittinen rekisteri mahtuu? No 0b11111111 on se. Tämä on numero 0xFF. Mikä on 255. Joten näet mitä tapahtuu? Ajastin vetää vetoa pitkin 15625 kertaa sekunnissa ja aina kun se saavuttaa 255, se "ylittää" ja palaa takaisin 0: een. Samalla kun se palaa nollaan, se lähettää ajastimen ylivuotokeskeytyssignaalin. Tietokone saa tämän ja tiedät mitä se tekee nyt? Joo. Se siirtyy ohjelmamuistipaikkaan 0x0020 ja suorittaa siellä löytämänsä käskyn.

Loistava! Jos olet edelleen kanssani, olet väsymätön supersankari! Jatketaan…

Vaihe 6: Ylivuotokäsittelijä

Oletetaan siis, että ajastin/laskuri0 -rekisteri on juuri ylittänyt. Tiedämme nyt, että ohjelma vastaanottaa keskeytyssignaalin ja suorittaa 0x0020, joka kehottaa ohjelmalaskuria, PC: tä siirtymään otsikkoon "overflow_handler", seuraava on koodi, jonka kirjoitimme kyseisen tarran jälkeen:

overflow_handler:

lisää ylivuotoja cpi ylivuotoja, 61 brne PC+2 clr ylivuotoja eläke

Ensimmäinen asia, jota se lisää, on muuttujan "ylivuoto" (joka on meidän nimemme yleiskäyttörekisteriin R17) lisääminen ja sitten "vertaa" ylivuotojen sisältöä numeroon 61. Ohje cpi toimii siten, että se yksinkertaisesti vähentää kaksi numeroa ja jos tulos on nolla, se asettaa Z -lipun SREG -rekisteriin (sanoin, että näemme tämän rekisterin koko ajan). Jos kaksi lukua ovat yhtä suuret, Z -lippu on 1, jos kaksi numeroa eivät ole yhtä suuret, se on 0.

Seuraavalla rivillä lukee "brne PC+2", mikä tarkoittaa "haaraa, jos ei yhtä suurta". Pohjimmiltaan se tarkistaa Z -lipun SREG: ssä ja jos se EI ole yksi (eli kaksi lukua eivät ole yhtä suuret, jos ne olisivat yhtä suuret, nollalippu asetettaisiin), PC haarautuu PC+2: ksi, eli se ohittaa seuraavan riville ja menee suoraan "reti" -tilaan, joka palaa keskeytyksestä mihin tahansa kohtaan, jossa se oli koodissa keskeytyksen saapuessa. Jos brne -käsky löytäisi 1 nollapisteen bitistä, se ei haarautuisi ja sen sijaan se jatkaisi vain seuraavalle riville, joka sulkeisi ylivuotot nollaamalla sen.

Mikä on tämän kaiken nettotulos?

No, näemme, että joka kerta, kun ajastin ylivuoto, tämä käsittelijä lisää "ylivuotojen" arvoa yhdellä. Joten muuttuja "ylivuoto" laskee ylivuotojen määrän niiden esiintyessä. Aina kun luku saavuttaa 61, nollaamme sen.

Miksi ihmeessä tekisimme niin?

Katsotaan. Muistatko, että kellomme nopeus suorittimellemme on 16 MHz ja "esiasetimme" sen käyttämällä TCCR0B: tä niin, että ajastin laskee vain nopeudella 15625 laskua sekunnissa? Ja joka kerta, kun ajastin saavuttaa 255, se ylittää. Tämä tarkoittaa, että se ylittää 15625/256 = 61,04 kertaa sekunnissa. Seuraamme ylivuotojen määrää muuttuvalla "ylivuotolla" ja vertaamme tätä lukua lukuun 61. Joten näemme, että "ylivuoto" on 61 kerran sekunnissa! Käsittelijämme nollaa "ylivuotot" nollaan joka sekunti. Jos siis vain seuraisimme muuttujaa "ylivuoto" ja ottaisimme huomioon joka kerta, kun se nollataan, laskemme sekuntia sekunnissa reaaliajassa (Huomaa, että seuraavassa opetusohjelmassa näytämme kuinka saada tarkempi viive millisekunteina samalla tavalla kuin Arduinon "viive" -rutiini toimii).

Nyt olemme "hoitaneet" ajastimen ylivuotokeskeytykset. Varmista, että ymmärrät, miten tämä toimii, ja siirry sitten seuraavaan vaiheeseen, jossa käytämme tätä tosiasiaa.

Vaihe 7: Viive

Nyt kun olemme nähneet, että ajastimen ylivuotokeskeytyksen käsittelijä "overflow_handler" -rutiini asettaa muuttujan "overflows" nollaksi joka sekunti, voimme käyttää tätä tosiasiaa "delay" -aliohjelman suunnittelussa.

Katso seuraava koodi viiveestämme: etiketti

viive:

clr ylivuoto sec_count: cpi ylivuoto, 30 brne sec_count ret

Alamme kutsua tätä aliohjelmaa aina, kun tarvitsemme ohjelman viivästymistä. Toimintatapa on se, että se ensin asettaa muuttujan "ylivuoto" nollaksi. Sitten se tulee alueelle, jonka nimi on "sec_count", ja vertaa ylivuotoja 30: een, jos ne eivät ole yhtä suuret, se haarautuu takaisin tunnisteeseen sec_count ja vertaa uudelleen ja uudelleen jne. Kunnes ne ovat lopulta yhtä suuret (muista, että koko tämän ajan ajastinkeskeytyskäsittelijämme jatkaa muuttujien ylivuotojen lisäämistä, joten se muuttuu joka kerta, kun käymme täällä. 1/2 sekunnin viive

Harjoitus 2: Muuta overflow_handler -rutiini seuraavasti:

overflow_handler:

inc ylivuotoja reti

ja aja ohjelma. Onko jotain erilaista? Miksi tai miksi ei?

Vaihe 8: Vilkkuu

Katsotaanpa lopuksi vilkkurutiinia:

räpäytys:

sbi PORTD, 4 rcall -viive cbi PORTD, 4 rcall -viive rjmp vilkkuu

Käynnistämme ensin PD4: n ja sitten kutsumme viivealiohjelman. Käytämme rcallia niin, että kun tietokone saa "ret" -lausekkeen, se palaa takaisin rcall -riviä. Sitten viivästysrutiini viivästyy 30 kertaa ylivuotomuuttujassa, kuten olemme nähneet, ja tämä on lähes täsmälleen 1/2 sekuntia, sitten sammutamme PD4: n, viivyttelemme vielä 1/2 sekuntia ja palaamme sitten takaisin alkuun.

Tuloksena on vilkkuva LED!

Luulen, että olette nyt samaa mieltä siitä, että "blink" ei todennäköisesti ole paras "hello world" -ohjelma kokoonpanokielellä.

Harjoitus 3: Muuta ohjelman eri parametreja siten, että LED -valo vilkkuu eri nopeuksilla, kuten sekunnin tai 4 kertaa sekunnissa jne. Esimerkiksi päälle 1/4 sekunnin ja sitten pois päältä 2 sekunnin ajan tai jotain sellaista Harjoitus 5: Vaihda TCCR0B -kellon valintabitit 100: ksi ja jatka sitten ylöspäin taulukossa. Missä vaiheessa siitä tulee erottamaton opetusohjelman 1 "hello.asm" -ohjelmastamme? Harjoitus 6 (valinnainen): Jos sinulla on erilainen kideoskillaattori, kuten 4 MHz tai 13,5 MHz tai mikä tahansa, vaihda 16 MHz: n oskillaattori leipäpöydälläsi uutta varten ja katso, miten se vaikuttaa LED -valon vilkkumiseen. Sinun pitäisi nyt pystyä käymään läpi tarkka laskelma ja ennustamaan tarkasti, miten se vaikuttaa korkoon.

Vaihe 9: Johtopäätös

Niille teistä, jotka olette kovia, jotka pääsivät tähän asti, onnittelut!

Ymmärrän, että se on melko vaikeaa, kun luet ja katselet enemmän kuin johdotat ja kokeilet, mutta toivon, että olet oppinut seuraavat tärkeät asiat:

  1. Ohjelmamuistin toiminta
  2. Miten SRAM toimii
  3. Kuinka etsiä rekistereitä
  4. Kuinka etsiä ohjeita ja tietää, mitä ne tekevät
  5. Keskeytysten toteuttaminen
  6. Miten CP suorittaa koodin, miten SREG toimii ja mitä tapahtuu keskeytysten aikana
  7. Kuinka tehdä silmukoita ja hyppyjä ja pomppia koodissa
  8. Kuinka tärkeää on lukea tietolomake!
  9. Kuinka kerran, kun tiedät kuinka tehdä tämä kaikki Atmega328p -mikrokontrollerille, se on suhteellinen kakku kävely, jotta opit kaikki uudet ohjaimet, joista olet kiinnostunut.
  10. Kuinka muuttaa suorittimen aika reaaliaikaiseksi ja käyttää sitä viivästysrutiineissa.

Nyt kun meillä on paljon teoriaa, voimme kirjoittaa parempaa koodia ja hallita monimutkaisempia asioita. Joten seuraavassa opetusohjelmassa teemme juuri sen. Rakennamme monimutkaisemman, mielenkiintoisemman piirin ja hallitsemme sitä hauskoilla tavoilla.

Harjoitus 7: "Riko" koodi eri tavoin ja katso mitä tapahtuu! Tieteellinen uteliaisuus vauva! Harjoitus 8: Kokoa koodi käyttämällä "-l" -vaihtoehtoa luodaksesi luettelotiedoston. Toisin sanoen "avra -l blink.lst blink.asm" ja katso luettelotiedostoa. Lisäluotto: Aluksi antamani kommentoimaton koodi ja kommentoitu koodi, joista keskustelemme myöhemmin, eroavat toisistaan! On yksi koodirivi, joka on erilainen. Löydätkö sen? Miksei sillä ole väliä?

Toivottavasti teillä oli hauskaa! Nähdään ensi kerralla…

Suositeltava: