Sunteți pe pagina 1din 8

Folosirea lui Timer0

Timer0 este un timer/counter pe 8 bii cu urmtoarele caracteristici: Registru de 8 bit timer/counter: TMR0 Prescaler de 8 biti Ceasul sursa poate fi selectat intern sau extern Frontul ceasului extern poate fi selectat Generare ntrerupere la depire

Folosirea in modul Timer


In modul timer, Timer0 se va incrementa la fiecare ciclu instruciune al procesorului (atunci cnd este folosit fara prescaler); acest mod este selectat punnd bitul T0CS din OPTION_REG pe zero. Atunci cnd o valoare este scrisa in TMR0, incrementarea lui este inhibata timp de 2 cicli instruciune, imediat dup scriere.

2011.Mai.25

OPTION_REG (Bank 1/3) 7 RBPU 6 INTEDG 5 T0CS 4 T0SE 3 PSA 2 PS2 1 PS1 0 PS1

7 6

RBPU INTEDG

PORTB pull-up Interrupt select

1 = dezactivat 0 = PORTB pull-up active EDGe 1 = Intrerupere pe frontul crescator 0 = Intrerupere pe frontul descrescator

T0CS

Tmr0 Clock 1 = TMR0 functioneaza pe post de counter, sursa Source select fiind pinul T0CKI 0 = Functionare ca timer, sursa fiind ceasul intern de executie a instructiunilor (Fosc/4) Tmr0 Source 1 = incrementare pe frontul descrescator Edge select 0 = incrementare pe frontul crescator al semnalului de pe pinul T0CKI PreScaler Assignment 1 = Prescalerul este alocat Watch Dog Timer-ului (echivalent cu TMR0 prescaler 1:1) 0 = Prescalerul este alocat pentru TMR0 (vezi tabelul de mai jos) rate Biti 000 001 010 011 100 101 110 111 TMR0 prescaler 1:2 1:4 1:8 1:16 1:32 1:64 1:128 1:256

T0SE

PSA

2-0

PS<2:0>

PreScaler select

2011.Mai.25

Folosirea in modul Counter


Atunci cnd este folosit drept counter, Timer0 se va incrementa pe fiecare front (cresctor sau descresctor) al semnalului de pe pinul T0CKI. Frontul de incrementare este determinat de bitul T0SE din OPTION_REG. Modul Counter este selectat punnd pe 1 bitul T0CS din OPTION_REG.

Prescaler programabil din software


Exista un singur prescaler, ce este partajat intre Timer0 si Watchdog Timer(WDT); numai unul din ei poate folosi prescalerul la un moment dat. Asignarea prescalerului este controlata de bitul PSA din OPTION_REG; pentru a asigna prescalerul lui Timer0, acest bit trebuie pus pe 0. Exista 8 opiuni pentru prescaler variind de la 1:2 pina la 1:256, selectabile prin biii PS<2:0> din OPTION_REG. Pentru a avea prescaler 1:1 (adic fara prescaler), prescalerul trebuie sa fie asignat lui WDT (bitul PSA = 1)

ntreruperea de Timer0
Timer0 poate genera o ntrerupere cnd registrul TMR0 produce depire (trece de la FFh la 00h). Bitul T0IF din INTCON este setat pe 1 de fiecare data cnd TMR0 produce depire, indiferent daca ntreruperile sunt activate sau nu. Bitul T0IF trebuie resetat in software. Bitul de activare a ntreruperii pentru Timer0 este T0IE din INTCON.

2011.Mai.25

Exemplul 1: Exemplu de pornire a lui Timer0, cu prescaler, lsat liber sa mearg, cu testarea depirii intro bucla, in programul principal (fara ntreruperi).
CLRF TMR0 CLRF INTCON BSF STATUS, RP0 MOVLW 0x03 MOVWF OPTION_REG BCF STATUS, RP0 ; Sterge continutul lui TMR0 ; Dezactiveaza toate intreruprile, deasemenea sterge T0IF ; Trece in Bank1, pentru a putea accesa OPTION_REG ;OPTION_REG = 0000 0011 ; prescaler 1:16 ; Trece in Bank0

asteapta BTFSS INTCON, T0IF GOTO asteapta

; Asteapta intr-o bucla si testeaza daca a aparut depasirea de Timer0

; Cind se ajunge aici insemana ca s-a produs depasirea lui Timer0 NOP GOTO $ ; aici o sa fie restul programului ; aici intra intr-o bucla infinita

Rulai programul pas cu pas. Punei spre examinare (Watch) registrul TMR0. Cum variaz TMR0? dup ce regula? Folositi StopWatch pentru a vedea mai bine cte instruciuni trec pana se incrementeaz timerul. Vedei intializarea lui OPTION_REG de mai sus. ncercai cu OPTION_REG = 08h.

2011.Mai.25

Exemplul 2: (prescaler 1:1) Avem un PIC ce lucreaz cu un oscilator de 20MHz. Ne propunem sa generam ntreruperi cu perioada 10us. Obs: La un quartz de 20MHz, rezulta viteza de execuie a instruciunilor de 5MHz, deci durata unei instruciuni este de 0.2us. Calculam ci cicli procesor sunt necesari pentru o durata de 10us: 10 / 0.2 = 50 cy. Selectam un prescaler de 1:1 (fr prescaler). Daca l lsam pe TMR0 s mearg liber, va produce depire dup 256 cicli main, adic dup 51.2 us. Pentru ca TMR0 sa se incrementeze doar de 50 de ori in loc de 256 ori, va trebui sa-l ajustam (sa-l punem s porneasc de la valoarea) cu: 256 50 = 206 Daca TMR0 pornete de la 206, atunci el se va incrementa numai de 50 de ori pana produce depirea. Deoarece dup fiecare modificare (scriere) in registrul TMR0, timer-ul este ngheat o perioada de 2+1 cicli procesor, numrul care il scriem trebuie sa fie si el ajustat cu 3, sa obinem o perioada precisa; deci in loc de 206, vom scrie 209, sa compensam ciclii cit timer-ul st ngheat de cnd e scris, pan pornete (aceasta ajustare se poate face numai cnd avem prescaler 1:1). Ajustarea o vom face in ntrerupere, adunnd 209 la valoarea curenta a lui TMR0.
LIST P=16F887 #include "p16f887.inc" radix dec ;__CONFIG _HS_OSC&_CP_OFF&_WDT_OFF&_BODEN_ON&_PWRTE_ON&_LVP_OFF&_DEBUG_OFF errorlevel 1, -305 CBLOCK 0x20 ENDC ORG 0 CLRF STATUS CLRF PCLATH GOTO init ;************ initial ******************* org 4 ; procedura de tratare a intreruperilor BCF STATUS, RP0 ; Bank 1 MOVLW 209 ; Ajustare TMR0 ADDWF TMR0 BSF PORTB, 7 ; semnalizam pe un pin de I/O BCF PORTB, 7 BCF INTCON,T0IF ; stergem flagul de intrerupere RETFIE ; iesim din intrerupere init CLRF CLRF BSF MOVLW MOVWF BCF BSF BSF TMR0 INTCON STATUS, RP0 0x08 OPTION_REG STATUS, RP0 INTCON, T0IE INTCON, GIE ; Sterge TMR0 ; Dezactiveaza toate intreruperile si sterge T0IF ; Bank1 ; fara prescaler ; Bank0 ; Activeaza intreruperea de Timer0 ; Activeaza intreruperile

repeta NOP NOP NOP ; bucla infinata GOTO repeta end

2011.Mai.25

Exemplul 3: Avem un PIC ce lucreaz cu un oscilator de 20MHz. Ne propunem sa generam ntreruperi cu perioada 1.314 ms. Calculam citi cicli procesor sunt necesari pentru o durata de 1314 us: 1314 / 0.2 = 6570 cy. (La un quartz de 20MHz, rezulta 5MHz viteza de execuie a instruciunilor, deci 0.2us este durata unei instruciuni) Sa determinam de ce prescaler avem nevoie: 6570 / 256 = 25.664 Obs:Daca am avea un prescaler de 25.66 si l-am selecta, mpreuna cu TMR0 lsat liber sa mearg (fr sa-l ajustam, depirea producndu-se dup cea de-a 256-a incrementare) am obine intervalul dorit. ns nu avem astfel de prescaler! Alegem un prescaler mai mare: 32 Obs:Cu un prescaler de 32, si TMR0 lsat liber (sa se incrementeze de 256 ori) obinem 32 * 256 = 8192 cy. Noi avem nevoie doar de 6750cy, deci va fi necesar sa ajustam TMR0, sa se incrementeze mai puin de 256 ori. Ca sa aflam de cate ori trebuie sa se incrementeze TMR0 cu prescalerul ales (32) facem: 6570 / 32 = 205.3 Pentru ca TMR0 sa se incrementeze de 205 ori, va trebui sa-l ajustam cu 256 205 = 51 (daca TMR0 pornete de la 51, atunci el se va incrementa de 205 ori, cat avem nevoie) Ajustarea o vom face in ntrerupere, adunnd 51 la valoarea curenta a lui TMR0. Frecventa 20 MHz 5 MHz Perioada 0.2 us 6.4 us 1312 us

Semnalul de la oscilator (Fosc) Executia instructiunilor (Fcy) Semnalul dupa prescaler 32 Timer0 incrementat de 205 de ori

