Большинство микроконтроллеров AVR имеют три выделенных вывода для каждого таймера (например, OC1A, OC1B и OC1C), которые могут переключаться автоматически, когда счетчик достигает так называемого верхнего значения в соответствующих трех регистрах (OCR1A, OCR1B и OCR1C).
Я не уверен, как эти три выделенных вывода/регистра могут работать в режиме CTC для разных независимых верхних значений, и это то, чего я хочу добиться. Я хочу переключать OC1A, OC1B и OC1C (хотя и «сравнение вывода», а не через прерывание или что-то в этом роде) с разными интервалами (чтобы увидеть наличие трех выделенных регистров и контактов).
Допустим, я хочу запрограммировать таймер AVR для переключения контактов OC1A, OC1B и OC1C с разными интервалами (например, 1 секунда, полсекунды, четверть секунды), но это не работает, как я ожидаю. Я установил сравнение регистров соответствия A, B и C с тремя разными значениями, имеющими наибольшее значение для A (я также пробовал использовать его для C).
Только OC1A переключается на нужной частоте.
Мне кажется, что если бы только OC1A очищал счетчик сверху, тогда можно было бы заставить три вывода работать с тремя разными независимыми значениями. Это правильно?
Вот сегмент, который я поместил в свою установку Arduino Lenoardo (на основе ATmega32U4 ). Я оставил loop()
пустым.
// Initialize timer1
noInterrupts(); // Disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCCR1C = 0;
TCNT1 = 0;
OCR1A = 62500; // Compare match register 16 MHz/256/1 Hz
OCR1B = 31250; // Compare match register 16 MHz/256/2 Hz
OCR1C = 15625; // compare match register 16 MHz/256/4 Hz
// Toggle OC1A, OC1B and OC1C => (on Lenoardo) PB5, PB6 and PB7 => digital 9, 10, 11
// TCCR1A = 0b01010100;
TCCR1A |= (1 << COM1C0) | (1 << COM1B0) | (1 << COM1A0);
// TCCR1B = 0b1100
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
interrupts(); // Enable all interrupts
Таймер в нормальном, быстром ШИМ или режиме CTC считает напрямую от НИЗА к ВЕРХУ, если не применяется внешнее воздействие. Когда он передает каждое значение OC, он выдает прерывание и/или прерывает вывод, как он настроен. Каждое значение OC пересекается только один раз , что означает, что все OC для одного и того же таймера работают с одной и той же частотой .
Они могут быть сконфигурированы так, чтобы иметь разные фазы или работать в дифференциальных парах на основе значений битов OCRnr и COMnrb, но единственный способ напрямую заставить их использовать разные частоты — это манипулировать их значениями OCR каждый раз, когда вызывается их ISR.
Самый простой способ изменить контакты с разной частотой — установить таймер на GCF/LCM различных желаемых периодов/частот, вести подсчет прошедших циклов, а затем удалять выводы, когда прошло соответствующее количество циклов. .
Модуль таймера позволяет генерировать несколько выходов с разными рабочими циклами, но все они будут иметь одинаковую основную частоту. Если вы хотите генерировать разные частоты, вам нужно будет использовать другой метод. Есть два основных способа сделать это. Первый метод заключается в использовании трех таймеров, каждый из которых работает на разной частоте. Если вы пытаетесь генерировать относительно низкочастотные выходы (1 кГц или меньше), вы можете использовать разумный такт таймера и процедуру прерывания. Если вы хотите генерировать 1 Гц, 2 Гц и 4 Гц, вы можете установить такт таймера не менее 8 Гц, а затем подсчитывать тики и включать и выключать контакты в нужное время. С тактом таймера 8 Гц для генерации выходного сигнала с частотой 4 Гц потребуется переключать контакт в каждом цикле, 2 Гц — каждый второй цикл, а 1 Гц — каждые 4 цикла.
Игнасио Васкес-Абрамс
Джиппи
Муайяд Альсади
Игнасио Васкес-Абрамс
Муайяд Альсади
Игнасио Васкес-Абрамс
Муайяд Альсади