40.8.2.3. Přerušení

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

Varování

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í:

Timer0

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.

Timer1

Generuje PWM na pinech d9 a d10

Timer2

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;
}
}
Licence Creative Commons
Elektronika a počítače, jejímž autorem je Radek Hnilica, podléhá licenci Creative Commons Uveďte autora-Nevyužívejte dílo komerčně-Zachovejte licenci 3.0 Česká republika .