Как восстановить правильную работу функции analogWrite() после применение библиотеки TimerOne?

После применения библиотеки TimerOne функция analogWrite() прекратит правильно работать:

#include <TimerOne.h>
#define OUTPUT_PIN 9

void setup() {
  pinMode(OUTPUT_PIN, OUTPUT);

  analogWrite(OUTPUT_PIN, 127);  // Все в порядке, на выводе ШИМ сигнал с частотой 
  delay(5000);                   // 490 Гц, 50% заполнения импульса

  Timer1.initialize();           // Используем библиотеку TimerOne
  analogWrite(OUTPUT_PIN, 127);  // Не работает, на выводе О вольт
}

void loop() {}

Не помогают ни функции Timer1.stop(), Timer1.disablePwm().


Ответы (1 шт):

Автор решения: MarianD

Функции библиотеки TimerOne используют прямо таймер Timer/Counter1 микропроцессора ATMega328P, тем самым меняя его поведение.

Надо восстановить эти параметры таймера:

  • маску перерывов, т.е. не разрешить перерывы,
  • режим его работы, т.е. ШИМ, фазово корректный, 8-битовый, чтобы заполнение сигнала было возможно опять задавать в диапазоне от 0 до 255,
  • правильное значение прескалера (делителя частоты 16 МГц микропроцессора), т.е. 64 - тогда мы получим частоту 16 МГц / 64 = 250 kГц.
TIMSK1 = 0;         // Timer/Counter Interrupt Mask Register (перерывы не разрешены)

TCCR1A = 0;         // Регистр Timer/Counter control register A сначала обнулим,
TCCR1A = 1 << WGM10;// затем восстановим режим работы на ШИМ, фазово корректный, 8-битовый


TCCR1B = 0;         // Регистр Timer/Counter control register A сначала тоже обнулим
TCCR1B = 1 << CS11 | 
         1 << CS10; // и значение прескалера восстановим на 64

Примечания:

  1. Имена битов не представляют их значение (т.е. битовие значения 0, 10, 100, 1000 и т.д.), а только их позиции (т. е. 0, 1, 2, 3, и т.д.), потому такие сложные конструкции как
    1 << WGM10 (сдвиг числа-цифры 1 налево на определенную позицию с автоматическим заполнение нулями справа).

  2. Режим работы определяется 4 битами (WGM13, WGM12, WGM11, WGM10), но наш режим (двоично) 0001, значит, после обнуления регистров нам хватит восстановить бит WGM10.

  3. Подобно, значение прескалера определяется битами CS12, CS11 и CS10, но нам нужны только 2 из них, именно CS11 и CS10 — для таблицы

Значение  Прескалер  Частота      Биты
 001       1          16 МГц      CSS10
 010       8           2 МГц      CSS11
 011       64        250 kГц      CSS11 | CSS10
 100       256        62.5 kГц    CSS12
 101       1024       15.625 kГц  CSS12 | CSS10
  1. Из частоты 250 kГц и 256 тиками таймера в секунду мы получим 250000 / 256 изменений сигнала в секунду (приблизительно 980), т.е. оригинальную частоту 490 Гц ШИМ сигнала функции analogWrite().

  2. См. даташит ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet (PDF, по-английски).

→ Ссылка