Timer di interruzione di Arduino UNO

Il timer è una funzione incorporata in ogni microcontrollore e svolge alcune funzioni relative allo scorrere del tempo. La funzione del timer in un microcontrollore può essere spiegata in modo specifico: il timer funziona per determinare quando il programma verrà eseguito e quando verrà interrotto. Il timer di un microcontrollore è costituito da diversi registri i cui valori diminuiscono e aumentano automaticamente. Su Arduino UNO sono presenti due tipi di timer, uno con risoluzione a 8 bit e uno con risoluzione a 16 bit. Tuttavia, FS Tech non tratterà questo timer in modo più specifico perché in questa istruzione ci concentriamo su come eseguire e impostare il timer su Arduino UNO.

Perché utilizzare un timer di interruzione

L'impostazione del timer sul microcontrollore ci permette di eseguire programmi con tempi ben precisi a determinati intervalli di tempo in modo multitasking. Come sappiamo, Arduino esegue un programma in loop utilizzando la funzione void loop(void) {} nell'ordine in cui è stata scritta, ma sarà molto difficile determinare il tempo degli eventi contenuti in questa funzione. Ciò accade perché alcuni comandi vengono eseguiti molto rapidamente e altri molto lentamente, il che è determinato dal numero di programmi eseguiti e dalle dichiarazioni condizionali come if, while, do while o for loop. Il timer che gira sulla funzione loop() di Arduino è molto difficile da prevedere a causa delle numerose funzioni contenute nella libreria di Arduino.

Il timer di interruzione del microcontrollore consente di controllare il tempo di esecuzione della funzione loop() a intervalli di tempo precisi; quando il timer di interruzione viene eseguito, interrompe il tempo di esecuzione della funzione loop() ed esegue una serie di programmi separati che vengono eseguiti su un timer al di fuori della funzione loop() e che ritornano al timer per eseguire nuovamente la funzione loop() dopo che un altro timer ha terminato l'esecuzione del programma.

Alcuni dei vantaggi offerti dall'esecuzione di un timer di interruzione sono:

  • Misura i segnali in entrata a intervalli regolari
  • Calcola il tempo tra due programmi
  • Trasmette e genera segnali a determinate frequenze.
  • Controllare periodicamente i dati seriali in entrata
  • Eseguire due programmi contemporaneamente (multitasking)
  • E molti altri

Prescaler e calcolo dei valori dei timer

Arduino UNO dispone di tre timer, Timer-0, Timer-1 e Timer-3. Ogni timer di Arduino Uno ha un'impostazione temporale che aumenta a ogni periodo di tempo fino a raggiungere un determinato valore che viene memorizzato in un registro e che viene azzerato ogni volta che il valore temporale viene raggiunto. Questo ciclo continua quando Arduino è acceso. Il valore del timer dipende dalla dimensione dei bit dell'indirizzo del timer; ad esempio, un timer con un valore di 8 bit ha un intervallo di valori compreso tra 0-255 e un timer con una risoluzione di 16 bit ha un intervallo di valori compreso tra 0-65535.

Per poter calcolare un timer, possiamo utilizzare un calcolo chiamato prescaler, che può essere scritto con la seguente equazione.

TimerSpeed(Hz) = ArduinoClockSpeed(16MHz) / prescaler

valore del prescaler all'indirizzo del prescaler

La tabella precedente mostra il valore del prescaler a ciascun indirizzo del prescaler, in modo che l'equazione per il valore di calcolo del temporizzatore possa essere scritta utilizzando la seguente equazione.

