ОБНОВЛЕНИЯ
- v1.0
БИБЛИОТЕКА
Библиотека для расширенного (ручного) управления таймерами ATmega328/168. Библиотека низкоуровневая и непростая в использовании, изучайте примеры!
- Функции библиотеки позволяют получить доступ ко всем возможностям и режимам работы с таймерами/счётчиками + прерывания watchdog
- Ничего не урезано и не упрощено, доступен весь описанный в даташите функционал
- Разработчик – Egor ‘Nich1con’ Zaharov
Поддерживаемые платформы: платы на ATmega328/168 (Arduino Nano, UNO, Pro Mini)
УСТАНОВКА
- Библиотеку можно найти и установить через менеджер библиотек по названию directTimers в:
- Arduino IDE (Инструменты/Управлять библиотеками)
- Arduino IDE v2 (вкладка «Library Manager»)
- PlatformIO (PIO Home, вкладка «Libraries»)
- Про ручную установку читай здесь
ДОКУМЕНТАЦИЯ
Список функций
// 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 // тактирование будет остановлено , таймер "заморожен" EXTERNAL_FALLING // тактирование внешним клоком до 8 мгц по спаду EXTERNAL_RISING // тактирование внешним клоком до 8 мгц по фронту // делители PRESCALER_1 PRESCALER_8 PRESCALER_32 PRESCALER_64 PRESCALER_128 PRESCALER_256 PRESCALER_1024 /* константы для настройки режима работы таймеров */ STANDARD_MODE // таймер считает до 255 и сбрасывается в 0, (может до 511/1023 для таймера 1) CTC_MODE // таймер считает от 0 до числа заданного функцией TIMERn_COMPA_setValue(), после чего сбрасывается (в этот момент может вызват прерывание) FAST_PWM_8BIT // аппаратный шим 8 бит FAST_PWM_9BIT // для таймера 1 FAST_PWM_10BIT // шим с коррекцией PHASECORRECT_PWM_8BIT PHASECORRECT_PWM_9BIT PHASECORRECT_PWM_10BIT FAST_PWM_CUSTOM // шим с кастомной глубиной, глубина задается TIMER0/2_COMPA_setValue() и TIMER1_setTop(); PHASECORRECT_PWM_CUSTOM // то же самое но с коррекцией /* константы для управления аппаратными выходами с таймеров */ DISABLE_COMP // выход отключен от ноги, ногой можно пользоваться NORM_PWM // выход генерирует шим >>> +5В при сбросе таймера, 0В при совпадении INVERT_PWM // выход генерирует инвертированный шим >>> 0В при сбросе таймера, +5В при совпадении TOGGLE_PIN // выход генерирует меандр >>> инверсия состояния пина при совпадении
ПРИМЕРЫ
Остальные примеры смотри в папке examples библиотеки, также примеры можно открыть из Arduino IDE/Файл/Примеры
Генерируем меандр
#include/* пример генерации меандра на таймере 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_PIN); // инвертирование состояние ноги при совпадении TIMER1_COMPB_mode(TOGGLE_PIN); // инвертирование состояние ноги при совпадении 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/* пример генерации шим с выбранной частотой на таймере 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(NORM_PWM); // настраиваем аппаратные выходы с таймера в режим ШИМ TIMER1_COMPB_mode(NORM_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) }
ШИМ 10 бит
#include/* пример генерации стандартного шим 10 бит */ void setup() { TIMER1_setClock(PRESCALER_1); // настройка делителя таймера TIMER1_setMode(FAST_PWM_10BIT); // настройка режима работы таймера TIMER1_COMPA_mode(NORM_PWM); // настроили аппаратные выходы с таймера в режим шим TIMER1_COMPB_mode(NORM_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/* пример генерации нескольких прерываний по таймерам */ 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)); }
ПОДДЕРЖАТЬ
Вы можете поддержать меня за создание доступных проектов с открытым исходным кодом, полный список реквизитов есть вот здесь.
5/5 - (2 голоса)
0
0
голоса
Рейтинг статьи