Arduino Mega — включение режима CTC отключает таймер

Я пытаюсь использовать timer3 на Arduino Mega 2560 в режиме CTC. Однако включение CTC полностью отключает код.

Вот функция, которую я вызываю в setup() для установки времени.

void SetupInterrerupt() {
  cli(); // Запретить прерывания

  // Настройка таймера
  TCCR3A = 0;     // устанавливаем весь регистр TCCR3A в 0
  TCCR3B = 0;     // то же самое для TCCR3B

  // Настройка регистра сравнения совпадений
  OCR3B =  CMP_FAST; // CMP_FAST = 40

  // включаем режим CTC:
  TCCR3B |= (1 << WGM32); // Закомментировав эту строку, код заработает
  // Устанавливаем биты CS10 и CS12 для прескалера 1024:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // включаем прерывание сравнения таймера:
  TIMSK3 |= (1 << OCIE3B);

  sei(); // Разрешаем прерывания

  Serial.println("Timers enabled");
}

И вектор прерывания.

// Прерывание таймера 3
ISR(TIMER3_COMPB_vect){//timer1 прерывание 1 Гц переключает контакт 13 (светодиод)
  // делаем что-то...
}

Как есть, прерывание вообще не выполняется. Как отмечено в коде, закомментирование «TCCR3B |= (1 << WGM32);» фактически выполняет прерывание, за исключением того, что частота больше похожа на 1 Гц вместо 720.

Я использую библиотеку Arduino-lmic, а также некоторые другие библиотеки структур данных. Я не думаю, что они используют какие-либо таймеры, но, поскольку lmic разработан для Uno, я решил, что использование таймеров 3 и выше будет вполне приемлемым.

К сожалению, мои таймеры немного подзабыли. Кто-нибудь сможет заметить мою ошибку?

Спасибо.

, 👍0


1 ответ


1

Я думаю, ваша проблема в том, что вы используете неправильный регистр значения счетчика «TOP».

OCR3B =  CMP_FAST; // CMP_FAST = 40

должно быть:

OCR3A =  CMP_FAST; // CMP_FAST = 40

Я не слишком знаком с работой AVR времен, но согласно таблице данных:

В режиме сброса таймера при сравнении или CTC (WGM22:0 = 2) регистр OCR2A используется для управления разрешением счетчика. В режиме CTC счетчик обнуляется, когда значение счетчика (TCNT2) соответствует OCR2A. OCR2A определяет верхнее значение счетчика, а значит, и его разрешение.

(Примечание: здесь упоминается только регистр таймера 2, но то же самое справедливо для всех таймеров одного класса, включая таймер 3).

Поскольку OCR3A равен нулю, совпадение никогда не происходит. А поскольку существует только один счетчик (TCNT3), который при совпадении сбрасывается в 0, для сравнения может быть только один регистр, и это регистр «А». Регистр «B» кажется избыточным в режиме CTC.

Возможно, вам также придется переключиться на вектор COMPA (я не уверен в этом, честно говоря)

,

Спасибо за ответ! К сожалению, это, похоже, не сработало. Переключение с OCR3B на OCR3A не меняет поведение. Переключение на вектор COMPA приводит к постоянной перезагрузке Arduino (я подозреваю, что всякий раз, когда происходит прерывание). Включение TCCR3B |= (1 << WGM32); просто снова отключает таймер. Думаю, я также пробовал использовать таймеры 0-2, но безрезультатно., @Jordan Sim

Возможно, вам следует вместо этого переключиться на использование библиотеки, чтобы управлять ею за вас. Я уверен, что есть некоторые варианты библиотеки TimerOne для Таймера 3., @Majenko

Помимо изменения OCR3B на OCR3A, вам также необходимо изменить OCIE3B на OCIE3A и TIMER3_COMPB_vect на TIMER3_COMPA_vect., @Gerben