InterruptFrequency(Hz) = ArduinoClockSpeed(16MHz) / ((prescaler * (compareMatchRegister + 1))

+1 grazie al confronto dei valori corrispondenti del registro indicizzato a 0.

Quindi, se si desidera un valore di prescaler, l'equazione può essere scritta secondo la seguente equazione.

CompareMatchRegister = 16MHz / (prescaler * DesiredInterruptFrequency) - 1

Tenete presente che se utilizzate il Timer-0 e il Timer-2 il valore deve essere inferiore a 256 e se utilizzate il Timer-1 il valore deve essere inferiore a 65536. 

Come utilizzare gli interrupt del timer per eseguire programmi multitasking

Timer-0 2KHz

				
					void setup(void) {
	cli();
	TCCR0A = 0;
	TCCR0B = 0;
	TCNT0 = 0;
	OCR0A = 124;
	TCCR0A |= (1<<WGM01);
	TCCR0B |= (1<<CS01) | (1<<CS00);
	TIMSK0 |= (1<<OCIE0A);
	sei();
}
				
			

TCCR0A = 0; TCCR0B, TCNT0 = 0; è per riportare a 0 il valore del tempo.

OCR0A imposta il registro di confronto per incrementi di 2KHz (16*10^6)/(2000*64)-1

WGM01 accendere CTC

CS01 e CS00 impostare i bit CS01 e CS00 per il prescaler 64

TIMSK0 abilita l'interrupt di confronto del timer

Timer-1 1Hz

				
					void setup(void) {
	cli();
	TCCR1A = 0;
	TCCR1B = 0;
	TCNT1 = 0;
	OCR1A = 15624;
	TCCR1B |= (1<<WGM12);
	TCCR1B |= (1<>CS10);
	TIMSK1 |= (1<<OCIE1A);
	sei();
}
				
			

TCCR1A = 0; TCCR1B, TCNT1 = 0; è per riportare a 0 il valore del tempo.

OCR1A imposta il registro di confronto per incrementi di 1Hz (16*10^6)/(1*1024)-1

WGM12 accendere CTC

CS10 e CS12 impostare i bit CS10 e CS12 per il prescaler 1024

TIMSK1 abilita l'interrupt di confronto del timer

Timer-2 8KHz

				
					void setup(void) {
	cli();
	TCCR2A = 0;
	TCCR2B = 0;
	TCNT2 = 0;
	OCR2A = 249;
	TCCR2A |= (1<<WGM21);
	TCCR2B |= (1<<CS21);
	TIMSK2 |= (1<<OCIE2A);
	sei();
}
				
			

TCCR2A = 0; TCCR2B, TCNT2 = 0; è per riportare a 0 il valore del tempo.

OCR2A imposta il registro di confronto per incrementi di 8KHz (16*10^6)/(8000*8)-1

WGM21 attivare CTC

CS21 impostare i bit CS21 per il prescaler 8

TIMSK1 abilita l'interrupt di confronto del timer

Perhatikan bagaimana ke tiga Timer diatur, misalnya untuk mengaktifkan mode CTC

TCCR0A |= (1 << WGM01); // per il timer 0

TCCR1B |= (1 << WGM12); // per il timer 1

TCCR2A |= (1 << WGM21); // per il timer 2

Dan perhatikan nilai prescaler yang diatur sesuai pada tabel diatas.

TCCR1B |= (1 << CS11); // 8 prescaler per il timer 1 

TCCR2B |= (1 << CS22); // 64 prescaler per il timer 2

TCCR0B |= (1 << CS02) | (1 << CS00); // 1024 prescaler per il timer 0

Il comando che si vuole eseguire durante l'interrupt del timer è nello sketch di Arduino riassunto come segue, al di fuori della funzione void setup(void) e della funzione void loop(void), e sono anche spiegati gli esempi di ciascun timer.

ISR(TIMER0_COMPA_vect) {

// per il timer 0

}

ISR(TIMER1_COMPA_vect) {

// per il timer 1

}

ISR(TIMER2_COMPA_vect) {

// per il timer 2

}

Esempio di programma Arduino per attivare un timer

Esempio per Timer-0 2KHz

				
					void setup(void) {
	pinMode(11, OUTPUT);
	
	cli();
	TCCR0A = 0;
	TCCR0B = 0;
	TCNT0 = 0;
	OCR0A = 124;
	TCCR0A |= (1<<WGM01);
	TCCR0B |= (1<<CS01) | (1<<CS00);
	TIMSK0 |= (1<<OCIE0A);
	sei();
}
void loop(void) {
	// fa qualcosa senza delay()
}
ISR(TIMER0_COMPA_vect) {
	booleano statico toggle = true;
	toggle = !toggle;
	digitalWrite(11, toggle ? HIGH : LOW);
}
				
			

Esempio per Timer-1 1Hz

				
					void setup(void) {
	pinMode(11, OUTPUT);
	
	cli();
	TCCR1A = 0;
	TCCR1B = 0;
	TCNT1 = 0;
	OCR1A = 15624;
	TCCR1B |= (1<<WGM12);
	TCCR1B |= (1<>CS10);
	TIMSK1 |= (1<<OCIE1A);
	sei();
}
void loop(void) {
	// fa qualcosa senza delay()
}
ISR(TIMER1_COMPA_vect) {
	booleano statico toggle = true;
	toggle = !toggle;
	digitalWrite(11, toggle ? HIGH : LOW);
}
				
			

Esempio per il timer-2 8KHz

				
					void setup(void) {
	pinMode(11, OUTPUT);
	
	cli();
	TCCR2A = 0;
	TCCR2B = 0;
	TCNT2 = 0;
	OCR2A = 249;
	TCCR2A |= (1<<WGM21);
	TCCR2B |= (1<<CS21);
	TIMSK2 |= (1<<OCIE2A);
	sei();
}
void loop(void) {
	// fa qualcosa senza delay()
}
ISR(TIMER1_COMPA_vect) {
	booleano statico toggle = true;
	toggle = !toggle;
	digitalWrite(11, toggle ? HIGH : LOW);
}
				
			

Fine

Dai tre esempi di programmi Timer, si può notare che quando l'interrupt del Timer è attivato, non è consigliabile usare la funzione delay() perché può interferire con tutte le attività del Timer sul microcontrollore, soprattutto se il valore della funzione delay() supera il valore del prescaler sull'interrupt del Timer, e se il vostro programma obbliga a usare la funzione delay(), Se invece il valore della funzione delay() non supera il valore del prescaler, allora può essere un po' tollerato, ma non è nemmeno una buona scelta; se non capite la funzione millis() o la funzione macros(), possiamo parlarne un'altra volta.

Una piccola aggiunta che forse ho dimenticato di spiegare è la funzione cli() e la funzione sei().

La funzione cli() viene utilizzata per disabilitare gli interrupt del timer.

La funzione sei() viene utilizzata per attivare l'interrupt del timer.

Forse è tutto ciò che possiamo condividere con voi, grazie.

Saluti.

Blog correlati

Saremo lieti di ascoltarvi