Ebben a leckében a Timer0-t használjuk a LEDek léptetésére számlálóciklusok helyett. A nyomógombbal a léptetés irányát változtathatjuk.
Fájlok ITT.
Megismerjük:
- a hardveres timert, ami órajelet vagy külső eseményeket számol,
- ennek előnyeit a delay ciklusokkal szemben,
- az előosztó használatát, melynek segítségével megadjuk, hány órajelet számoljon egynek a timerünk.
A Timer0 a PIC18F45K20 időzítő/számláló perifériája, mellyel akár külső eseményeket is számolhatunk a T0CKI lábon. 8 és 16 bites üzemmódja létezik, tehát 0-tól 255-ig, vagy 0-tól 65535-ig tud számolni. Ha a számláló túlcsordul, beállít egy flaget, amelyet polling módszerrel vizsgálhatunk.
A Timer0 része egy előosztó (prescaler), amely a számláló elérése előtt osztja az órajelet. 1:1-es előosztót használva a timer egyet ugrik minden utasításórajelre (Ami, mint azt már megtanultuk, az oszcillátor órajelének negyede). 1:8 előosztásnál minden 8 utasításórajelre számol egyet az időzítő. Bármikor írjuk a timert, az előosztó törlődik.
Ha a Timer0-t 16 bites módban használjuk, az időzítő értékének írása és olvasása kicsit bonyolultabb: A 16 bites értékünként. TMR0H akkor frissül, amikor TMR0L-t olvassuk,k alsó bájtját a TMR0L SFR-en keresztül írhatjuk és olvashatjuk. A felső bájt azonban nem érhető el direkt, hanem a TMR0H SFR-ben tartja a vezérlő puffer vagy írjuk. Ha TMR0L-t írjuk, akkor íródik meg a tényleges TMR0H a felső bájtba. Így egyszerre tudjuk olvasni a teljes 16 bites értéket. Tehát, ha olvasni szeretnénk a Timer0 számlálóját, először az alsó bájtot kell olvasnunk, utána a felsőt. Ha írni szeretnénk, akkor először a felsőt írjuk, utána az alsót.
A Timer0-t a T0CON SFR-en keresztül vezérelhetjük.
Ahhoz, hogy a Timer0 leválthassa a softwares delayünket, úgy kell beállítanunk, hogy 2-300 ms-ként túlcsorduljon. A T0CON SFR-ben ezt így állíthatjuk be:
- T08BIT = 0
Timer0 16 bites, hogy bemutathassuk a TMR0H pufferelését.
- T0CS = 0
Timer0 a belső utasításciklusról fut. Fosc=1MHz esetén ez 250kHz-et jelent.
- T0SE = 0
Ha a Timer0 a T0CKI lábról futna, ezzel állítanánk be, hogy fel-, vagy lefutó élre számoljunk. Mivel mi ezt most nem használjuk, ez a bit számunkra nem érdekes (Házi feladat!). Ezt a szakszöveg "Don't care"-nek mondja, és a beállításainkat ez a bit nem változtatja meg.
- PSA = 1
A timer 65536 számolás után túlcsordul. 250kHz-en ez azt jelenti, hogy minden 65536 *(1/250000) = 262 ms-enként. Ez az idő nekünk megfelelő, szóval nem kell előosztót beállítanunk.
- T0PS2:T0PS0 = 000
Mivel nem használunk előosztót ezek a rész "don't care".
- TMR0ON = 0
Ezzel a bittel kapcsolhatjuk be és ki az időzítőnket. Most kikapcsoljuk, mivel majd a beállítás után indítjuk el.
Ezen beállítások használatához írjuk a 0b00001000 értéket a T0CON-ba.
(A PIC18F45K20 további 2 beállítható időzítővel rendelkezik. Ezekről bővebben a vezérlő adatlapjában olvashatsz)
Nyissuk meg a forráskódot, és böngésszük végig! Vegyük észre, hogy a 05 Timer.h-ban létrehozunk két új típust:
typedef enum { LEFT2RIGHT, RIGHT2LEFT} LEDDirections;
typedef enum { FALSE, True} BOOL;
Ezekkel a típusokkal deklarálhatunk új változókat a main() függvényben:
LEDDirections Direction = LEFT2RIGHT;
BOOL SwitchPressed = FALSE;
A Direction változóban tároljuk a LEDek forgásirányát, a SwitchPressed figyeli, hogy megnyomtuk-e a gombot. A gombnyomással a LEDek forgásirányát változtathatjuk.
A következő kód állítja be a while(1) ciklus előtt a Timer0 modult:
// Init Timer
INTCONbits.TMR0IF = 0; // 1. sor
T0CON = 0b00001000; // 2. sor
// T0CON = 0b00000001; (ignore commented line for now)
TMR0H = 0; // 3. sor
TMR0L = 0; // 4. sor
T0CONbits.TMR0ON = 1; // 5. sor
Nézzük végig a számozott sorokat, mit is csinálunk pontosan!
Az 1. sorban töröljük a TMR0IF flaget az INTCON SFR-ben. Ez a flag lesz beállítva mindig, amikor az időzítő túlcsordul, tehát ezt fogjuk folyamatosan lekérdezni, hogy megtudjuk, mikor kell léptetni a LEDeket. Ez a bit nem törlődik hardveresen, nekünk kell törölnünk azt, hogy a timerünk rendben fusson.
A 2. sor a korábban tárgyalt beállításokat tölti a T0CON regiszterbe.
A 3. sorban töröljük a TMR0H buffert. Emlékezzünk, ez csak a felső bájtja a számlálónak! A 0 érték csak akkor íródik be, amikor az alsót is beírjuk!
A 4. sorban töröljük a TMR0L regisztert, amivel a vezérlőnk törli a TMR0H-t is. Tehát a teljes 16 bites időzítőnk a 0x0000 értékkel lesz megtöltve.
Az 5. sor beállítja a TME0ON bitet a T0CON regiszterben, így bekapcsolja az időzítőt, ami elkezd számolni. A T0CONbits.TMR0ON SFR bit használatával ezt tudjuk be- és kikapcsolni a többi érték megváltoztatása nélkül.
Figyelem! Néhány esetben ezen SFR uniók használata hatással van más bitekre! Pontosabban az történik, hogy az utasítás alatt a bitet olvassuk, újra beállítjuk, és ekkor a teljes regiszter újraíródik. Ezt Read-Modify-Write-nak hívja a szaknyelv. Ha egy bit más értéket ad vissza, mint amire utoljára beállítottuk, az hatással lehet a regiszter más bitjeire is. Nézzük át alaposan az SFR bitek leírását! A T0CON esetében minden bitet szoftverből állítunk, a hardver nem fog hozzányúlni a regiszterhez.
A while(1) ciklusban a LED_Display változót beállítjuk, hogy az '1' bitet léptesse a Direction változó tartalmának megfelelően, majd frissítse a kijelzőt (LATD).
A do{...} while() ciklus ezek után megnézi a kapcsolót, hogy történt-e gombnyomás, amíg a timer túlcsordulására várunk. Ez egyszerű példája annak, hogy segíti a timer a vezérlő gyors működését: Nem kell számítási teljesítményt áldozni arra, hogy teljen az idő, közben tudunk fontosabb dolgokkal foglalkozni.
Ha megnyomjuk a gombot, a Direction változó értéke megváltozik. A do{...}while() ciklus if-else if ágát figyelve láthatjuk, hogyan történik mindez.
Végül, amikor a Timer0 túlcsordul, és beállítja a TMR0IF flaget, a do{...}while() ciklus kilép, A TMR0IF-et töröljük szoftverből, és előlről kezdjük az egészet.
Fordítsuk le, és égessük be a programot a demópanelünk vezérlőjébe! A futófény futni fog, a gombbal pedig az irányt változtatjuk meg.
Az előosztó
Menjünk csak vissza a Timer0 beállításaihoz! Mi az a kommentezett sor? Vegyük ki a kommentet, és nézzük meg, mi változott!
- PSA = 0
Az előosztót most bekapcsoltuk, és a T0PSx értéke fogja beállítani az osztást.
- T0PS2:T0PS0 = 001
Ezzel az értékkel az előosztót 1:4-re állítjuk, tehát az időzítőnk minden negyedik utasítást fogja számolni. Tehát pontosan négyszer annyi időbe telik elszámolni 65536-ig, és, ha megnézzük, ez már több, mint egy másodperc!
Fordítsuk le újra a forráskódot, és égessük be! A LEDek pontosan négyszer olyan lassan fognak változni.
A cikk még nem ért véget, lapozz!
Értékeléshez bejelentkezés szükséges!