Salve ragazzi, oggi vorrei parlare di timer interrupt!
Più che altro mi piacerebbe che foste voi a parlarmente.
Vorrei ampliare le mie conoscenze, ho già fatto qualche ricerca.
Per quello che ho capito un timer interrupt non è altro che un evento scatenato dall'overflow di una variabile.
E questo come si mette in pratica?
Altra domanda, l'overflow di una variabile vale solamente quando va oltre il limite consentito per quella variabile (per esempio se dichiaro una variabile bit, l'overflow sarà al raggiungimento del valore due, se dichiaro un byte l'overflow sarà al raggiungimento di 256)?
non l'overflow di una variabile, ma di un registro. quindi la dimensione è fissa, ma esiste un altro registro in cui puoi impostare il valore massimo da raggiungere. Quindi l'overflow può avvenire <= dimensione registro
lesto:
non l'overflow di una variabile, ma di un registro. quindi la dimensione è fissa, ma esiste un altro registro in cui puoi impostare il valore massimo da raggiungere. Quindi l'overflow può avvenire <= dimensione registro
Di che registro si tratta? E' un registro che è fatto apposta oppure lo si utilizza occasionalmente per questo?
E come lo si programma?
sono 2 registri fatti apposta. se vuoi un bell'esempio, cerca la swRTC di leo72 che in pratica è una libreria che setta il tutto per avere un overflow ogni secondo, e poi conta questi secondi per fare un orologio
lesto:
sono 2 registri fatti apposta. se vuoi un bell'esempio, cerca la swRTC di leo72 che in pratica è una libreria che setta il tutto per avere un overflow ogni secondo, e poi conta questi secondi per fare un orologio
Se ti devo dire la verità non ho capito molto...
Per gestire i registri intanto cosa devo fare? Includere la libreria WProgram?
Partire da zero parlando di un argomento così complesso NON è l'approccio migliore.
Quindi, ti consiglio di prendere il datasheet ed iniziare a leggerti le pagine dalla 95 alla 144. Lì trovi come funzionano i timer e gli interrupt ad essi collegati, vedi la differenza nel gestire un timer ad 8 bit ed uno a 16 bit, vedi tutti i nomi dei registri e dei flag che puoi e devi usare per impostare le varie funzioni, vedi le diverse modalità operative di un timer.
Ogni timer può ad esempio assumere diverse modalità operative, può generare un interrupt quando va in overflow oppure, come ha detto lesto, generarlo quando raggiunge un valore prefissato. Può ripartire da zero oppure da un altro valore. Può operare solo internamente oppure gestire anche i pin ad esso associato (è così che funzionano i segnali PWM, che sono generati dai timer in maniera diretta), ecc...
Non si può riassumere in un post, si dovrebbe scrivere qualcosa come decine di post di spiegazioni....
Un ultima domanda.
Ho capito che ci sono 3 timer, e abbiamo 6 uscite PWM ciò significa che ogni timer ne gestisce due! Quindi se io dovessi andare a utilizzare uno di questi timer dovrei rinunciare ad utilizzare i pin PWM alla quale sono assegnati!
Ma non li posso più utilizzare definitivamente (dunque neanche come pin digitali) o solo come PWM?
Dipende.
Dipende dal fatto se stai usando il timer collegato ai pin oppure no. Esempio: vedi la swRTC, dove il timer 2 è usato come semplice contatore e non per generare segnali sui pin. Se invece agganci il timer ai pin, dopo non puoi usare la funzione PWM di Arduino perché i pin genereranno la frequenza impostata da te.
I timer sol 328 sono 3: il 1° ed il 3° sono ad 8 bit, il 2° a 16 bit.
leo72:
Dipende.
Dipende dal fatto se stai usando il timer collegato ai pin oppure no. Esempio: vedi la swRTC, dove il timer 2 è usato come semplice contatore e non per generare segnali sui pin. Se invece agganci il timer ai pin, dopo non puoi usare la funzione PWM di Arduino perché i pin genereranno la frequenza impostata da te.
I timer sol 328 sono 3: il 1° ed il 3° sono ad 8 bit, il 2° a 16 bit.
Come consigliato io sto leggendo il datasheet dell'ATMega328 però non è molto facile capire come funziona un timer.
Ho stampato anche le pagine con i vari registri.
Per esempio il TIMER/COUNTER1 ha 8 registri.
OCR1BH
OCR1BL
OCR1AH
OCR1AL
ICR1H
ICR1L
TCNT1H
TCNT1L
I primi quattro sono "Output Compare Register", però la domanda è, se il TIMER 1 è a 8 BIT perchè ci sono 2 byte? (Intendo High Byte e Low Byte).
Altra domanda, cos'è un "Compare Register"?
TCNT1H e TCNT1L credo siano i byte che immagazinano il valore del conteggio no?
Xfox:
Per esempio il TIMER/COUNTER1 ha 8 registri.
OCR1BH
OCR1BL
OCR1AH
OCR1AL
ICR1H
ICR1L
TCNT1H
TCNT1L
I primi quattro sono "Output Compare Register", però la domanda è, se il TIMER 1 è a 8 BIT perchè ci sono 2 byte? (Intendo High Byte e Low Byte).
Stai facendo un po' di confusione
Il timer 1 è il 2° timer, non il 1°. I timer sono 0, 1 e 2. In informatica la maggior parte delle volte la numerazione parte da 0, non da 1.
OCR1BH/L sono registri del timer 1, quindi a coppie di byte per formare registri a 16 bit.
Per capire di che timer è un registro, basta vedere il numero presente nel registro stesso:
OCR0A è il registro Output Compare Reg. A del timer 0, OCR1AH è il byte alto del registro OCRxA del timer 1.
Altra domanda, cos'è un "Compare Register"?
Il compare register contiene un valore preimpostato che, se il timer viene usato in modalità generazione d'onda, viene confrontato con il valore del timer stesso per generare un segnale. Immaginalo come un valore preimpostato, una specie di "segno".
TCNT1H e TCNT1L credo siano i byte che immagazinano il valore del conteggio no?
Sì, ma sempre del 2° timer, quindi 2 byte per un registro a 16 bit.
E ICR1H e ICR1L?
E' una specie di segnatempo per registrare il valore del timer1 a cui si è generato un dato evento esterno. Sinceramente non l'ho mai usato, né immagino la sua utilità nell'uso da "comuni mortali" che facciamo noi dei micro
Allora mettiamo caso che io voglio utilizzare un timer per richiamarmi una funzione ogni 100 ms.
Dovrei impostare uno dei due compare register a quel valore in modo che quando il secondo raggiunge lo stesso richiama una funzione?
No, i registri OCR si usano per generare forme d'onda.
Per la tua funzione devi impostare il timer sulla modalità classica (incrementale) in modo che all'overflow del contatore venga generato un interrupt.
Il tutto però va calcolato in base al registro usato (se ad 8 o 16 bit), al prescaler ed alla frequenza del micro in modo da avere un overflow ogni tot.
Nella swRTC trovi una formula che calcola il tempo tra 2 overflow dati il valore iniziale del contatore, il suo valore max, il prescaler e la frequenza del micro.
leo72:
No, i registri OCR si usano per generare forme d'onda.
Per la tua funzione devi impostare il timer sulla modalità classica (incrementale) in modo che all'overflow del contatore venga generato un interrupt.
Il tutto però va calcolato in base al registro usato (se ad 8 o 16 bit), al prescaler ed alla frequenza del micro in modo da avere un overflow ogni tot.
Nella swRTC trovi una formula che calcola il tempo tra 2 overflow dati il valore iniziale del contatore, il suo valore max, il prescaler e la frequenza del micro.
Cosa significa impostare il timer sulla modalità classica?
Prendendo di riferimento swRTC:
//the following code sets the prescaler depending on the system clock
if (F_CPU == 16000000UL) { // prescaler set to 64
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
Imposta il prescaler a 64, ma cosa significa esattamente? Che 250000 volte al secondo viene incrementato il registro che si deve portare all'overwlof?
Cosa significa impostare il timer sulla modalità classica?
Ad esempio cap 14.7: Timer 0 - Normal mode
Viene incrementato il contatore finché non raggiunge il suo valore massimo e va in overflow generando dopodiché il conteggio riparte dall'inizio.
Imposta il prescaler a 64, ma cosa significa esattamente? Che 250000 volte al secondo viene incrementato il registro che si deve portare all'overwlof?
Vuol dire che il clock del sistema viene diviso per 64. Quindi se tu hai un clock a 1 MHz, sono 1.000.000 di colpi al secondo. Usando un prescaler a 64, hai in realtà 15.625 colpi al secondo. Il prescaler si usa per "rallentare" la velocità con cui viene incrementato il contatore interno.
Cosa significa impostare il timer sulla modalità classica?
Ad esempio cap 14.7: Timer 0 - Normal mode
Viene incrementato il contatore finché non raggiunge il suo valore massimo e va in overflow generando dopodiché il conteggio riparte dall'inizio.
Imposta il prescaler a 64, ma cosa significa esattamente? Che 250000 volte al secondo viene incrementato il registro che si deve portare all'overwlof?
Vuol dire che il clock del sistema viene diviso per 64. Quindi se tu hai un clock a 1 MHz, sono 1.000.000 di colpi al secondo. Usando un prescaler a 64, hai in realtà 15.625 colpi al secondo. Il prescaler si usa per "rallentare" la velocità con cui viene incrementato il contatore interno.
In normal operation the Timer/Counter Overflow Flag (TOV0) will be set in the same
timer clock cycle as the TCNT0 becomes zero.
Questo significa che il flag TOV0 (E' un bit?) quando è 1 ha generato l'evento di overflow?
A te non interessa controllare quel flag, a te interessa intercettare l'evento immediatamente quando accade. Per questo si usa l'interrupt.
Nel momento in cui viene chiamato, l'interrupt si occupa anche di ripulire tale flag.
Vedi sempre la swRTC dove c'è il bit di flag per attivare l'interrupt sull'overflow del contatore e la routine che intercetta l'overflow. Ovviamente per ogni timer e per ogni modalità esiste la sua routine di intercettazione dell'interrupt, ma trovi tutto nel datasheet.
leo72:
A te non interessa controllare quel flag, a te interessa intercettare l'evento immediatamente quando accade. Per questo si usa l'interrupt.
Nel momento in cui viene chiamato, l'interrupt si occupa anche di ripulire tale flag.
Vedi sempre la swRTC dove c'è il bit di flag per attivare l'interrupt sull'overflow del contatore e la routine che intercetta l'overflow. Ovviamente per ogni timer e per ogni modalità esiste la sua routine di intercettazione dell'interrupt, ma trovi tutto nel datasheet.
Ciò che intercetta l'overflow sarebbe questo?:
ISR(TIMER2_OVF_vect) {}
Cioè quello che c'è fra le due parentesi viene generato ogni volta che si ha un overflow del registro?
Ma nel datasheet nel paragrafo 15 (o i vari paragrafi dei vari timer) ci sono scritte tutte le istruzioni necessarie per svolgere tutte le operazioni svolte nel codice di swRTC?
Ad esempio:
//during setup, disable all the interrupts based on timer 0
TIMSK0 &= ~(1<<TOIE0);
TIMSK0 &= ~((1<<OCIE0A) | (1<<OCIE0B));
Te lo chiedo perchè io prima ho provato a cercare sul datasheet il nome dell'evento (TIMER2_OVF_vect) ma non ha generato risultato.
P.S.
Vorrei ringraziarti per tutte le spiegazioni che mi stai dando
Nel datasheet ci sono tutte le info sui vari registri, che sono poi quelli che ho usato per manipolare i timer nella swRTC. Ovviamente devi leggerti un bel po' di volte quelle pagine prima di capirci qualcosa...
TIMER2_OVF_vect non lo trovi, è un nome dell'IDE di Arduino, ma trovi la tabella dei vettori degli interrupt (vect), cercando TIMER2_OVF mi pare. Cmq è tutto nella sezione relativa agli interrupt.