Режим быстрого ШИМ
В этом режиме таймер-счётчик на каждом такте увеличивает на единицу значение регистра TCNTn от 0 до верхней границы регистра (255 для 8-битных таймеров или 65535 для 16-битного). При переполнении, как и в нормальном режиме, устанавливается флаг переполнения TOVn, а также обновляется значение совпадения из регистра OCRnx (двойная буферизация).
Вывод OCnx в этом режиме может работать как нормальном режиме, так и в инверсном. В нормальном режиме он устанавливается в высокий уровень при TCNTn равном 0, и в низкий уровень при совпадении значений регистров TCNTn и OCRnx. В инверсном режиме - наоборот.
Временная диаграмма работы таймера-счётчика в режиме быстрого ШИМ:
Высокая частота ШИМ этого режима позволяет успешно применять его в задачах регулировки мощности, выпрямления тока, цифро-аналоговом преобразовании.
Для расчёта Частоты ШИМ можно применить формулу
Fpwm = Fclk / (N*256),
где Fclk равен тактовой частоте таймера-счётчика, а N равен коэффициенту предделителя (например, 1, 8, 32, 64, ...).
Если записать в регистр OCRnx значение половины верхней границы (127 для 8-битных счётчиков или 32767 для 16-битного), то логический уровень на выводе OCnx будет переключаться с половиной тактовой частоты таймера, так же, как и режиме CTC, но при этом можно использовать двойную буферизацию регистра OCRnx.
Значения, близкие к верхней и нижней границам TCNTn - это особый случай. Если записать в регистр OCRnx ноль, то напряжение на выводе OCnx в нормальном режиме будет изменяться краткими импульсами каждые 256 или 65536 тактов. А если записать 255 или 65535, то оно постоянно равно логической единице в нормальном режиме или нулю - в инверсном.
Пример использования таймера-счётчика в режиме быстрого ШИМ
В данном примере я с помощью потенциометра, подключенного ко входу Analog 0, буду управлять шириной импульсов на выводе OC2A.
Если соединить резистором 10К вывод Digital 11 (OC2A) платы Arduino UNO с выводом Digital 13, то можно будет управлять яркостью свечения встроенного светодиода.
В скетче используется библиотека VEduino.
Код скетча (скачать):
#include <ve_avr.h> // Используется библиотека VEduino
void setup()
{
setModeOutput(DEV_TIMER2_OCA); // Пин OC2A в режим вывода
DEV_TIMER2.setClockSelect(Prescaler2::Prescaler_8); // 16МГц / 8 = 2 МГц. Таймер-счётчик 2 будет
// увеличивать значение регистра TCNT2 на единицу
// каждые 100 наносекунд.
DEV_TIMER2.setWaveGenMode(Timer2::FastPWM); // Режим быстрого ШИМ таймера-счётчика
DEV_TIMER2.setCompOutModeA(Timer2::Clear); // Сбрасывать вывод OC2A при TCNT2 == OCR2A
}
void loop()
{
int potValue = analogRead(0); // Считать значение ширины импульса, заданное потенциометром
OCR2A = map(potValue, 0, 1023, 0, 255); // Задать значение регистра OCR2A
delay(100);
}
Пример использования таймера-счётчика в режиме быстрого ШИМ с вершиной в OCRnA
В данном примере я с помощью потенциометра, подключенного ко входу Ananlog 0, буду управлять частотой импульсов на выходе OC2A (пин 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::FastPWM_OCRA); // Режим быстрого ШИМ с вершиной OCR2A таймера-счётчика
DEV_TIMER2.setCompOutModeA(Timer2::Toggle); // Переключать вывод OC2A при TCNT2 == OCR2A
}
void loop()
{
int potValue = analogRead(0); // Считать значение частоты, заданное потенциометром
OCR2A = map(potValue, 0, 1023, 255, 0); // Задать значение регистра OCR2A
delay(100);
}