Ich versuche, mit Arduino einen Zeitverzögerungs-Interrupt zu erstellen. Ich möchte die Funktion interrupts() verwenden, da es sich um einen internen Interrupt handelt.
Beispiel: Nehmen wir an, ich möchte ein Licht blinken lassen, nur mit dem Timing des Interrupts.
Es gibt Beispielcode, aber er verwendet externe Interrupts (attachInterrupt()). Ich möchte weiterhin die internen Interrupts verwenden.
Noah Stahls Blog enthält ein Beispiel für das Blinken einer LED mit Timer2 . Damit und mit dem Datenblatt sollten Sie in der Lage sein, es an jeden Interrupt anzupassen, den Sie verwenden möchten – dh den Interrupt, dessen normale Funktion Sie am ehesten aufgeben können oder zu ändern bereit sind. Timer2 wird normalerweise für einige PWM-Funktionen verwendet.
Sein Beispiel zitiert den ATmega2560; Ich kann bestätigen, dass es auch mit einem ATmega328p funktioniert. Sehen Sie sich auf seiner Website nach weiteren nützlichen Beispielen für Arduino-Interrupts um.
Bearbeiten:
Hier ist meine leicht bearbeitete – hauptsächlich in den Kommentaren – Version von Noahs Code. Rufen Sie Timer2init() aus der Arduino-Funktion setup() auf, nachdem Sie alle zugehörigen Datenstrukturen oder Hardware initialisiert haben, da das Timing – und das Unterbrechen – beginnt, sobald Sie dies tun.
Zum Beispiel habe ich es verwendet, um eine 3-stellige 7-Segment-Anzeige zu multiplexen, also habe ich vor der Initialisierung des Timers die Anzeige-E / A-Register initialisiert und die Anzeigedaten an der Stelle gelöscht, an der die ISR danach suchen wird.
In den Kommentaren befindet sich eine Tabelle mit einigen nützlichen Timing-Daten aus dem Datenblatt und meinen eigenen Berechnungen als Referenz, um ein anderes Timing-Schema einzurichten.
Das ISR()-Makro kümmert sich darum, einen Interrupt-Eingangs- und -Ausgangscode für einen ISR anstelle des Eingangs und Ausgangs einer normalen Funktion zu erzeugen und ihn mit dem richtigen Interrupt-Vektor zu verknüpfen. Der Rest dieser Funktion ist 1) der Code, der bei jedem Interrupt ausgeführt werden soll, und 2) der Codecode zum Zurücksetzen des Timers für den nächsten Interrupt.
Wie geschrieben, sollte dies in einer .pde- oder .ino-Skizze (oder einer .cpp-Datei, wenn Sie Eclipse, f/ex verwenden) abgelegt werden. Die Skizze muss #define LEDPIN und setup() muss Timer2init() aufrufen. Die Schleifenfunktion kann leer sein oder nicht; Die LED sollte beim Download anfangen zu blinken (na ja, buchstäblich, nachdem Timer2init() aufgerufen wurde).
/*
* From sample interrupt code published by Noah Stahl on his blog, at:
* http://arduinomega.blogspot.com/p/arduino-code.html
*
*/
/*** FUNC
Name: Timer2init
Function: Init timer 2 to interrupt periodically. Call this from
the Arduino setup() function.
Description: The pre-scaler and the timer count divide the timer-counter
clock frequency to give a timer overflow interrupt rate:
Interrupt rate = 16MHz / (prescaler * (255 - TCNT2))
TCCR2B[b2:0] Prescaler Freq [KHz], Period [usec] after prescale
0x0 (TC stopped) 0 0
0x1 1 16000. 0.0625
0x2 8 2000. 0.500
0x3 32 500. 2.000
0x4 64 250. 4.000
0x5 128 125. 8.000
0x6 256 62.5 16.000
0x7 1024 15.625 64.000
Parameters: void
Returns: void
FUNC ***/
void Timer2init() {
// Setup Timer2 overflow to fire every 8ms (125Hz)
// period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
// (1/16000000) * 1024 * (255-130) = .008 sec
TCCR2B = 0x00; // Disable Timer2 while we set it up
TCNT2 = 130; // Reset Timer Count (255-130) = execute ev 125-th T/C clock
TIFR2 = 0x00; // Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK2 = 0x01; // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
TCCR2A = 0x00; // Timer2 Control Reg A: Wave Gen Mode normal
TCCR2B = 0x07; // Timer2 Control Reg B: Timer Prescaler set to 1024
}
/*** FUNC
Name: Timer2 ISR
Function: Handles the Timer2-overflow interrupt
Description: Maintains the 7-segment display
Parameters: void
Returns: void
FUNC ***/
ISR(TIMER2_OVF_vect) {
static unsigned int led_state = 0; // LED state
led_state = !led_state; // toggles the LED state
digitalWrite(TOGGLE_PIN, led_state);
TCNT2 = 130; // reset timer ct to 130 out of 255
TIFR2 = 0x00; // timer2 int flag reg: clear timer overflow flag
};
Die Funktion attachmentInterrupt() hängt tatsächlich einen Interrupt an eine externe Zustandsänderung an einem Pin an, sie hat keine anderen Optionen.
Auf derselben Seite sind die Modusoptionen wie folgt aufgeführt:
mode definiert, wann der Interrupt ausgelöst werden soll. Als gültige Werte sind vier Konstanten vordefiniert:
- LOW , um den Interrupt auszulösen, wenn der Pin niedrig ist,
- CHANGE , um den Interrupt auszulösen, wenn der Pin seinen Wert ändert
- RISING , um auszulösen, wenn der Stift von niedrig nach hoch geht,
- FALLING , wenn der Pin von High auf Low wechselt.
Tut mir leid, der Überbringer schlechter Nachrichten zu sein, das war auch eines der ersten Dinge, nach denen ich gesucht habe.
Dieser Artikel über PWM wird viele Ihrer Zweifel bezüglich der Verwendung von Arduino-Timern ausräumen. Es gibt zwei 8-Bit-Timer und einen 16-Bit-Timer auf Arduino. Es gibt keine High-Level-API, um die ISR-Funktion direkt mit den Timern zu verknüpfen, die mit dem Arduino SDK (dh als Standardbibliothek) geliefert werden, sondern eine etwas niedrigere Methode zum Setzen von Special-Function-Registers und Bit-Arithmetik / Operationen an ihnen. Es gibt jedoch eine von Benutzern beigesteuerte Bibliothek namens Timer one .
Arduino verwendet alle drei Timer in ATMega328. Timer1
(16 Bit) wird für Funktionen wie delay()
und millis()
für die PWM-Ausgabe an den Pins 5 und 6 verwendet. Die anderen beiden Timer — Timer0
und Timer2
werden für die PWM-Ausgabe an den Pins 3, 9, 10, 11 verwendet.
Es gibt also keine Arduino-Funktion für den Timer-Interrupt. Aber es gibt einen Weg. Sie können diesen Code verwenden, um den Timer-Interrupt zu aktivieren Timer2
:
ISR(TIMER2_OVF_vect) {
// Interrupt routine.
}
void setup() {
// Enable Timer2 interrupt.
TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}
void loop() {
// Your main loop.
}
Ich habe diesen Code ohne Tests geschrieben, daher ist es möglich, dass ich einen Fehler gemacht habe. In diesem Fall siehe Datenblatt, S. 156 .
Wenn Sie die Timer-Frequenz (Prescaler) ändern möchten, ändern Sie einfach das Register TCCR2A
. Weitere Informationen finden Sie im Datenblatt auf Seite 153. Wenn Sie jedoch die Frequenz des Timers ändern, ändern Sie auch die Frequenz des PWM-Signals an zwei Ausgangspins!
Timer0
und Timer2
sind 8 Bit und nur Timer1
16 Bit.
Klatsch
Seth Archer Brown