Entdecken Sie unser breites Sortiment an Arduinos sowie Zubehör!
Als Arduino-Programmierer haben Sie wahrscheinlich Timer und Interrupts verwendet, ohne auch nur zu wissen, dass es da ist, weil all die Hardware-Komponenten der unteren Ebene von der Arduino-API verborgen sind. Viele Arduino-Funktionen verwenden Timer, zum Beispiel die Zeitfunktionen: delay (), millis () und micros (), die PWM-Funktionen analogWrite (), tone () und noTone (), sogar die Servo-Bibliothek verwendet Timer und Interrupts .
Was ist ein Timer?
Ein Timer oder Zähler ist ein Stück Hardware auf dem Arduino-Controller. Es ist wie eine Uhr und kann verwendet werden, um Zeitereignisse zu messen.
Der Timer kann durch einige spezielle Register programmiert werden. Sie können den Pre-Scaler für den Timer oder die Betriebsart und viele andere Dinge konfigurieren.
Viele Arduino Board basieren beispielsweise auf einem Atmel AVR ATmega168 oder einem m ATmega328 Microchip. Diese Chips sind pinkompatibel und unterscheiden sich nur in der Größe des internen Speichers. Beide haben 3 Timer (Timer0, Timer1 und Timer2). Timer0 und Timer2 sind 8-Bit-Timer, wobei Timer1 ein 16-Bit-Timer ist.
Der wichtigste Unterschied zwischen 8-Bit- und 16-Bit-Timer ist die Timer-Auflösung. 8 Bits bedeutet 256 Werte (zwei zur Potenz von 8), wobei 16 Bit 65536 Werte bedeutet (zwei zur Potenz von 16), was eine viel höhere Auflösung ist.
Die Arduino Mega Serie basiert auf dem Atmel AVR ATmega1280 oder dem ATmega2560. Sie sind fast identisch mit früheren Chips, unterscheiden sich jedoch nur in der Speichergröße. Diese Chips haben 6 Timer. Die ersten 3 Timer (Timer 0, Timer1 und Timer2) sind identisch mit dem ATmega168 / 328. Timer3, Timer4 und Timer5 sind alle 16bit-Timer, ähnlich wie Timer1.
Alle Timer hängen von der Systemuhr Ihres Arduino-Systems ab. Normalerweise ist die Systemuhr 16MHz, aber der Arduino Pro 3,3V ist 8Mhz, also seien Sie vorsichtig beim Schreiben Ihrer eigenen Timer-Funktionen.
Die Timer-Hardware kann mit einigen speziellen Timer-Registern konfiguriert werden. In der Arduino-Firmware wurden alle Timer auf eine 1-kHz-Frequenz konfiguriert, und Interrupts werden im Allgemeinen aktiviert.
Timer Register
Sie können das Timer-Verhalten über das Timer-Register ändern. Die wichtigsten Timer-Register sind:
- TCCRx - Timer / Zählersteuerregister. Der Prescaler kann hier konfiguriert werden.
- TCNTx - Timer / Zählerregister. Der aktuelle Timer-Wert wird hier gespeichert.
- OCRx - Ausgabevergleichsregister
- ICRx - Input Capture Register (nur für 16bit-Timer)
- TIMSKx - Timer / Zählerunterbrechungsmaskenregister. Zum Aktivieren / Deaktivieren von Timer-Interrupts.
- TIFRx - Timer / Zählerunterbrechungsmerkerregister. Zeigt einen ausstehenden Timer-Interrupt an.
Timer mit einem Arduino Uno verwenden
Ein Timer wird verwendet, weil Sie während der Funktion delay () nichts machen können. Aber mit einem Timer können Sie alles machen, denn wenn der Moment kommt, aktiviert er den Interrupt.
In diesem Beispiel wird der TIMER0 verwendet, da er der am einfachsten zu konfigurierende Timer ist. Als erstes betrachten wir hierfür das Datenblatt des ATmega328P.
Der Vorskalierer empfängt einen Impuls von einem Taktzyklus und leitet ihn dann an die Steuerlogik weiter, daher inkrementiert die Steuerlogik das TCNTn-Register um 1.
Jetzt können wir den Wert von TCNTn mit einem bestimmten Wert vergleichen. Wenn das TCNTn-Register diesen Wert erreicht, wissen Sie, dass eine bestimmte Zeit verstrichen ist.
Diese Methode wird CTC-Modus für "Clear Timer on Compare" genannt. Der Wert TCNTn-Register wird mit dem OCRn-Register verglichen, wenn eine Vergleichsübereinstimmung auftritt, erzeugt der TOVn einen Interrupt.
Eine weitere wichtige Sache ist der Prescaler, mit dem Sie verschiedene Bereiche der Uhr erstellen können, in der Tat 16MHz ist zu viel, aber dank des Prescaler können Sie einige Submultiples davon erstellen. Dies hängt von der Konfiguration des TCCR0B-Registers ab.
Eine weitere wichtige Sache ist, den Wert des OCRn-Registers zu bestimmen, um eine bestimmte Zeit zu zählen, dazu brauchen Sie ein bisschen Mathematik.
Zum besseren Verständnis sollten Sie sich den unten aufgeführten Code ansehen. Dort wird eine Interrupt-Anfrage alle 0,001 Sekunden aktiviert.
Arduino Internal Timer Code
/*
This program turns on and off a LED on pin 13 each 1 second using an internal timer
*/
int timer=0;
bool state=0;
void setup() {
pinMode(13,OUTPUT);
TCCR0A=(1<<WGM01); //Set the CTC mode
OCR0A=0xF9; //Value for ORC0A for 1ms
TIMSK0|=(1<<OCIE0A); //Set the interrupt request
sei(); //Enable interrupt
TCCR0B|=(1<<CS01); //Set the prescale 1/64 clock
TCCR0B|=(1<<CS00);
}
void loop() {
//in this way you can count 1 second because the nterrupt request is each 1ms
if(timer>=1000){
state=!state;
timer=0;
}
digitalWrite(13,state);
}
ISR(TIMER0_COMPA_vect){ //This is the interrupt request
timer++;
}
Fritzing Schematics