Режим очистки при совпадении (CTC)

В этом режиме таймер на каждом такте увеличивает на единицу значение регистра TCNTn от 0 до верхней границы, задаваемой регистром OCRnx, и при совпадении значение регистра TCNTn обнуляется. При этом устанавливается флаг прерывания OCFnx, а также переключается логический уровень на выводе OCnx.

Временная диаграмма работы таймера-счётчика в режиме CTC:

Если разрешено прерывание по совпадению TIMERn_COMPx_vect, то вызывается функция-обработчик, в которой можно изменить верхнюю границу, присвоив новое значение регистру OCRnx. Но поскольку в регистрах таймеров-счётчиков не используется двойная буферизация, то при высокой тактовой частоте таймера запись в регистр OCRnx значения, близкого к 0 из функции-обработчика прерывания может привести к тому, что флаг прерывания будет таймер установлен ещё до того, как функция-обработчик завершится, и таким образом один или несколько периодов таймера окажутся пропущенными.

Например, я захотел сгенерировать синусоиду. И вот, как будет выглядеть осцилограмма моего генератора:

В режиме CTC вывод OCnx может автоматически переключать своё состояние при каждом совпадении. Если в регистр OCRnx записать значение 0, то он будет переключаться с максимальной частотой, равной половине тактовой частоты таймера.

Для расчёта частоты импульсов, которую можно получить на выводе OCnx, можно использовать формулу

Focnx = Fclk/(2*N*(1+OCRnx),

где Fclk равен тактовой частоте таймера, а N равен коэффициенту предделителя (например, 8, 32, 64, ...).

Флаг переполнения TOVn в режиме CTC устанавливается так же, как и в нормальном режиме.

Пример использования таймера-счётчика в режиме CTC

В данном примере я с помощью потенциометра, подключенного ко входу Analog 0, буду управлять импульсами на выводе OC2A (пин Digital 11 на плате Arduino UNO).

Я задал тактирование таймера-счётчика 2 с предделителем /1024, что даёт частоты импульсов от 30.5 Гц значении OCR2A, равном 255, до 7812 Гц при значении, равном 0.

В скетче используется библиотека VEduino.

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

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


void setup()

{

setModeOutput(DEV_TIMER2_OCA); // Пин OC2A в режим вывода

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

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

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

DEV_TIMER2.setWaveGenMode(Timer2::CTC); // Режим CTC таймера-счётчика

DEV_TIMER2.setCompOutModeA(Timer2::Toggle); // Переключать вывод OC2A при TCNT2 == OCR2A

}


void loop()

{

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

OCR2A = map(potValue, 0, 1023, 255, 0); // Задать значение регистра OCR2A

delay(100);

}