Utilizzare il reload timer

Nella maggior parte dei casi i timer dispongono di logica di comparazione e capacità di reload che consentono di implementare, così, la generazione di forme d’onda in uscita con modulazione PWM o il conteggio di eventi in ingresso, il tutto con intervento minimale da parte della CPU. Vediamo come utilizzare questa funzione nei micro Fujitsu F²MC-16FX.

Il timer è certamente una delle periferiche più semplici di un microcontrollore ma, sotto certi aspetti, anche una delle più flessibili. Nella maggior parte dei casi i timer dispongono di logica di comparazione e capacità di reload che consentono di implementare, così, la generazione di forme d’onda in uscita con modulazione PWM o il conteggio di eventi in ingresso, il tutto con intervento minimale da parte della CPU. In altri, vi è la possibilità di utilizzare un segnale di trigger o clock esterno ed avere, così, misure di frequenza o, in generale, contatori di evento. Di seguito sono mostrati alcuni esempi di utilizzo di questo tipo del reload timer dei microcontrollori a 16-bit della serie F²MC-16FX per applicazioni automotive di Fujitsu. Per maggiori dettagli si rimanda all’Application Note indicata nei riferimenti [1].

Figura 1. Reload timer dei micro F²MC-16FX

ARCHITETTURA DEL TIMER

La Figura 1 mostra uno schema di principio dell’architettura interna del reload timer dei micro F²MC-16FX. Il timer ha risoluzione 16-bit, capacità di reload e pre-scaling del clock, supportando così la misura di intervalli temporali tra 125 ns e 263 ms con clock di 16 MHz (nel configurare il reload timer fare attenzione al fatto che la periferica è clockata dalla linea di clock CLKP1, generata internamente al microcontrollore mediante divisione del clock CLKS1). Il reload timer può operare in modalità one-shot o reload. Dispone di uscita verso un pin di I/O del dispositivo (attivata, in un livello configurabile, in corrispondenza del trigger e commutata in corrispondenza di un evento di overflow), ingresso esterno di clock/trigger e linea di interruzione verso la CPU (abilitabile in corrispondenza di un evento di underflow). Le funzionalità principali della periferica (come modalità di abilitazione, selezione della modalità operativa, selezione del clock e del relativo fattore di pre-scaling) sono controllate dal registro TMCSR, la cui descrizione è riportata per convenienza nella Tabella 1. Il registro TMRLR definisce il valore di reload in corrispondenza dell’evento di trigger, mentre il valore corrente del timer è accessibile mediante il registro TMR. Il registro TMISR definisce, invece, la selezione, proprio, del segnale di trigger stesso, supportando così, da esempio, la connessione di diversi timer in cascata.

Tabella 1: il registro TMCSR del reload timer.

Tabella 1: il registro TMCSR del reload timer

INTERVAL TIMER

L’esempio più semplice di utilizzo del reload timer è certamente come interval timer. In questo caso il timer viene in genere clockato con il clock interno (CLKP1). E’ sufficiente, allora, programmare il valore di reload nell’opportuno registro per definire la finestra temporale che si intende generare ed abilitare il timer, scegliendo il fattore di scaling del clock (FSEL, CSL0 e CSL1 del registro TMCSR); in corrispondenza dell’evento di overflow è possibile generare un’interruzione alla CPU (TMCSR.INTE) e verso il pin di uscita (TMCSR.OUTE). Il timer potrà, come detto, essere configurato, infine, in modalità one-shot o reload (TMCSR.RELD) a seconda che si richieda un singolo evento o uno periodico. In modalità reload, sulla linea di uscita del modulo (si ricordi che questa commuta in corrispondenza di ogni overflow) sarà generata una forma d’onda periodica di frequenza data dalla relazione seguente:

dove, appunto, divsel è il fattore di divisione impostato e R il valore di reload. La frequenza di interruzioni alla CPU è, ovviamente, il doppio di questa. Il Listato 1 mostra il semplice codice per gestire un'applicazione del tipo descritto. In questo caso, come si può vedere (fare riferimento alla precedente Tabella 1), il fattore di divisione è impostato a 2 e quindi la frequenza di evento di overflow è di 488 kHz con clock di ingresso a 16 MHz. Essendo il bit TRG attivo, il timer è triggerato al momento della configurazione. Come si può vedere, inoltre, il bit TMCSR.INTE è attivo e quindi sarà generata una interruzione alla CPU in corrispondenza dell’evento di overflow (ricordarsi di attivare la linea corrispondente anche nella configurazione del registro ICR del microcontrollore). Lo stesso Listato 1 riporta un semplice prototipo dell’interrupt handler per il reload timer che implementa il solo reset della flag di underflow.