Prescalerul l activam din bitul PSA si selecta cu PSx din OPTION_REG. Obinem o perioada reala de activare a ntreruperilor de 1.3134 ms. Eroarea este de 13141313.4=0.6 us Obs.:Daca nu am fi folosit prescaler (daca am fi avut in TMR0 mai mare de 8 biti) eroarea maxima acceptabila ar fi fost de un ciclu instruciune, deci de 0.2us. Deoarece in acest exemplu folosim un prescaler de 1:32 (iar contorul intern al prescalerului nu ne este accesibil), eroarea maxima acceptabila este de aceeai mrime cu prescalerul, deci 16cicli, echivalent cu 16*0.2 = 3.2us. Atunci cnd folosim un prescaler mare, nu mai putem face corecia de 3 cicli maina cit timp este ngheat timerul; TMR0 sta inghetat 3 cicli, insa in acest timp el oricum nu ar fi fost incrementat, deoarece naintea lui este prescalerul care se incrementeaza, si doar cand ajunge prescalerul la maxim, se pareste TMR0 cu o unitate. deoarece TMR0 se incrementeaz la fiecare pp instruciuni (daca prescalerul e setat 1:pp) (cu alte cuvinte acei 3 cicli pierdui sunt cumva mascai de incrementarea presalerului). Daca din greeala am ncerca sa facem corecia, am genera in schimb o eroare de 3*pp.

2011.Mai.25

LIST P=16F887;, F=INHX8M #include "p16f887.inc" radix dec


;__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _LVP_OFF & _DEBUG_OFF

errorlevel 1, -305 CBLOCK 0x20 ENDC ORG 0 CLRF CLRF GOTO STATUS PCLATH init

;************ initial ******************* org 4 ; procedura de tratare a intreruperilor CLRF STATUS ; trece in bank 0 MOVLW 51 ADDWF TMR0 BSF PORTB, 7 BCF PORTB, 7 BCF INTCON,T0IF ; stergem flagul de intrerupere RETFIE init CLRF CLRF BSF MOVLW MOVWF BCF BSF BSF TMR0 INTCON STATUS, RP0 0x04 OPTION_REG STATUS, RP0 INTCON, T0IE INTCON, GIE

; Bank1 ; prescaler 1:32 ; Bank0 ; Activeaza intreruperile

repeta NOP ; bucla infinata GOTO repeta end

2011.Mai.25

Din MPLAB folositi: Debugger-> SelectTool -> MplabSim View -> Watch -> AddSFR -> TMR0 Debugger -> Settings -> ProcessorFrequency Debugger -> StopWatch (folositi Zero pentru a-l reseta) Un dublu-click pe marginea din stnga in MPLAB aduga un breakpoint (rulearea in simulare se va opri intodeauna la breakpoint) Rulai pas cu pas si urmrii cum evolueaz TMR0. Observai ce se ntmpla atunci cnd depaseste FFh. Folosind StopWatch msurai care este durata dintre 2 activri succesive ale ntreruperii (rulai pas cu pas sau folosii un breakpoint pe prima instruciune din ntrerupere) Obs. Ignorai prima activare a ntreruperii; msurai timpul numai intre 2 ntreruperi. Exercitiul 1: Pornind de la exemplu 2, generai ntreruperi cu perioada de exact 35us. Considerai un PIC cu un oscilator de 20MHz. Obs: odat ce o noua valoare este scrisa in TMR0, dureaz 2+1 cicli pana TMR0 pornete cu valoarea scrisa; Este necesara o corecie de +3 atunci cnd modificam TMR0 si-l folosim fara prescaler, pentru a obine un interval precis. Exercitiul 2: Generai un impuls la fiecare 15 ms. Considerai un PIC cu un oscilator de 16MHz. Exercitiul 3: Generai un impuls la fiecare 131 ms. Deoarece prescalerul lui Timer0 nu este deajuns de mare, va trebui sa implementai in software un contor ce se modifica la fiecare generare de ntrerupere, si numai cnd ajunge la valoarea dorita sa se genereze impusul. Fata de exemplele precedente adugai in ntrerupere salvarea si restaurarea registrelor STATUS,W (Datasheet->SpecialFeaturesOfTheCpu>Interrupts) si actualizarea contorului.
ORG 0 ... GOTO main ORG 4 ;salvare registri ; corectie TMR0 ; actualizare contor ; contor=valoare_dorita? ; DA-> generare_impuls, reinitializare_contor ;sterge T0IF ;restaurare registri RETFIE main ;initializare TMR0 ; initializare_contor ; activare intreruperi ... repeta GOTO repeta

2011.Mai.25

S-ar putea să vă placă și