Il Timer0 sui PIC18

timerE' mia intenzione implementare del codice che sfrutta il Timer0 del PIC 18F4550; la particolarità di tale timer è che è impostabile a 8 o 16 bit; in quest'ultima configurazione il timer incrementa cioè di un'unità ad ogni ciclo di clock (Fosc/4) per raggiungere un valore massimo pari a 65535 (2^16-1), oltre il quale torna a zero e va in overflow, attivando il flag di interrupt T0IF.

Nel seguente codice ho impostato i vari registri che controllano il Timer0 in maniera da ottenere un overflow ogni secondo; per tale durata un LED (PORTD,0) resterà alternativamente acceso e spento: 1 sec acceso, 1 sec spento, …

Registri relativi al TMR0

T0CON

Questo registro sarà il primo e l'ultimo che verrà inizializzato, per le ragioni che di seguito spiego.

Infatti è importante che lo settiamo subito per la modalità a 16bit, azzerando il bit 6 T08BIT; le seguenti impostazioni sui registri di TMR0 saranno una conseguenza di questa modalità; con l'occasione impostiamo il prescaler a 1:256 (bit 2-0 a '111').

 movlw 0x07            ;setta TMR0 a 16bit, prescaler a 1:256
 movwf T0CON

Il bit TMR0ON, che avvia il timer0, sarà invece l'ultima cosa che faremo nella routine di inizializzazione.

TMR0H e TMR0L

Questi sono i due registri, alto e basso, che compongono TMR0; a che valori devono essere impostati?

Innazitutto qualche calcolo preliminare; uso un quarzo a 20Mhz, il che implica un Fosc/4 di 5Mhz, cioè 5.000.000 operazioni al secondo, ovvero un'operazione ogni 0,2 us (microsecondi); senza prescaler TMR0 andrebbe in overflow troppo presto, cioè dopo circa 13 ms (0,000002s x 65535).

Provo ad impostare il prescaler al massimo, cioè a 1:256, in maniera che la frequenza di incremento di TMR0 si riduca a 5000000 / 256, cioè a circa 19531Hz.

Il prescaler non riduce in alcun modo il clock del PIC! Va ad agire unicamente sulla frequenza di incremento di TMR0

Con queste frequenze ridotte, se TMR0 conta fino a 19531 significa che è passato un secondo; ma TMR0 conta fino a 65535 e solo superata tale soglia genera un interrupt, che è possibile intercettare. E' necessario quindi, in fase di inizializzazione, impostare un valore di partenza di TMR0, caricandolo nei suoi due registri alto e basso.

Il calcolo è presto fatto, perchè 65535-19531=46004, che espresso in esadecimale fa 0xB3B4; quest'ultimo sarà il valore che dovrà essere caricato in TMR0H e TMR0L.

In altre parole tale valore di partenza consente di raggiungere l'overflow di TMR0 dopo 19531 cicli, i quali sono processati in un secondo.

 movlw 0xB3          ;imposta valore iniziale registri TMR0
 movwf TMR0H
 movlw 0xB4
 movwf TMR0L

E' possibile scegliere anche il valore di prescaler di 1:128; la frequenza risultante sarebbe infatti 50000000/128=39062Hz, valore che TMR0 dovrebbe contare, partendo da 26473, per raggiungere la condizione di overflow. Un prescaler di 1:64 invece non andrebbe bene, perchè la frequenza di circa 78KHz sarebbe superiore a 65536, massimo raggiungibile dal TMR0 a 16 bit

Ultime inizializzazioni registri

Di seguito abilito l'interrupt da TMR0 e il General Interrupt:

 bsf INTCON, TMR0IE     ;abilita interrupt da TMR0
 bsf INTCON,GIE     ;abilita GIE Interrupt

E come ultima cosa avvio Timer0:

 bsf T0CON,TMR0ON       ;avvia TMR0

ISR

Tutta la gestione dell'interrupt avverrà nella routine apposita (ISR); dopo che il programma sarà 'saltato' nella locazione apposita per la gestione degli interrupt generici, verificherà l'attivazione del flag specifico di interrupt da overflow di TMR0 e attiverà l'apposita subroutine.

 btfsc INTCON,TMR0IF    ;testa se l'interrupt deriva da Overflow TMR0
 goto IsrTmr0

La subroutine fa due cose; in primis effettua un toggle di un LED, secondariamente reimposta i valori di TMR0H e TMR0L al valore 0xB3B4 e rimuove il flag T0IF, così che si possa intercettare la successiva condizione di overflow.

IsrTmr0
 movlw b'00000001'      ;Routine di overflow di TMR0
 xorwf PORTD            ;effettua il toggle di PORTD,0
 movlw 0xB3             ;ricarica TMR0
 movwf TMR0H
 movlw 0xB4
 movwf TMR0L
 bcf INTCON,TMR0IF      ;azzera flag TMR0IF
Attachment: 

Add new comment

Filtered HTML

  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <p> <h1> <h2> <h3> <h4> <h5> <div> <pre> <object>
  • You may insert videos with [video:URL]
  • Web page addresses and e-mail addresses turn into links automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.