void InitReloadTimer0(void)
{
TMRLR0 = 0x2000; // set reload value
TMCSR0 = 0x105B; // prescaler 1:2
}
__interrupt void ReloadTimer0 (void)
{
TMCSR0_UF = 0; // reset underflow interrupt request flag
}
Listato 1

TIMER CON TRIGGER ESTERNO

Come accennato in precedenza, è possibile configurare il timer per accettare un segnale di trigger esterno (mediante pin dedicato del microcontrollore). L’applicazione più tipica di questo è, ad esempio, la generazione di un segnale di controllo sulla linea di uscita del timer (con durata specificata) in corrispondenza di un evento. Si pensi alla generazione di un suono di allarme in corrispondenza della pressione di un tasto del sistema; in questo caso, l’evento di trigger corrisponde con la pressione del tasto e l’uscita del reload timer può essere usata per pilotare (eventualmente mediante opportuno amplificatore) un buzzer. Il Listato 2 mostra il codice per gestire una tale applicazione.

void InitReloadTimer0(void)
{
TMRLR0 = 0x1869; // set reload value = 6249
PIER08_IE0 = 1; // enable TIN0 input pin
TMCSR0 = 0x083C; // prescaler 1:64, trigger input–rising edge, output
// enable, count enable, trigger
}
void main(void)
{
InitReloadTimer0();
while(1);
}
Listato 2

Come si può vedere (al solito fare riferimento alla Tabella 1 per il contenuto del registro di controllo TMCSR) i bit di modo MOD[2:0] assumono il valore 001, configurando il timer nella modalità con trigger esterno di tipo rising-edge. E’ il caso di osservare, inoltre, che affinchè l’applicazione del Listato 1 funzioni correttamente è necessario, come nell’esempio mostrato, che il pin di ingresso del microcontrollore sia correttamente configurato, settando l'IE bit del corrispondente registro PIERx. L’applicazione funziona usando il fronte attivo del segnale di trigger per attivare il timer. In realtà, questo può essere configurato in modo da essere attivato in funzione del livello del segnale (ingresso di gate) e non della sua transizione. Per fare ciò il bit MOD[2] del registro TMCSR deve essere impostato ad "1".

CONTATORE DI EVENTO

Oltre che come trigger, come abbiamo appena visto, l’ingresso esterno del reload timer può anche essere usato come clock. In questo caso il timer si decrementa in corrispondenza di una transizione (di polarità configurabile) del segnale; perché questa venga vista correttamente, tuttavia, il segnale esterno deve restare attivo per almeno 4 periodi del clock del timer. Una tale modalità di "contatore di evento" può essere utilizzata, ad esempio, per misurare la frequenza di un segnale esterno. E’ necessario disporre di un secondo timer per definire una finestra di conteggio di durata prefissata. Il codice sorgente per gestire una tale applicazione è mostrato nel Listato 3. Come si può vedere, il timer 0 è configurato per generare una interruzione alla CPU dopo un intervallo di 1 secondo (CLKP1 ha una frequenza di 4 MHz) mentre il timer 1 opera appunto nella modalità "contatore di evento" appena descritta. La routine di gestione dell’interrupt del timer 0 non fa altro che leggere il valore del timer 1 e calcolare il numero di volte che è stato decrementato, corrispondente al numero di eventi sul segnale di ingresso.

void InitReloadTimer0_1(void)
{
TMRLR0 = 0xF423; // set reload value = 62499
TMRLR1 = 0xFFFF; // set event counter value
PIER01_IE0 = 1; // enable TIN1 input pin
TMCSR0 = 0x080B; // prescaler 1:64, count enable, interrupt enable,
// trigger
TMCSR1 = 0x1C83; // External count mode, event input, rising edge,
// count enable, trigger
}
unsigned int Frequency;
void main(void)
{
InitReloadTimer0_1();
while (1);
}
__interrupt void ReloadTimer0 (void)
{
TMCSR0_UF = 0; // reset underflow interrupt request flag
Frequency = 0xFFFF – TMR1; // calculate frequency
TMCSR0_INTE = 0;
Listato 3
Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend