Odkazy:
V procesorech Atmel jenž jsou srdcem Arduina máme řadu dedikovaných hardawrových bloků které plní specializované úlohy. Jsou to například sériový komunikační modul (USART), modul I2C sběrnice, modul SPI, čítače/časovače. Všechny tyto bloky mohou vyvolávat různá přeřušení. Nejen tyto bloky, ale přerušení může být vyvoláno i změnami digitálních vstupů. Celý systém přerušení existuje proto, aby jednotlové části hardware mohli "přitáhnout pozornost" procesoru a býti přednostně a rychle obslouženy. Například hlavní program provádí dlouhý výpočet, a jednotka časovače vyvolá přerušení. Procesor zanechá vykonávání hlavního výpočtu a provede kód obsluhy přerušení časovače. Poté se procesor vrátí k hlavnímu výpočtu a pokračuje v práci kde byl přerušen.
V kódu zapisujeme proceduru/funkci obsluhy přerušení podle následující předlohy. Jako parametr makra ISR uvedeme název vektoru přerušení, který chceme obsloužit.
ISR(přerušovací_vektor
) {
kód obsluhy přerušení
}
Jeden vektor přerušení může ukazovat jen na jednu funkci/proceduru obsluhy přerušení.
#include <avr/interrupt.h> byte v, dv; ISR(TIMER2_OVF_vect) { TCNT2 = dv; PORTD = v; }
V MCU ATmega328 a ATmega168 jsou tři čítače/časovače. Jeji propojení s piny a možnosti jsou následující:
Systémový časovač, PWM na pinech d5 a d6
Tento čítač/časovač se používá k sledování času. Používá jej například funkce millis. Rovněž je tento čítač/časovač použit ke generování PWM signálu na pinech d5 a d6.
Generuje PWM na pinech d9 a d10
Generuje PWM na pinech d3 a d11
Ačkoli jsou užity všechny čítače/časovače, jen Timer0 má k přerušení přiřazenu přerušovací rutinu.
Použití čítače/časovače Timer2
#define TIMER_CLOCK_FREQ 2000000.0 // 16MHZ / 8 unsigned char SetupTimer2(float timeoutFrequency) { unsigned char result; result = (int)((257.0-(TIMER_CLOCK_FREQ/timeoutFrequency))+0.5); TCCR2A = 0; TCCR2B = 0<<CS22 | 1 <<CS21 | 0<<CS20; TIMSK2 = 1<<TOIE2; // Timer2 Overflow Interrupt Enable TCNT2 = result; // load the timer fot its first cycle return(result); }
Zápis procedury volané přerušením od časovače.
#define TOGGLE_IO 9 ISR(TIMER2_OVF_vect) { digitalWrite(TOGGLE_IO, !digitalRead(TOGGLE_IO)); latency = TCNT2; TCNT2 = latency + timerLoadValue; }
Ukázka kódu z gonium.net
http://gonium.net/md/2006/12/23/arduino-timer-interrupt/
#include <avr/interrupt.h> #include <avr/io.h> #define INIT_TIMER_COUNT 6 #define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT int ledPin = 13; int int_counter = 0; volatile int second = 0; int oldSecond = 0; long starttime = 0; // Aruino runs at 16 Mhz, so we have 1000 Overflows per second... // 1/ ((16000000 / 64) / 256) = 1 / 1000 ISR(TIMER2_OVF_vect) { RESET_TIMER2; int_counter += 1; if (int_counter == 1000) { second+=1; int_counter = 0; } }; void setup() { Serial.begin(9600); Serial.println("Initializing timerinterrupt"); //Timer2 Settings: Timer Prescaler /64, TCCR2A |= (1<<CSS22); TCCR2A &= ~((1<<CS21) | (1<<CS20)); // USe normal mode TCCR2A &= ~((1<<WGM21) | (1<<WGM20)); // Use internal clock - external clock not used in Arduino ASSR |= (0 << AS2); //Timer2 Overflow Interrupt Enable TIMSK2 |= (1<<TOIE2) | (0 << OCIE2A); sei(); //Timer2 Overflow Interrupr Enable TIMSK2 = Serial.print(millis() - starttime); Serial.println("."); digitalWrite(ledPin, HIGH); delay(100); digitalWrite(ledPin, LOW); oldSecond = second; } }