Нормальный режим

В нормальном режиме таймер на каждом такте увеличивает на единицу значение регистра TCNTn от 0 до переполнения, то есть до значения 256 для 8-битных таймеров или до 65536 для 16-битного.

При переполнении биты регистра TCNTn принимают значение 0, а также устанавливается флаг переполнения TOVn. То есть флаг TOVn в данном случае работает как 9-й или 17-й бит, но он может быть программно только установлен в единицу, но не обнулён. Если для таймера разрешено прерывание по переполнению, то микроконтроллер вызывает соответствующую функцию обработчик вектора TIMERn_OVF_vect.

В нормальном режиме нет ограничений на изменение значения регистра TCNTn, его можно изменять программно в любом месте программы.

Пример использования нормального режима

В данном примере я буду использовать таймер-счётчик 2 для того, чтобы мигать встроенным светодиодом.

Частоту мигания светодиода будет задавать значение потенциометра, подключенного к входу Analog 0.

Когда на входе Analog 0 будет низкий логический уровень, частота мигания будет равна 10 Герцам. При высоком логическом уровне - 1 Гц.

Для работы с таймером в скетче используется библиотека VEduino.

Код скетча (скачать код скетча):


#include <ve_avr.h> // Используется библиотека VEduino


volatile bool bOverflow = false; // Флаг прерывания (объявлен volatile, потому что изменяется в обработчике прерывания)

int counter = 0; // Счётчик прерываний

int frequency = 98; // Частота мигания светодиода (976 = 1Гц, 98 = 10 Гц)


void setup()

{

pinMode(LED_BUILTIN, OUTPUT); // Пин светодиода в режим вывода

DEV_TIMER2.setClockSelect(Prescaler2::Prescaler_64); // 16МГц / 64 = 250 кГц. Таймер-счётчик 2 будет

// увеличивать значение регистра TCNT2 на единицу

// каждые 4 микросекунды.

DEV_TIMER2.setWaveGenMode(Timer2::Normal); // Нормальный режим таймера-счётчика

DEV_TICTRL2.setOverflowIntEnable(true); // Разрешить прерывание по переполнению

interrupts(); // Разрешить прерывания

}


ISR(TIMER2_OVF_vect) // Обработчик прерывания TIMER2_OVF - переполнение таймера-счётчика 2

{

bOverflow = true; // Установить флаг прерывания

}


void loop()

{

while (bOverflow == false) ; // Ожидаем установки флага прерывания

bOverflow = false; // Сбрасываем флаг прерывания

++counter; // Увеличить счётчик на 1

if (counter == frequency / 2) // На половине значения частоты выключить светодиод

digitalWrite(LED_BUILTIN, LOW);

else if (counter == frequency) { // При достижении счётчиком значения частоты:

digitalWrite(LED_BUILTIN, HIGH); // Включить светодиод

counter = 0; // Обнулить счётчик прерываний

int potValue = analogRead(0); // Считать значение частоты, заданное потенциометром

frequency = map(potValue, 0, 1023, 98, 976);

}

}