Таймер 2 «Очистить OC2B при сравнении совпадений» не работает в режиме CTC
Это продолжение моего предыдущего вопроса.
У меня Timer2 находится в режиме CTC, при этом TOP=OCR2A установлен на 150 (с предварительным делителем 8, что дает временной интервал 75 мкс).
В техническом описании указано, что установка COM2B1 в 1 в TCCR2A «очистит OC2B при сравнении» (= вывод D3 Arduino), когда вы находитесь в режиме CTC.
Я хотел бы использовать эту функциональность для получения сигнала "ШИМ" с периодом 75 мкс, с рабочим циклом, определяемым OCR2B. Я понимаю, что это очень запутанный способ достижения этого, но в конечном итоге я хочу постоянно изменять OCR2B, чтобы получить (быстро) изменяющийся рабочий цикл.
В прерывании канала сравнения A я хотел бы перевести D3 в высокий уровень, полагаясь на функцию «очистки при совпадении сравнения» канала B, чтобы перевести его в низкий уровень через небольшой промежуток времени.
У меня есть следующий минимальный пример:
#define OCIEA 1
#define CA21 1
void setup() {
// PD3 как выход
DDRD |= (1 << PD3);
// Приостановите таймеры, чтобы они синхронизировались
GTCCR = (1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC); // Остановить все таймеры
// Сбросить таймер
TCNT2 = 0; // устанавливаем timer2 на 0 (8-битный таймер)
// Включить режим CTC
TCCR2A = (1 << WGM21); // Таймер 2 в CTC (TOP = OCR2A)
// Очистить выходные контакты при сравнении совпадений
TCCR2A |= (1 << COM2B1); // Очистить OC2B при совпадении
// Установить предделитель
TCCR2B = (1 << CA21); // устанавливаем делитель таймера 2 на 8
// Установить сравнение выходных данных
OCR2A = 150; // Определяет TOP для Timer2
// Определяет ширину импульса
OCR2B = 75; // Таймер 2 выход B (управляет OC2B = PD3 = D3)
// Включить прерывания для таймера 2
TIMSK2 = (1 << OCIEA);
// Снова устанавливаем таймеры
GTCCR = 0; // освободить все таймеры
}
ISR(TIMER2_COMPA_vect)
{
TCCR2A &= ~((1 << COM2B1) | (1 << COM2B0)); // Отключить очистку OC2B при совпадении
DDRD |= (1 << PD3); // Включить вывод
PORTD |= (1 << PD3); // Выход высокий
TCCR2A |= (1 << COM2B1); // Включить очистку OC2B при совпадении
}
void loop() {
}
В идеале ISR должен состоять только из PORTD |= (1 << PD3);
, но это не дает желаемого мной 50% рабочего цикла, но, по-видимому, невозможно записывать на вывод при включенном COM2B1, поэтому я пробовал различные комбинации его отключения и повторного подключения вывода, но все, что я получаю, это очень, очень короткий импульс. Похоже, как только COM2B1 снова включается, вывод переходит на низкий уровень, хотя сопоставление сравнения на канале B еще не должно было произойти.
Установка COM2B0 вместо COM2B1 работает так, как и ожидалось: вывод переключает состояние (но это не то, что мне нужно).
Почему это не работает так, как я ожидаю, и есть ли способ получить желаемое поведение? Кроме того, если это невозможно, в чем, черт возьми, смысл функции очистки при сравнении совпадений, если вы вообще не можете включить пин при ее использовании?
Я обнаружил, что могу получить желаемое поведение, установив COM2B0 вместо COM2B1 (переключать при совпадении, а не очищать при совпадении) и принудительно выполнить сравнение в прерывании (выключая вывод), чтобы позже «реальное» переключение при совпадении выключило его. Однако это не идеально (так как если реальное и принудительное совпадение перекрываются, я теряю отслеживание состояния вывода), и мне все еще интересно, в чем смысл функции очистки при совпадении, если она просто принудительно устанавливает вывод на низкий уровень.
1 ответ
Arduino предварительно настраивается как
TCCR2A = (1 << WGM20);
TCCR2B = (1 << WGM22);
таким образом Первоначально сбросить регистр
TCCR2A=0;//сброс регистра
TCCR2B=0;//сброс регистра
- Генерация стабильной частоты
- Изменчивая переменная не обновляется с таймера ISR
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Точность синхронизации Arduino nano
- Настройка таймера ATMega328p (Arduino)
- Интервальный таймер на Arduino: Сомнения по поводу библиотеки TimerOne
- Что означает «Обновление OCR1x в» в таблице WGM ATMEGA328?
- максимальная частота ШИМ на основе прерываний при 500 Гц