БИБЛИОТЕКА DIRECTTIMERS
directDimers v1.0

Библиотека для расширенного (ручного) управления таймерами ATmega328/168. Библиотека низкоуровневая и непростая в использовании, изучайте примеры!
- Функции библиотеки позволяют получить доступ ко всем возможностям и режимам работы с таймерами/счётчиками + прерывания watchdog
- Ничего не урезано и не упрощено, доступен весь описанный в даташите функционал
- Разработчик – Egor ‘Nich1con’ Zaharov
Поддерживаемые платформы: платы на ATmega328/168 (Arduino Nano, UNO, Pro Mini)
ДОКУМЕНТАЦИЯ
// n - номер таймера (0, 1 или 2) void TIMERn_COMPA_attachInterrupt(void (*isr)()); void TIMERn_COMPB_attachInterrupt(void (*isr)()); void TIMERn_COMPA_detachInterrupt(void); void TIMERn_COMPB_detachInterrupt(void); void TIMERn_setClock(byte clk); void TIMERn_setMode(byte mode); void TIMERn_COMPA_mode(byte mode); void TIMERn_COMPB_mode(byte mode); byte TIMERn_getCounter(void); void TIMERn_setCounter(byte value); void TIMERn_COMPA_setValue(byte value); void TIMERn_COMPB_setValue(byte value); // прерывания watchdog void WDT_attachInterrupt(void (*isr)(),int prescaler); void WDT_detachInterrupt(void); /* константы для TIMERn_clock() */ STOPPED 0 //- тактирование будет остановлено , таймер "заморожен" EXTERNAL_FALLING 1 //-тактирование внешним клоком до 8 мгц по спаду EXTERNAL_RISING 2 //-тактирование внешним клоком до 8 мгц по фронту PRESCALER_1 3 // делитель 1 PRESCALER_8 4 // делитель 8 PRESCALER_32 5 // и тд PRESCALER_64 6 PRESCALER_128 7 PRESCALER_256 8 PRESCALER_1024 9 /* константы для настройки режима работы таймеров */ STANDARD_MODE 10 // таймер считает до 255 и сбрасывается в 0, (может до 511/1023 для таймера 1) CTC_MODE 11 // таймер считает от 0 до числа заданного функцией TIMERn_COMPA_setValue(), после чего сбрасывается (в этот момент может вызват прерывание) FAST_PWM_8BIT 12 // аппаратный шим 8 бит FAST_PWM_9BIT 13 // для таймера 1 FAST_PWM_10BIT 14 PHASECORRECT_PWM_8BIT 15 // шим с коррекцией PHASECORRECT_PWM_9BIT 16 PHASECORRECT_PWM_10BIT 17 FAST_PWM_CUSTOM 18 // шим с кастомной глубиной, глубина задается TIMER0/2_COMPA_setValue() и TIMER1_setTop(); PHASECORRECT_PWM_CUSTOM 19 // то же самое но с коррекцией /* константы для управления аппаратными выходами с таймеров */ DISABLE_COMP 20 // выход отключен от ноги, ногой можно пользоваться NORM_PWM 21 // выход генерирует шим >>> +5В при сбросе таймера, 0В при совпадении INVERT_PWM 22 // выход генерирует инвертированный шим >>> 0В при сбросе таймера, +5В при совпадении TOGGLE_PIN 23 // выход генерирует меандр >>> инверсия состояния пина при совпадении
ПРИМЕРЫ
#include "directTimers.h" /* пример генерации меандра на таймере 1*/ /* формула для расчета предела счета для генерации меандра приведена в шпаргалке README */ /* unsigned int top = (8000000/freqency)-1; где top- предел счета, на который мы настроим таймер, freqency - желаемая частота меандра */ /* максимальная частота меандра - 8мгц */ // сгенерируем меандр с частотой 100кгц на двух каналах таймера 1 с возможностью смещения фазы 0...180 градусов относительно друг друга // соотв для частоты 100 кгц >>> top = (8000000/100000)-1; >>> top = 79; void setup() { TIMER1_setClock(PRESCALER_1); //установим максимальную частоту таймера TIMER1_setMode(CTC_MODE); // включим сброс по совпадению, происходит при совпадении счетного регистра со значением заданым TIMER1_COMPA_setValue(); TIMER1_COMPA_mode(TOGGLE); // инвертирование состояние ноги при совпадении TIMER1_COMPB_mode(TOGGLE); // инвертирование состояние ноги при совпадении TIMER1_COMPA_setValue(79); //в режиме CTC_MODE задает предел счета и соотв частоту событий, на этом моменте уже начнется генерация меандра на канале А } void loop() { byte value = map(analogRead(A0), 0, 1023, 0, 79); // преобразуем значение с потенциометра в установленный нами диапазон 0...79 /* 0...79 в данном случае эквивалентно сдвигу фазы на 0...180 градусов */ TIMER1_COMPB_setValue(value); // изменяя значение от 0 до 79 мы можем сдвигать меандр на канале В относительно первого на 0...180 градусов }
#include "directTimers.h" /* пример генерации шим с выбранной частотой на таймере 1 формула для рачета предела счета приведена в шпаргалке README */ /* Для режима FAST PWM >>> top = (Fтаймера/Fшим)-1; Для режима PHASECORRECT PWM >>> top = Fтаймера/(2*Fшим); */ // пусть частота ШИМ будет 25 кгц в режиме коррекции фазы >>> top = 8000000/25000 >>> top = 320; void setup() { pinMode(9, 1); // настраиваем канал А как выход pinMode(10, 1); // настраиваем канал В как выход TIMER1_setClock(PRESCALER_1); // задаем таймеру максимальную частоту TIMER1_setMode(PHASECORRECT_PWM_CUSTOM); // включаем режим кастомного предела счета TIMER1_setTop(320); // устанавливаем предел счета 320, чтобы получить частоту 25 кгц с коррекцией фазы TIMER1_COMPA_mode(PWM); // настраиваем аппаратные выходы с таймера в режим ШИМ TIMER1_COMPB_mode(PWM); } void loop() { int dutyA = map(analogRead(A0), 0, 1023, 0, 320); // пересчитываем диапазон потенциометра в диапазон таймера 0...top >>> 0...320 int dutyB = map(analogRead(A1), 0, 1023, 0, 320); TIMER1_COMPA_setValue(dutyA); // устанавливаем на выходе А заполнение потенциометром (pin 9) TIMER1_COMPB_setValue(dutyB); // (pin 10) }
#include "directTimers.h" /* пример генерации быстрого шим 8 бит с частотой 31 кгц и коррекцией фазы */ void setup() { TIMER2_setClock(PRESCALER_1); // настройка делителя таймера TIMER2_setMode(PHASECORRECT_PWM_8BIT); // настройка режима работы таймера TIMER2_COMPA_mode(PWM); // прямой шим канал А TIMER2_COMPA_mode(INVERT_PWM); // инверсный шим канал B pinMode(11, OUTPUT); // аппаратный выход с таймера А pinMode(3, OUTPUT); // аппаратный выход с таймера B } void loop() { int duty = analogRead(A0) / 4; TIMER1_COMPA_setValue(duty); // заполнение шим канала А (pin 11) регулируется потенциометром TIMER1_COMPB_setValue(duty); // заполнение равно каналу A и инвертировано. (pin 3) }
#include "directTimers.h" /* пример генерации стандартного шим 10 бит */ void setup() { TIMER1_setClock(PRESCALER_1); // настройка делителя таймера TIMER1_setMode(FAST_PWM_10BIT); // настройка режима работы таймера TIMER1_COMPA_mode(PWM); // настроили аппаратные выходы с таймера в режим шим TIMER1_COMPB_mode(PWM); pinMode(9, OUTPUT); // аппаратный выход с таймера А pinMode(10, OUTPUT); // аппаратный выход с таймера B } void loop() { TIMER1_COMPA_setValue(analogRead(A0)); // заполнение шим канала А (pin 9) регулируется потенциометром TIMER1_COMPB_setValue(analogRead(A1)); // аналогично с каналом B (pin 10) }
#include "directTimers.h" /* пример генерации нескольких прерываний по таймерам */ volatile int actualValue; void setup() { Serial.begin(9600); TIMER1_setClock(PRESCALER_1024); // максимально замедляем таймер TIMER1_setMode(CTC_MODE); // включаем сброс таймера по совпадению TIMER1_COMPA_setValue(7811); // настроим таймер1 на прерывание 2 раза в секунду TIMER1_attach_COMPA(); // мигаем диодом pinMode(13, 1); // подключим светодиод на 13 ноге TIMER2_setClock(PRESCALER_1024); // максимально замедляем таймер TIMER2_setMode(CTC_MODE); // включаем сброс таймера по совпадению TIMER2_COMPA_setValue(24); // настраиваем прерывание на часототу 625 гц TIMER2_attach_COMPA(); // функция для получения актуального значения с ацп WDT_attachInterrupt(128); // настраиваем ватчдог на прерывание примерно раз в секунду >> доступны делители 16/32/64/128/256/512/1024 => ~0.125sec/0.25sec/0.5sec/1sec/2sec/4sec/8sec; while (millis() < 5000); // пока не пройдет 20 секунд сидим в setup и принимаем прерывания ватчдога WDT_detachInterrupt(); // отключаем прерывания ватчдога и продолжаем } void loop() { Serial.println(actualValue); // кидаем в порт актуальное значение с ацп } ISR_T2_COMPA { actualValue = analogRead(A0); // читаем ацп в прерывании } ISR_WDT { Serial.println("hello from watchdog"); // прерывание ватчдога } ISR_T1_COMPA { // прерывание мигания светодиодом digitalWrite(13, !digitalRead(13)); }
ОСТАЛЬНЫЕ БИБЛИОТЕКИ

У меня есть ещё очень много всего интересного! Смотрите полный список библиотек вот здесь.