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;
}
}