This is an old revision of the document!
Necessary knowledge: [HW] Controller module, [HW] User Interface Module, [AVR] Interrupts, [AVR] Counters/Timers, [LIB] Pins, [LIB] Delay, [LIB] Timers, [PRT] Software delay
Das Ziel dieses praktischen Beispiels ist es den Gebrauch von Interrupts an Beispiel von Countern zu zeigen. Die Interrupts sind Programmteile welche auf Events die in einem Microcontroller stattfinden reagieren. Ihr Zweck ist normalerweise eine schnelle Antwort auf ein Event, können aber auch benutzt werden um mehrere parallele Prozesse zu beenden, präzise zeitlich abgestimmte Aktion auszuführen, und zur Energieeinsparung. Zum Beispiel ist es möglich eine LED mit Interrupts blinken zu lassen, so dass die Blinkfrequenz nicht von dem abhängig ist, was gerade in einem Programm passiert.
Das folgende Programm zeigt wie Counter eingestellt werden um einen Interrupt auszulösen. Es sind 2 LEDs des Digitalen I/O Moduls in diesem Programm, der Status der roten LED wird mit einer Softwareverzögerung periodisch geändert, der Status der grünen LED wird geändert wenn ein Interrupt stattfindet. Es gibt ein separates Beispiel für blinkende LEDs mit Softwareverzögerung, und wird daher nicht hier erklärt. Das Ziel ist der Gebrauch der Library für Counter und Interrupts.
Zu Beginn des Programms wird der 16-Bit Counter/Timer 1 mit der Funktion timer1_init_ctc eingestellt. Mit dieser Funktion wird der Counter im CTC clear timer on compare match Modus gesetzt, damit ist der maximale Wert vom Benutzer einstellbar. In diesem Fall wird der maximale Wert so gesetzt dass er gleich dem Wert des ICR1 Indexes ist. Der Teiler des Counters ist 1024 und der Wert des ICR1 ist 14400, also bei einer Taktfrequenz von 14,7456MHz ist die Periode genau eine Sekunde. Es ist einfach mit folgender Formel zu rechnen:
f = 14745600 Hz / 1024 / 14400 = 1
Nachdem erlauben von Interrupts wenn der maximale Wert von Counter 1 erreicht ist, muss auch auf globelem Level, also im Microcontroller, ein Interrupts erlaubt werden. Um globale Interrupts zu erlauben gibt es die Funktion sei und zum verbieten cli. Die Headerdatei avr/interrupt.h muss für diese Funktionen und Interrupts eingefügt werden. Der Programmteil des Interrupts ist durch die Macrofunktion ISR definiert, dessen Parameter der Name des Interruptvektors ist. In diesem Set-up ist die maximalen Wert Interrupts ist TIMER1_CAPT_vect.
// // The HomeLab's example of blinking LED which blinks due to counter interruptings. // For comparison to the LED blinking due to interrupts, // there is a software delay blinking LED working parallel. // #include <homelab/pin.h> #include <homelab/delay.h> #include <homelab/timer.h> #include <avr/interrupt.h> // // Determining the pins of the LEDs. // pin led_red = PIN(C, 5); pin led_green = PIN(C, 3); // // Interruption // ISR(TIMER1_CAPT_vect) { // Changing the state of the green LED. pin_toggle(led_green); } // // Main program. // int main(void) { // Setting the pins of the LEDs as outputs. pin_setup_output(led_red); pin_setup_output(led_green); // Seting the timer up in the CTC mode. timer1_init_ctc( TIMER1_PRESCALE_1024, TIMER1_CTC_TOP_ICR); // The maximal value of the timer is 14400, which // makes the length of the period 1 s. // Formula: 14,7456Mhz / 1024 = 14400 timer1_set_input_capture_value(14400); // Allowing interruption of achieving the value. timer1_input_capture_interrupt_enable(true); // Allowing global interruption. sei(); // Endless loop. while (true) { // Software delay 1000 ms. sw_delay_ms(1000); // Change of the state of the red LED. pin_toggle(led_red); } }
Zu Beginn des Programms sieht man, dass egal was der Mircocontroller grade im Hauptprogramm macht, Interrupts stattfinden und die grüne LED blinkt.
Wenn wir das Programm ein paar Minuten arbeiten lassen, wird ein wichtiger Aspekt sichtbar, dass man nicht so schnell bei dem der Softwareverzögerung gemerkt haben. Auch wenn die Verzögerung der blinkenden LED 1000ms ist, brauch der komplette Zyklus etwas länger. Das Ändern des LED Status, der Callout der Verzögerungsfunktion und das Beenden des Zyklus benötigt ein paar Arbeitstakte des Prozessors und damit auch Zeit. Daher scheint es, als läuft die rote LED der grünen hinterher. Darum sollte man wenn man Uhren oder andere präzise Aktionen nicht mit Verzögerungen sondern mit Countern ausführen.