Настраиваем прерывания по таймерам в плате Arduino Nano.

В данном уроке мы настроем прерывание от внутреннего таймера без использования arduino библиотек, но в среде программирования Arduino IDE.

Использовать мы будем плату Arduino Nano, данная плата плата на борту содержит микроконтроллер Atmega 328 , у которой в наличии три таймера: Timer0, Timer1 и Timer2.

Timer0 —  8 битный таймер, с максимальным числом счета до 255. Данный таймер используется стандартными временными функциями Arduino такими как delay() и millis(), поэтому при использовании arduino библиотек нужно быть с ним аккуратным.

Timer1 — 16  битный таймер, с максимальным числом счета 65535.  Данный  таймер использует библиотека Arduino Servo.

Timer2 — 8 битный таймер, с максимальным числом счета до 255. Он используется в Arduino функции tone().

Для настройки таймеров нам понадобятся следующие регистры:

TCCRxA и TCCRxB, где x — номер таймера

Регистр TCCR1A :

Регистр TCCR1В :

Рассмотрим настройки необходимых для нас бит:

Так как наш микроконтроллер работает на частоте 16 МГц, а мы хотим управлять светодиодом, для увеличения времени счета нашего таймера, мы поделим его тактовую частоту на 1024:

TCCR1B |= (1 << CS10); 
TCCR1B |= (1 << CS12);

Таким образом мы получаем скорость счета (тактирования) 15625 Гц или 64,0е-6 секунды. Нам нужно, что бы счетчик менял свое состояние раз в 0,5 секунду, разделив 0,5/64,0е-6 мы получаем 7812,5. Таким образом в регистр OCR1A нам необходимо записать 7813. Но с учетом того, что сброс счетчика в ноль занимает один такт, нам необходимо записать в регистр OCR1A  — 7812.

Для проверки работы прерывания, мы будем моргать светодиодом, который расположен на макетной плате.
Программа реализации прерывания по счетчику:
#include <avr/io.h> 
#include <avr/interrupt.h> 
#define LED 13
void setup() { // инициализация Timer1 
cli(); // отключить глобальные прерывания 
TCCR1A = 0; // установить регистры в 0 
TCCR1B = 0; 
OCR1A = 7812; // установка регистра совпадения
TCCR1B |= (1 << WGM12); // включить CTC режим 
TCCR1B |= (1 << CS10); // Установить биты на коэффициент деления 1024 
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << OCIE1A); // включить прерывание по совпадению таймера
sei(); // включить глобальные прерывания 
pinMode(LED, OUTPUT);
}

ISR(TIMER1_COMPA_vect){ 
digitalWrite(LED, !digitalRead(LED)); 
} 
void loop() {}