├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── docs └── timers.xlsx ├── examples ├── all_functions │ └── all_functions.ino ├── double_interrupts │ └── double_interrupts.ino ├── encoder_mode │ └── encoder_mode.ino ├── meandr_2tact │ └── meandr_2tact.ino ├── meandr_test │ └── meandr_test.ino ├── simple │ └── simple.ino └── withoutInterrupts │ └── withoutInterrupts.ino ├── keywords.txt ├── library.properties └── src ├── GyverTimers.cpp └── GyverTimers.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/GyverTimers.svg?color=brightgreen)](https://github.com/GyverLibs/GyverTimers/releases/latest/download/GyverTimers.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/GyverTimers.svg)](https://registry.platformio.org/libraries/gyverlibs/GyverTimers) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/GyverTimers?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # GyverTimers 10 | Настройка и контроль прерываний по аппаратным таймерам ATmega328p, ATmega2560 11 | - Поддерживаются все три таймера на ATmega328 и шесть таймеров на ATmega2560; 12 | - Настройка периода (мкс) и частоты (Гц) прерываний: 13 | - 8 бит таймеры: 61 Гц - 1 МГц (16 384 мкс.. 1 мкс); 14 | - 16 бит таймеры: 0.24 Гц - 1 МГц (4 200 000 мкс.. 1 мкс); 15 | - Автоматическая корректировка настройки периода от частоты тактирования (F_CPU); 16 | - Функция возвращает точный установившийся период/частоту для отладки (частота ограничена разрешением таймера); 17 | - Поддержка многоканального режима работы: один таймер вызывает 2 (ATmega328) или 18 | 3 (ATmega2560, таймеры 1, 3, 4, 5) прерывания с настраиваемым сдвигом по фазе 0-360 градусов; 19 | - Настраиваемое действие аппаратного вывода таймера по прерыванию: высокий сигнал, низкий сигнал, переключение. 20 | Позволяет генерировать меандр (одно- и двухтактный); 21 | - Контроль работы таймера: старт/стоп/пауза/продолжить/инициализация; 22 | 23 | ### Совместимость 24 | ATmega328p, ATmega2560 25 | 26 | ### Документация 27 | К библиотеке есть [расширенная документация](https://alexgyver.ru/GyverTimers/) 28 | 29 | ## Содержание 30 | - [Установка](#install) 31 | - [Инициализация](#init) 32 | - [Использование](#usage) 33 | - [Пример](#example) 34 | - [Версии](#versions) 35 | - [Баги и обратная связь](#feedback) 36 | 37 | 38 | ## Установка 39 | - Библиотеку можно найти по названию **GyverTimers** и установить через менеджер библиотек в: 40 | - Arduino IDE 41 | - Arduino IDE v2 42 | - PlatformIO 43 | - [Скачать библиотеку](https://github.com/GyverLibs/GyverTimers/archive/refs/heads/main.zip) .zip архивом для ручной установки: 44 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 45 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 46 | - Распаковать и положить в *Документы/Arduino/libraries/* 47 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 48 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 49 | ### Обновление 50 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 51 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 52 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 53 | 54 | 55 | 56 | ## Инициализация 57 | Нет 58 | 59 | 60 | ## Использование 61 | ```cpp 62 | Методы для Timer0, Timer1, Timer2... 63 | uint32_t setPeriod(период); // установка периода в микросекундах и запуск таймера. Возвращает реальный период (точность ограничена разрешением таймера). 64 | uint32_t setFrequency(частота); // установка частоты в Герцах и запуск таймера. Возвращает реальную частоту (точность ограничена разрешением таймера). 65 | float setFrequencyFloat(частота float); // установка частоты в Герцах и запуск таймера, разрешены десятичные дроби. Возвращает реальную частоту (точность ограничена разрешением таймера). 66 | void enableISR(источник); // включить прерывания, канал прерываний CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560) 67 | void disableISR(источник); // выключить прерывания, канал CHANNEL_A или CHANNEL_B. Счёт таймера не останавливается (без указания параметров будет выключен канал А). 68 | void pause(); // приостановить счёт таймера, не сбрасывая счётчик 69 | void resume(); // продолжить счёт после паузы 70 | void stop(); // остановить счёт и сбросить счётчик 71 | void restart(); // перезапустить таймер (сбросить счётчик) 72 | void setDefault(); // установить параметры таймера по умолчанию ("Ардуино-умолчания") 73 | void outputEnable(канал, режим); // канал: включить выход таймера CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560). Режим: TOGGLE_PIN, CLEAR_PIN, SET_PIN (переключить/выключить/включить пин по прерыванию) 74 | void outputDisable(канал); // отключить выход таймера CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560, см. такблицу таймеров) 75 | void outputState(канал, состояние); // сменить состояние канала: HIGH / LOW 76 | void phaseShift(источник, фаза); // сдвинуть фазу канала на 0-360 градусов (у 8 бит таймеров двигается только канал B) 77 | bool ready(uint8_t channel); // возвращает true, если произошло прерывание на указанном канале 78 | bool ready(); // возвращает true, если произошло прерывание на канале A 79 | 80 | /* 81 | Библиотека даёт прямой доступ к прерыванию без “Ардуиновских” attachInterrupt, что позволяет 82 | сократить время вызова функции-обработчика прерывания. Прерывание с настроенной частотой 83 | будет обрабатываться в блоке вида ISR(канал) {}, пример: 84 | */ 85 | ISR(TIMER1_A) { 86 | // ваш код 87 | } 88 | 89 | ISR(TIMER1_B) { 90 | // ваш код 91 | } 92 | 93 | ISR(TIMER2_B) { 94 | // ваш код 95 | } 96 | 97 | ISR(TIMER0_A) { 98 | // ваш код 99 | } 100 | 101 | /* 102 | -------------------------------- Arduino NANO 16 МГц (ATmega328) ------------------------------------ 103 | Таймер | Разрядность | Частоты | Периоды | Выходы | Пин Arduino | Пин МК| 104 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 105 | Timer0 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | D6 | PD6 | 106 | | | | | CHANNEL_B | D5 | PD5 | 107 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 108 | Timer1 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | D9 | PB1 | 109 | | | | | CHANNEL_B | D10 | PB2 | 110 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 111 | Timer2 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | D11 | PB3 | 112 | | | | | CHANNEL_B | D3 | PD3 | 113 | ---------------------------------------------------------------------------------------------------- 114 | 115 | ------------------------------ Arduino MEGA 16 МГц (ATmega2560) ------------------------------------- 116 | Таймер | Разрядность | Частоты | Периоды | Выходы | Пин Arduino | Пин МК| 117 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 118 | Timer0 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | 13 | PB7 | 119 | | | | | CHANNEL_B | 4 | PG5 | 120 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 121 | Timer1 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 11 | PB5 | 122 | | | | | CHANNEL_B | 12 | PB6 | 123 | | | | | CHANNEL_C | 13 | PB7 | 124 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 125 | Timer2 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | 10 | PB4 | 126 | | | | | CHANNEL_B | 9 | PH6 | 127 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 128 | Timer3 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 5 | PE3 | 129 | | | | | CHANNEL_B | 2 | PE4 | 130 | | | | | CHANNEL_C | 3 | PE5 | 131 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 132 | Timer4 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 6 | PH3 | 133 | | | | | CHANNEL_B | 7 | PH4 | 134 | | | | | CHANNEL_C | 8 | PH5 | 135 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 136 | Timer5 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 46 | PL3 | 137 | | | | | CHANNEL_B | 45 | PL4 | 138 | | | | | CHANNEL_C | 44 | PL5 | 139 | ---------------------------------------------------------------------------------------------------- 140 | */ 141 | ``` 142 | 143 | 144 | ## Пример 145 | Остальные примеры смотри в **examples**! 146 | ```cpp 147 | // Демонстрация всех функций библиотеки 148 | 149 | #include 150 | 151 | void setup() { 152 | // Перенастроить таймер и задать ему период или частоту 153 | // Все функции возвращают реальный период / частоту, которые могут отличаться от введенных 154 | Timer2.setPeriod(1000); // Задать конкретный период 1000 мкс (~ 1000 гц), вернет реальный период в мкс 155 | Timer0.setFrequency(250); // Задать частоту прерываний таймера в Гц, вернет реальную частоту в герцах 156 | Timer1.setFrequencyFloat(50.20); // Задать частоту более точно, в дробных числах, актуально для низких частот и таймера 1 157 | // С этого момента таймер уже перенастроен и гоняет с выьранной частотой / периодом 158 | 159 | // Подключить прерывание таймера, с этого момента прерывания начнут вызываться 160 | Timer0.enableISR(); // Подключить стандартное прерывание, канал А, без сдига фаз 161 | Timer2.enableISR(CHANNEL_B); // Подключить прерывание таймера 2, канал B 162 | Timer1.enableISR(CHANNEL_A); // Подключить прерывание канала А 163 | Timer1.enableISR(CHANNEL_B); // Подключить второе прерывание таймера 1 164 | // Прерывание уже начнет вызываться 165 | 166 | // Если вдруг прерывание нужно отключить, не останавливая таймер 167 | Timer1.disableISR(CHANNEL_B); 168 | // С этого момента прерывание B больше не будет вызываться 169 | 170 | // Если нужно приостановить таймер ПОЛНОСТЬЮ, аппаратно 171 | Timer2.pause(); 172 | // С этого момента таймер стоит на месте, содержимое счетчика остается нетронутым 173 | 174 | // Теперь таймер можно вернуть в строй 175 | Timer2.resume(); 176 | // Таймер продолжил считать с того же места 177 | 178 | // Если нужно полностью остановить таймер и сбросить содержимое счетчика 179 | Timer1.stop(); 180 | // Таймер стоит, счетчик сброшен 181 | 182 | // Возвращаем таймер в строй 183 | Timer1.restart(); 184 | // Таймер перезапущен, начал считать с начала 185 | 186 | // Если нужно вернуть стандартные Arduino - настройки таймера 187 | Timer0.setDefault(); 188 | // Теперь таймер работает в станлартном режиме 189 | } 190 | 191 | // векторы прерываний 192 | ISR(TIMER1_A) { 193 | } 194 | 195 | ISR(TIMER1_B) { 196 | } 197 | 198 | ISR(TIMER2_B) { 199 | } 200 | 201 | ISR(TIMER0_A) { 202 | } 203 | 204 | void loop() { 205 | 206 | } 207 | ``` 208 | 209 | 210 | ## Версии 211 | - v1.1 - исправлена ошибка в расчёте периодов 212 | - v1.2 - код разбит на h и cpp 213 | - v1.3 - поправлен незначительный баг 214 | - v1.4 - исправлена таблица частот и периодов 215 | - v1.5 - исправлен restart и resume 216 | - v1.6 - phase shift вынесен отдельным методом 217 | - v1.7 - поправлена документация 218 | - v1.8 - исправлен баг с макс периодом 219 | - v1.9 - исправлен баг с возвращаемым 2х периодом 220 | - v1.10 - добавлен флаг ready 221 | 222 | 223 | ## Баги и обратная связь 224 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 225 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 226 | 227 | 228 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 229 | - Версия библиотеки 230 | - Какой используется МК 231 | - Версия SDK (для ESP) 232 | - Версия Arduino IDE 233 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 234 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 235 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 236 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Gyvertimers 4 | Setting up and controlling interruptions on the hardware timer ATMEGA328P, Atmega2560 5 | - all three timers on Atmega328 and six timers on Atmega2560 are supported; 6 | - Setting up the period (ISS) and frequency (Hz) interruptions: 7 | - 8 bit timers: 61 Hz - 1 MHz (16 384 μs .. 1 μs); 8 | - 16 bits of timers: 0.24 Hz - 1 MHz (4,200,000 μs .. 1 μs); 9 | - automatic adjustment of the settings of the period from the tactive frequency (F_CPU); 10 | - the function returns the exact established period/frequency for debugging (the frequency is limited by the timer resolution); 11 | - Support for the multichannel mode of operation: one timer calls 2 (atmega328) or 12 | 3 (ATMEGA2560, timers 1, 3, 4, 5) interruption with a custom-made shift in a phase of 0-360 degrees; 13 | - the customizable action of the hardware output of the timer for interruption: high signal, low signal, switching. 14 | Allows you to generate a meander (one- and two-stroke); 15 | - timer control: start/stop/pause/continue/initialization; 16 | 17 | ## compatibility 18 | Atmega328p, Atmega2560 19 | 20 | ### Documentation 21 | There is [extended documentation](https://alexgyver.ru/gyvertimers/) to the library 22 | 23 | ## Content 24 | - [Installation](#install) 25 | - [Initialization](#init) 26 | - [Usage](#usage) 27 | - [Example](#example) 28 | - [Versions](#versions) 29 | - [Bugs and feedback](#feedback) 30 | 31 | 32 | ## Installation 33 | - The library can be found by the name **gyvertimers** and installed through the library manager in: 34 | - Arduino ide 35 | - Arduino ide v2 36 | - Platformio 37 | - [download the library](https://github.com/gyverlibs/gyvertimers/archive/refs/heads/main.zip) .Zip archive for manual installation: 38 | - unpack and put in *C:\Program Files (X86)\Arduino\Libraries* (Windows X64) 39 | - unpack and put in *C:\Program Files\Arduino\Libraries* (Windows X32) 40 | - unpack and put in *documents/arduino/libraries/* (Mac) 41 | - (Arduino IDE) Automatic installation from ZIP: *Sketch > Include library > Add .ZIP library...* and specify downloaded archive 42 | - Read more detailed instructions for installing libraries [here](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 43 | ### Update 44 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 45 | - through the IDE library manager: find the library how to install and click "update" 46 | - Manually: **remove the folder with the old version**, and then put a new one in its place. “Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors! 47 | 48 | 49 | 50 | ## Initialization 51 | No 52 | 53 | 54 | ## Usage 55 | ```CPP 56 | Methods for Timer0, Timer1, Timer2 ... 57 | uint32_t setperiod (period);// Installation of the period in microseconds and starting the timer.Returns the real period (accuracy is limited by the timer resolution). 58 | uint32_t setfrequency (frequency);// Frequency installation in Hertz and the timer launch.Returns the real frequency (accuracy is limited by the timer resolution). 59 | Float SetFrequencyFloat// Frequency installation in Hertsa and the timer launch, decimal fractions are allowed.Returns the riverfrequency (accuracy is limited by timer resolution). 60 | VOID Enableisr (source);// Turn on the interruptions, the channel of interruptions Channel_a or Channel_b (+ Channel_C by Mega2560) 61 | Void Disableisr (source);// Turn off the interruptions, channel Channel_a or Channel_b.The timer account does not stop (the channel A will be turned off without specifying the parameters). 62 | VOID PAUSE ();// suspend the timer account without dropping the counter 63 | VOID Resume ();// Continue the score after a pause 64 | VOID Stop ();// stop the score and drop the counter 65 | VOID RESTART ();// restart the timer (drop the counter) 66 | VOID Setdefault ();// Install the default timer parameters ("arduino-wilting") 67 | VOID outputenable (channel, mode);// Channel: Turn on the output of the Channel_a or Channel_b timer (+ channel_c in Mega2560).Mode: Toggle_pin, Clear_pin, Set_pin (switch/turn off/turn on the PIN on interruption) 68 | VOID outputdisable (channel);// Disconnect the output of the Channel_a or Channel_b timer (+ channel_c from Mega2560, see Thamere Taklitsa) 69 | VOID outputState (channel, condition);// Change the condition of the channel: High / Low 70 | VOID PHASSHIFT (source, phase);// shift the phase of the channel by 0-360 degrees (only channel b moves 8 bits of timers) 71 | Bool Ready (Uint8_T Channel);// returns True if an interruption on the specified channel occurs 72 | Bool Ready ();// returns True if there is an interruption on the channel A 73 | 74 | /* 75 | The library gives direct access to interruption without “arduinsky” Attachinterrapt, which allows 76 | Reduce the time of calling the interruption processor function.Interruption with configured frequency 77 | will be processed in the block of the type of ISR (channel) {}, example: 78 | */ 79 | ISR (Timer1_a) { 80 | // Your code 81 | } 82 | 83 | ISR (Timer1_b) { 84 | // Your code 85 | } 86 | 87 | ISR (Timer2_b) { 88 | // Your code 89 | } 90 | 91 | ISR (Timer0_A) { 92 | // Your code 93 | } 94 | 95 | /* 96 | ------------------------------------------- ARDUINO Nano 16 MHz (atmega328) ------------------------------------ 97 | Timer |Discharge |Frequencies |Periods |Exits |Pin Arduino |PIN MK | 98 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 99 | Timer0 |8 bits |61 Hz - 1 MHz |16 384 .. 1 μs |Channel_a |D6 |PD6 | 100 | ||||Channel_b |D5 |PD5 | 101 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 102 | Timer1 |16 bit |0.24 Hz - 1 MHz |4 200 000 .. 1 μs |Channel_a |D9 |PB1 | 103 | ||||Channel_b |D10 |PB2 | 104 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 105 | Timer2 |8 bits |61 Hz - 1 MHz |16 384 .. 1 μs |Channel_a |D11 |PB3 | 106 | ||||Channel_b |D3 |PD3 | 107 | ------------------------------------------------------------------------------------------ 108 | 109 | -------------------------------------------- MEGA 16 MHz (atmega2560) --------------------------------------- 110 | Timer |Discharge |Frequencies |Periods |Exits |Pin Arduino |PIN MK | 111 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 112 | Timer0 |8 bits |61 Hz - 1 MHz |16 384 .. 1 μs |Channel_a |13 |PB7 | 113 | ||||Channel_b |4 |PG5 | 114 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 115 | Timer1 |16 bit |0.24 Hz - 1 MHz |4 200 000 .. 1 μs |Channel_a |11 |PB5 | 116 | ||||Channel_b |12 |PB6 | 117 | ||||Channel_c |13 |PB7 | 118 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 119 | Timer2 |8 bits |61 Hz - 1 MHz |16 384 .. 1 μs |Channel_a |10 |PB4 | 120 | ||||Channel_b |9 |PH6 | 121 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | --------------- | ------ | 122 | Timer3 |16 bit |0.24 Hz - 1 MHz |4 200 000 .. 1 μs |Channel_a |5 |PE3 | 123 | ||||Channel_b |2 |PE4 | 124 | ||||Channel_c |3 |PE5 | 125 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 126 | Timer4 |16 bit |0.24 Hz - 1 MHz |4 200 000 .. 1 μs |Channel_a |6 |PH3 | 127 | ||||Channel_b |7 |PH4 | 128 | ||||Channel_c |8 |PH5 | 129 | -------- | ------------------ | -------------------------------------------------------------- | ----------- | ------------------------------------------------------| 130 | Timer5 |16 bit |0.24 Hz - 1 MHz |4 200 000 .. 1 μs |Channel_a |46 |PL3 | 131 | ||||Channel_b |45 |PL4 | 132 | ||||Channel_c |44 |PL5 | 133 | ------------------------------------------------------------------------------------------ 134 | */ 135 | ``` 136 | 137 | 138 | ## Example 139 | The rest of the examples look at ** Examples **! 140 | ```CPP 141 | // Demonstration of all functions of the library 142 | 143 | #include 144 | 145 | VOID setup () { 146 | // reconfigure the timer and set him a period or frequency 147 | // All functions return the real period / frequency that may differ from the introduced 148 | Timer2.Setperiod (1000);// set a specific period of 1000 μs (~ 1000 Hz), will return the real period to the ISS 149 | Timer0.setfrequency (250);// Set the frequency of the timer interruptions in Hz, will return the real frequency in Herza 150 | Timer1.setfrequencyFloat (50.20);// Set the frequency more accurately, in fractional numbers, it is relevant for low frequencies and timer 1 151 | // From that moment on, the timer is already reconfigured and drives with a fractured frequency / period 152 | 153 | // Connect the interruption of the timer, from this moment the interruption will begin to be called 154 | Timer0.enableisr ();// connect the standard interruption, channel A, without a phase retire 155 | Timer2.enableisr (Channel_b);// Connect the interruption of timer 2, channel b 156 | Timer1.enableisr (Channel_a);// Connect the interruption of the channel a 157 | Timer1.enableisr (Channel_b);// connect the second interruption of timer 1 158 | // interruption will already begin to be called 159 | 160 | // if suddenly the interruption needs to be turned off without stopping the timer 161 | Timer1.disableisr (Channel_b); 162 | // From this moment, interruption b will no longer be called 163 | 164 | // if you need to suspend the timer completely, hardware 165 | Timer2.pause (); 166 | // From that moment on the timer stands still, the contents of the counter remains untouched 167 | 168 | // Now the timer can be returned to duty 169 | Timer2.Resum (); 170 | // Timer continued to count from the same place 171 | 172 | // if you need to completely stop the timer and drop the contents of the counter 173 | Timer1.Stop (); 174 | // Timer stands, the counter is dropped 175 | 176 | // Return the timer to duty 177 | Timer1.Restart (); 178 | // The timer is restarted, began to count from the beginning 179 | 180 | // if you need to return the standard arduino - timer settings 181 | Timer0.Setdefault (); 182 | // Now the timer works in Stanland mode 183 | } 184 | 185 | // Vectors of interruptions 186 | ISR (Timer1_a) { 187 | } 188 | 189 | ISR (Timer1_b) { 190 | } 191 | 192 | ISR (Timer2_b) { 193 | } 194 | 195 | ISR (Timer0_A) { 196 | } 197 | 198 | VOID loop () { 199 | 200 | } 201 | ``` 202 | 203 | 204 | ## Versions 205 | - V1.1 - Fixed error in the calculation of periods 206 | - V1.2 - The code is divided into h and CPP 207 | - v1.3 - a slight bug is corrected 208 | - V1.4 - Fixed frequency and periods are fixed 209 | - V1.5 - Restart and Resume fixed 210 | - V1.6 - Phase Shift is made in a separate method 211 | - v1.7 - documentation corrected 212 | - V1.8 - Fixed bug with max period 213 | - V1.9 - Fixed a bug with a return 2 -period 214 | - V1.10 - added flag of Ready 215 | 216 | 217 | ## Bugs and feedback 218 | Create an **issue** when you find bugs, and better immediately write to the mail [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 219 | The library is open for refinement and your **pull requests**. 220 | 221 | 222 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 223 | - The version of the library 224 | - What is MK used 225 | - SDK version (for ESP) 226 | - Version of Arduino IDE 227 | - Whether the built-in examples work correctly, in which the functions and designs are used, leading to a bug in your code 228 | - What code is loaded, what was expected, and how it works in reality 229 | - Ideally, attach the minimum code in which the bug is observed. Not a thousand lines, but a minimum code. 230 | -------------------------------------------------------------------------------- /docs/timers.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GyverLibs/GyverTimers/8d16082b9d7210e80fc342b0e17899b5107e47d1/docs/timers.xlsx -------------------------------------------------------------------------------- /examples/all_functions/all_functions.ino: -------------------------------------------------------------------------------- 1 | // Демонстрация всех функций библиотеки 2 | 3 | #include 4 | 5 | void setup() { 6 | // Перенастроить таймер и задать ему период или частоту 7 | // Все функции возвращают реальный период / частоту, которые могут отличаться от введенных 8 | Timer2.setPeriod(1000); // Задать конкретный период 1000 мкс (~ 1000 гц), вернет реальный период в мкс 9 | Timer0.setFrequency(250); // Задать частоту прерываний таймера в Гц, вернет реальную частоту в герцах 10 | Timer1.setFrequencyFloat(50.20); // Задать частоту более точно, в дробных числах, актуально для низких частот и таймера 1 11 | // С этого момента таймер уже перенастроен и гоняет с выьранной частотой / периодом 12 | 13 | // Подключить прерывание таймера, с этого момента прерывания начнут вызываться 14 | Timer0.enableISR(); // Подключить стандартное прерывание, канал А, без сдига фаз 15 | Timer2.enableISR(CHANNEL_B); // Подключить прерывание таймера 2, канал B 16 | Timer1.enableISR(CHANNEL_A); // Подключить прерывание канала А 17 | Timer1.enableISR(CHANNEL_B); // Подключить второе прерывание таймера 1 18 | // Прерывание уже начнет вызываться 19 | 20 | // Если вдруг прерывание нужно отключить, не останавливая таймер 21 | Timer1.disableISR(CHANNEL_B); 22 | // С этого момента прерывание B больше не будет вызываться 23 | 24 | // Если нужно приостановить таймер ПОЛНОСТЬЮ, аппаратно 25 | Timer2.pause(); 26 | // С этого момента таймер стоит на месте, содержимое счетчика остается нетронутым 27 | 28 | // Теперь таймер можно вернуть в строй 29 | Timer2.resume(); 30 | // Таймер продолжил считать с того же места 31 | 32 | // Если нужно полностью остановить таймер и сбросить содержимое счетчика 33 | Timer1.stop(); 34 | // Таймер стоит, счетчик сброшен 35 | 36 | // Возвращаем таймер в строй 37 | Timer1.restart(); 38 | // Таймер перезапущен, начал считать с начала 39 | 40 | // Если нужно вернуть стандартные Arduino - настройки таймера 41 | Timer0.setDefault(); 42 | // Теперь таймер работает в станлартном режиме 43 | } 44 | 45 | // векторы прерываний 46 | ISR(TIMER1_A) { 47 | 48 | } 49 | 50 | ISR(TIMER1_B) { 51 | 52 | } 53 | 54 | ISR(TIMER2_B) { 55 | 56 | } 57 | 58 | ISR(TIMER0_A) { 59 | 60 | } 61 | 62 | void loop() { 63 | 64 | } 65 | -------------------------------------------------------------------------------- /examples/double_interrupts/double_interrupts.ino: -------------------------------------------------------------------------------- 1 | // Пример генерации двухканальных прерываний на таймере с РАВНЫМ периодом, но сдвинутых по фазе 2 | // два потока прерываний с сдвигом 180 градусов (полная инверсия) 3 | 4 | #include 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | 9 | Serial.print("Real timer frequency is : "); // Выведем реальную частоту, реальная может отличаться от заданой (ограничено разрешением таймера) 10 | Serial.println(Timer1.setFrequencyFloat(2.50)); // Частота прерываний - 2.5 гц , используй .setFrequency(...) для целых чисел 11 | delay(1000); 12 | Timer1.enableISR(CHANNEL_A); // Первый канал - А 13 | Timer1.enableISR(CHANNEL_B); // Второй канал - B 14 | Timer1.phaseShift(CHANNEL_B, 180); // сдвинем фазу относительно первого 15 | } 16 | 17 | void loop() {} 18 | 19 | // два прерывания на одном таймере 20 | ISR(TIMER1_A) { 21 | Serial.println(" Channel A interrupt !"); // Прерывание А 22 | } 23 | 24 | ISR(TIMER1_B) { 25 | Serial.println(" Channel B interrupt !"); // Прерывание B 26 | } 27 | -------------------------------------------------------------------------------- /examples/encoder_mode/encoder_mode.ino: -------------------------------------------------------------------------------- 1 | // Пример генерации двухтактного меандра на таймере 2 (пины D3 и D11) 2 | #include 3 | 4 | void setup() { 5 | pinMode(3, OUTPUT); // настроить пин как выход 6 | pinMode(11, OUTPUT); // настроить пин как выход 7 | 8 | // из-за особенности генерации меандра таймером 9 | // частоту нужно указывать в два раза больше нужной! 10 | Timer2.setFrequency(15000 * 2); // настроить частоту в Гц и запустить таймер. Меандр на 15 кГц 11 | Timer2.outputEnable(CHANNEL_A, TOGGLE_PIN); // в момент срабатывания таймера пин будет переключаться 12 | Timer2.outputEnable(CHANNEL_B, TOGGLE_PIN); // в момент срабатывания таймера пин будет переключаться 13 | 14 | // задаём фазовый сдвиг 0-360 (для всех каналов кроме A на 8 бит таймерах) 15 | Timer2.phaseShift(CHANNEL_B, 180); 16 | } 17 | 18 | void loop() { 19 | } 20 | -------------------------------------------------------------------------------- /examples/meandr_2tact/meandr_2tact.ino: -------------------------------------------------------------------------------- 1 | // Пример генерации двухтактного меандра на таймере 2 (пины D3 и D11) 2 | #include 3 | 4 | void setup() { 5 | pinMode(3, OUTPUT); // настроить пин как выход 6 | pinMode(11, OUTPUT); // настроить пин как выход 7 | 8 | // из-за особенности генерации меандра таймером 9 | // частоту нужно указывать в два раза больше нужной! 10 | Timer2.setFrequency(15000 * 2); // настроить частоту в Гц и запустить таймер. Меандр на 15 кГц 11 | Timer2.outputEnable(CHANNEL_A, TOGGLE_PIN); // в момент срабатывания таймера пин будет переключаться 12 | Timer2.outputEnable(CHANNEL_B, TOGGLE_PIN); // в момент срабатывания таймера пин будет переключаться 13 | Timer2.outputState(CHANNEL_A, HIGH); // задаём начальное состояние пина 11 14 | Timer2.outputState(CHANNEL_B, LOW); // задаём начальное состояние пина 3 15 | } 16 | 17 | void loop() { 18 | } -------------------------------------------------------------------------------- /examples/meandr_test/meandr_test.ino: -------------------------------------------------------------------------------- 1 | //Пример генерации меандра на таймере 2 , канале B (D3 на Arduino UNO) 2 | #include 3 | 4 | void setup() { 5 | pinMode(3, OUTPUT); // настроить пин как выход 6 | 7 | // из-за особенности генерации меандра таймером 8 | // частоту нужно указывать в два раза больше нужной! 9 | Timer2.setFrequency(500 * 2); // настроить частоту таймера в Гц 10 | Timer2.outputEnable(CHANNEL_B, TOGGLE_PIN); // в момент срабатывания таймера пин будет переключаться 11 | } 12 | 13 | void loop() { 14 | } -------------------------------------------------------------------------------- /examples/simple/simple.ino: -------------------------------------------------------------------------------- 1 | // Пример простой генерации прерываний аппаратным таймером 2 | #include 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | Timer1.setFrequency(3); // Высокоточный таймер 1 для первого прерывания, частота - 3 Герца 7 | //Timer1.setPeriod(333333); // то же самое! Частота 3 Гц это период 333 333 микросекунд 8 | //Timer1.setFrequencyFloat(4.22); // Если нужна дробная частота в Гц 9 | Timer1.enableISR(); // Запускаем прерывание (по умолч. канал А) 10 | 11 | // запустим второй таймер 12 | Timer2.setPeriod(10000); // Устанавливаем период таймера 10000 мкс -> 100 гц 13 | Timer2.enableISR(CHANNEL_A); // Или просто .enableISR(), запускаем прерывание на канале А таймера 2 14 | pinMode(13, OUTPUT); // будем мигать 15 | } 16 | 17 | void loop() {} 18 | 19 | // Прерывание А таймера 1 20 | ISR(TIMER1_A) { // пишем в сериал 21 | Serial.println("timer1"); 22 | } 23 | 24 | // Прерывание А таймера 2 25 | ISR(TIMER2_A) { 26 | // мигаем 27 | digitalWrite(13, !digitalRead(13)); 28 | } 29 | -------------------------------------------------------------------------------- /examples/withoutInterrupts/withoutInterrupts.ino: -------------------------------------------------------------------------------- 1 | // Используем аппаратный таймер вместо софтверного millis()/micros() БЕЗ прерываний 2 | // Подойдет для быстрых событий с высокой точностью! 3 | 4 | #include 5 | 6 | void setup() { 7 | Serial.begin(9600); // Для примера откроем порт 8 | 9 | Timer1.setFrequency(3); // Задать частоту в целых числах 10 | // С этого момента таймер уже перенастроен и гоняет с выбранной частотой / периодом 11 | } 12 | 13 | void loop() { 14 | static uint32_t timer = millis(); 15 | if (millis() - timer >= 1000) { 16 | timer = millis(); 17 | Serial.println("Software timer!"); 18 | } 19 | 20 | if (Timer1.ready(CHANNEL_A)) { // Если прерывание канала А таймера 1 готово (но мы его не включили) 21 | Timer1.stop(); // Тормозим таймер (при желании) 22 | Serial.println("Hardware timer!"); 23 | Timer1.restart(); // Перезапускаем таймер (раз затормозили) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For GyverTimers 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | GyverTimers KEYWORD1 9 | 10 | Timer0 KEYWORD1 11 | Timer1 KEYWORD1 12 | Timer2 KEYWORD1 13 | Timer3 KEYWORD1 14 | Timer4 KEYWORD1 15 | Timer5 KEYWORD1 16 | 17 | ####################################### 18 | # Methods and Functions (KEYWORD2) 19 | ####################################### 20 | ISR KEYWORD2 21 | 22 | ready KEYWORD2 23 | setPeriod KEYWORD2 24 | setFrequency KEYWORD2 25 | setFrequencyFloat KEYWORD2 26 | enableISR KEYWORD2 27 | disableISR KEYWORD2 28 | pause KEYWORD2 29 | resume KEYWORD2 30 | stop KEYWORD2 31 | restart KEYWORD2 32 | setDefault KEYWORD2 33 | outputEnable KEYWORD2 34 | outputDisable KEYWORD2 35 | outputState KEYWORD2 36 | phaseShift KEYWORD2 37 | 38 | ####################################### 39 | # Constants (LITERAL1) 40 | ####################################### 41 | TIMER0_A LITERAL1 42 | TIMER0_B LITERAL1 43 | TIMER1_A LITERAL1 44 | TIMER1_B LITERAL1 45 | TIMER1_C LITERAL1 46 | TIMER2_A LITERAL1 47 | TIMER2_B LITERAL1 48 | TIMER3_A LITERAL1 49 | TIMER3_B LITERAL1 50 | TIMER3_C LITERAL1 51 | TIMER4_A LITERAL1 52 | TIMER4_B LITERAL1 53 | TIMER4_C LITERAL1 54 | TIMER5_A LITERAL1 55 | TIMER5_B LITERAL1 56 | TIMER5_C LITERAL1 57 | 58 | CHANNEL_A LITERAL1 59 | CHANNEL_B LITERAL1 60 | CHANNEL_C LITERAL1 61 | 62 | TOGGLE_PIN LITERAL1 63 | CLEAR_PIN LITERAL1 64 | SET_PIN LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GyverTimers 2 | version=1.10 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Library for control hardware timers on ATmega328p and ATmega2560 6 | paragraph=Library for control hardware timers on ATmega328p and ATmega2560 7 | category=Timing 8 | url=https://github.com/GyverLibs/GyverTimers 9 | architectures=avr -------------------------------------------------------------------------------- /src/GyverTimers.cpp: -------------------------------------------------------------------------------- 1 | #include "GyverTimers.h" 2 | 3 | // ========================== READY ========================== 4 | bool Timer_0::ready(uint8_t channel) { 5 | bool flag = false; 6 | switch (channel) { 7 | case CHANNEL_A: flag = bitRead(TIFR0, OCF0A); if (flag)bitSet(TIFR0, OCF0A); break; // Return interrupt flag + clear flag 8 | case CHANNEL_B: flag = bitRead(TIFR0, OCF0B); if (flag)bitSet(TIFR0, OCF0B); break; 9 | } 10 | return flag; 11 | } 12 | 13 | bool Timer_1::ready(uint8_t channel) { 14 | bool flag = false; 15 | switch (channel) { 16 | case CHANNEL_A: flag = bitRead(TIFR1, OCF1A); if (flag)bitSet(TIFR1, OCF1A); break; // Return interrupt flag + clear flag 17 | case CHANNEL_B: flag = bitRead(TIFR1, OCF1B); if (flag)bitSet(TIFR1, OCF1B); break; 18 | #if defined(__AVR_ATmega2560__) 19 | case CHANNEL_C: flag = bitRead(TIFR1, OCF1C); if (flag)bitSet(TIFR1, OCF1C); break; 20 | #endif 21 | } 22 | return flag; 23 | } 24 | 25 | bool Timer_2::ready(uint8_t channel) { 26 | bool flag = false; 27 | switch (channel) { 28 | case CHANNEL_A: flag = bitRead(TIFR2, OCF2A); if (flag)bitSet(TIFR2, OCF2A); break; // Return interrupt flag + clear flag 29 | case CHANNEL_B: flag = bitRead(TIFR2, OCF2B); if (flag)bitSet(TIFR2, OCF2B); break; 30 | } 31 | return flag; 32 | } 33 | 34 | #if defined(__AVR_ATmega2560__) 35 | bool Timer_3::ready(uint8_t channel) { 36 | bool flag = false; 37 | switch (channel) { 38 | case CHANNEL_A: flag = bitRead(TIFR3, OCF3A); if (flag)bitSet(TIFR3, OCF3A); break; // Return interrupt flag + clear flag 39 | case CHANNEL_B: flag = bitRead(TIFR3, OCF3B); if (flag)bitSet(TIFR3, OCF3B); break; 40 | case CHANNEL_C: flag = bitRead(TIFR3, OCF3C); if (flag)bitSet(TIFR3, OCF3C); break; 41 | } 42 | return flag; 43 | } 44 | 45 | bool Timer_4::ready(uint8_t channel) { 46 | bool flag = false; 47 | switch (channel) { 48 | case CHANNEL_A: flag = bitRead(TIFR4, OCF4A); if (flag)bitSet(TIFR4, OCF4A); break; // Return interrupt flag + clear flag 49 | case CHANNEL_B: flag = bitRead(TIFR4, OCF4B); if (flag)bitSet(TIFR4, OCF4B); break; 50 | case CHANNEL_C: flag = bitRead(TIFR4, OCF4C); if (flag)bitSet(TIFR4, OCF4C); break; 51 | } 52 | return flag; 53 | } 54 | 55 | bool Timer_5::ready(uint8_t channel) { 56 | bool flag = false; 57 | switch (channel) { 58 | case CHANNEL_A: flag = bitRead(TIFR5, OCF5A); if (flag)bitSet(TIFR5, OCF5A); break; // Return interrupt flag + clear flag 59 | case CHANNEL_B: flag = bitRead(TIFR5, OCF5B); if (flag)bitSet(TIFR5, OCF5B); break; 60 | case CHANNEL_C: flag = bitRead(TIFR5, OCF5C); if (flag)bitSet(TIFR5, OCF5C); break; 61 | } 62 | return flag; 63 | } 64 | #endif 65 | 66 | // ========================== OUTPUT STATE ========================== 67 | void Timer_0::outputState(uint8_t channel, bool state) { 68 | switch (channel) { 69 | case CHANNEL_A: TCCR0B = (TCCR0B & 0x7F) | (state << FOC0A); break; 70 | case CHANNEL_B: TCCR0B = (TCCR0B & 0xBF) | (state << FOC0B); break; 71 | } 72 | } 73 | 74 | void Timer_1::outputState(uint8_t channel, bool state) { 75 | switch (channel) { 76 | case CHANNEL_A: TCCR1C = (TCCR1C & 0x7F) | (state << FOC1A); break; 77 | case CHANNEL_B: TCCR1C = (TCCR1C & 0xBF) | (state << FOC1B); break; 78 | #if defined(__AVR_ATmega2560__) 79 | case CHANNEL_C: TCCR1C = (TCCR1C & 0xDF) | (state << FOC1C); break; 80 | #endif 81 | } 82 | } 83 | 84 | void Timer_2::outputState(uint8_t channel, bool state) { 85 | switch (channel) { 86 | case CHANNEL_A: TCCR2B = (TCCR2B & 0x7F) | (state << FOC2A); break; 87 | case CHANNEL_B: TCCR2B = (TCCR2B & 0xBF) | (state << FOC2B); break; 88 | } 89 | } 90 | 91 | #if defined(__AVR_ATmega2560__) 92 | void Timer_3::outputState(uint8_t channel, bool state) { 93 | switch (channel) { 94 | case CHANNEL_A: TCCR3C = (TCCR3C & 0x7F) | (state << FOC3A); break; 95 | case CHANNEL_B: TCCR3C = (TCCR3C & 0xBF) | (state << FOC3B); break; 96 | case CHANNEL_C: TCCR3C = (TCCR3C & 0xDF) | (state << FOC3C); break; 97 | } 98 | } 99 | 100 | void Timer_4::outputState(uint8_t channel, bool state) { 101 | switch (channel) { 102 | case CHANNEL_A: TCCR4C = (TCCR4C & 0x7F) | (state << FOC4A); break; 103 | case CHANNEL_B: TCCR4C = (TCCR4C & 0xBF) | (state << FOC4B); break; 104 | case CHANNEL_C: TCCR4C = (TCCR4C & 0xDF) | (state << FOC4C); break; 105 | } 106 | } 107 | 108 | void Timer_5::outputState(uint8_t channel, bool state) { 109 | switch (channel) { 110 | case CHANNEL_A: TCCR5C = (TCCR5C & 0x7F) | (state << FOC5A); break; 111 | case CHANNEL_B: TCCR5C = (TCCR5C & 0xBF) | (state << FOC5B); break; 112 | case CHANNEL_C: TCCR5C = (TCCR5C & 0xDF) | (state << FOC5C); break; 113 | } 114 | } 115 | #endif 116 | 117 | 118 | // ========================== PAUSE ========================== 119 | void Timer_0::pause(void) { 120 | TCCR0B = (TCCR0B & 0xF8); // Clear timer clock bits 121 | } 122 | 123 | void Timer_1::pause(void) { 124 | TCCR1B = (TCCR1B & 0xF8); 125 | } 126 | 127 | void Timer_2::pause(void) { 128 | TCCR2B = (TCCR2B & 0xF8); 129 | } 130 | 131 | #if defined(__AVR_ATmega2560__) 132 | 133 | void Timer_3::pause(void) { 134 | TCCR3B = (TCCR3B & 0xF8); 135 | } 136 | 137 | void Timer_4::pause(void) { 138 | TCCR4B = (TCCR4B & 0xF8); 139 | } 140 | 141 | void Timer_5::pause(void) { 142 | TCCR5B = (TCCR5B & 0xF8); 143 | } 144 | 145 | #endif 146 | 147 | // ========================== RESUME ========================== 148 | void Timer_0::resume(void) { 149 | TCCR0B = ((TCCR0B & 0xF8) | _timer0_clock); // Return clock timer settings 150 | } 151 | 152 | void Timer_1::resume(void) { 153 | TCCR1B = ((TCCR1B & 0xF8) | _timer1_clock); 154 | } 155 | 156 | void Timer_2::resume(void) { 157 | TCCR2B = ((TCCR2B & 0xF8) | _timer2_clock); 158 | } 159 | 160 | #if defined(__AVR_ATmega2560__) 161 | void Timer_3::resume(void) { 162 | TCCR3B = ((TCCR3B & 0xF8) | _timer3_clock); 163 | } 164 | 165 | void Timer_4::resume(void) { 166 | TCCR4B = ((TCCR4B & 0xF8) | _timer4_clock); 167 | } 168 | 169 | void Timer_5::resume(void) { 170 | TCCR5B = ((TCCR5B & 0xF8) | _timer5_clock); 171 | } 172 | #endif 173 | 174 | 175 | // ========================== STOP ========================== 176 | void Timer_0::stop(void) { 177 | Timer_0::pause(); 178 | TCNT0 = 0x00; // Clear timer counter 179 | } 180 | 181 | void Timer_1::stop(void) { 182 | Timer_1::pause(); 183 | TCNT1 = 0x00; 184 | } 185 | 186 | void Timer_2::stop(void) { 187 | Timer_2::pause(); 188 | TCNT2 = 0x00; 189 | } 190 | 191 | #if defined(__AVR_ATmega2560__) 192 | void Timer_3::stop(void) { 193 | Timer_3::pause(); 194 | TCNT3 = 0x00; 195 | } 196 | 197 | void Timer_4::stop(void) { 198 | Timer_4::pause(); 199 | TCNT4 = 0x00; 200 | } 201 | 202 | void Timer_5::stop(void) { 203 | Timer_5::pause(); 204 | TCNT5 = 0x00; 205 | } 206 | #endif 207 | 208 | 209 | // ========================== RESTART ========================== 210 | void Timer_0::restart(void) { 211 | Timer_0::resume(); 212 | TCNT0 = 0x00; 213 | } 214 | 215 | void Timer_1::restart(void) { 216 | Timer_1::resume(); 217 | TCNT1 = 0x00; 218 | } 219 | 220 | void Timer_2::restart(void) { 221 | Timer_2::resume(); 222 | TCNT2 = 0x00; 223 | } 224 | 225 | #if defined(__AVR_ATmega2560__) 226 | void Timer_3::restart(void) { 227 | Timer_3::resume(); 228 | TCNT3 = 0x00; 229 | } 230 | 231 | void Timer_4::restart(void) { 232 | Timer_4::resume(); 233 | TCNT4 = 0x00; 234 | } 235 | 236 | void Timer_5::restart(void) { 237 | Timer_5::resume(); 238 | TCNT5 = 0x00; 239 | } 240 | #endif 241 | 242 | 243 | // ========================== DISABLE ISR ========================== 244 | void Timer_0::disableISR(uint8_t source) { 245 | TIMSK0 &= ~ (source ? (1 << OCIE0B) : (1 << OCIE0A)); 246 | } 247 | 248 | void Timer_1::disableISR(uint8_t source) { 249 | switch (source) { 250 | case CHANNEL_A: TIMSK1 &= ~ (1 << OCIE1A); break; 251 | case CHANNEL_B: TIMSK1 &= ~ (1 << OCIE1B); break; 252 | #if defined(__AVR_ATmega2560__) 253 | case CHANNEL_C: TIMSK1 &= ~ (1 << OCIE1C); break; 254 | #endif 255 | } 256 | } 257 | 258 | void Timer_2::disableISR(uint8_t source) { 259 | TIMSK2 &= ~ (source ? (1 << OCIE2B) : (1 << OCIE2A)); 260 | } 261 | 262 | #if defined(__AVR_ATmega2560__) 263 | void Timer_3::disableISR(uint8_t source) { 264 | switch (source) { 265 | case CHANNEL_A: TIMSK3 &= ~ (1 << OCIE3A); break; 266 | case CHANNEL_B: TIMSK3 &= ~ (1 << OCIE3B); break; 267 | case CHANNEL_C: TIMSK3 &= ~ (1 << OCIE3C); break; 268 | } 269 | } 270 | 271 | void Timer_4::disableISR(uint8_t source) { 272 | switch (source) { 273 | case CHANNEL_A: TIMSK4 &= ~ (1 << OCIE4A); break; 274 | case CHANNEL_B: TIMSK4 &= ~ (1 << OCIE4B); break; 275 | case CHANNEL_C: TIMSK4 &= ~ (1 << OCIE4C); break; 276 | } 277 | } 278 | 279 | void Timer_5::disableISR(uint8_t source) { 280 | switch (source) { 281 | case CHANNEL_A: TIMSK5 &= ~ (1 << OCIE5A); break; 282 | case CHANNEL_B: TIMSK5 &= ~ (1 << OCIE5B); break; 283 | case CHANNEL_C: TIMSK5 &= ~ (1 << OCIE5C); break; 284 | } 285 | } 286 | #endif 287 | 288 | // ========================== DEFAULT ========================== 289 | void Timer_0::setDefault(void) { 290 | TCCR0A = 0x03; // Fast PWM , 8 bit 291 | TCCR0B = 0x03; // Prescaler /64 292 | OCR0B = 0x00; // Clear COMPA 293 | OCR0A = 0x00; // Clear COMPB 294 | TCNT0 = 0x00; // Clear counter 295 | } 296 | 297 | void Timer_1::setDefault(void) { 298 | TCCR1A = 0x01; // Phasecorrect PWM , 8 bit 299 | TCCR1B = 0x0B; // Prescaler /64 300 | OCR1B = 0x00; // Clear COMPA 301 | OCR1A = 0x00; // Clear COMPB 302 | TCNT1 = 0x00; // Clear counter 303 | } 304 | 305 | void Timer_2::setDefault(void) { 306 | TCCR2A = 0x01; // Phasecorrect PWM , 8 bit 307 | TCCR2B = 0x04; // Prescaler /64 308 | OCR2B = 0x00; // Clear COMPA 309 | OCR2A = 0x00; // Clear COMPB 310 | TCNT2 = 0x00; // Clear counter 311 | } 312 | 313 | 314 | #if defined(__AVR_ATmega2560__) 315 | void Timer_3::setDefault(void) { 316 | TCCR3A = 0x01; // Phasecorrect PWM , 8 bit 317 | TCCR3B = 0x0B; // Prescaler /64 318 | OCR3B = 0x00; // Clear COMPA 319 | OCR3A = 0x00; // Clear COMPB 320 | TCNT3 = 0x00; // Clear counter 321 | } 322 | 323 | void Timer_4::setDefault(void) { 324 | TCCR4A = 0x01; // Phasecorrect PWM , 8 bit 325 | TCCR4B = 0x0B; // Prescaler /64 326 | OCR4B = 0x00; // Clear COMPA 327 | OCR4A = 0x00; // Clear COMPB 328 | TCNT4 = 0x00; // Clear counter 329 | } 330 | 331 | void Timer_5::setDefault(void) { 332 | TCCR5A = 0x01; // Phasecorrect PWM , 8 bit 333 | TCCR5B = 0x0B; // Prescaler /64 334 | OCR5B = 0x00; // Clear COMPA 335 | OCR5A = 0x00; // Clear COMPB 336 | TCNT5 = 0x00; // Clear counter 337 | } 338 | #endif 339 | 340 | // ========================== PHASE SHIFT ========================== 341 | void Timer_0::phaseShift(uint8_t source, uint16_t phase) { 342 | if (source) OCR0B = map(phase, 0, 360, 0, OCR0A); 343 | } 344 | 345 | void Timer_1::phaseShift(uint8_t source, uint16_t phase) { 346 | switch (source) { 347 | case CHANNEL_A: OCR1A = map(phase, 0, 360, 0, ICR1); break; 348 | case CHANNEL_B: OCR1B = map(phase, 0, 360, 0, ICR1); break; 349 | #if defined(__AVR_ATmega2560__) 350 | case CHANNEL_C: OCR1C = map(phase, 0, 360, 0, ICR1); break; 351 | #endif 352 | } 353 | } 354 | 355 | void Timer_2::phaseShift(uint8_t source, uint16_t phase) { 356 | if (source) OCR2B = map(phase, 0, 360, 0, OCR2A); 357 | } 358 | 359 | #if defined(__AVR_ATmega2560__) 360 | 361 | void Timer_3::phaseShift(uint8_t source, uint16_t phase) { 362 | switch (source) { 363 | case CHANNEL_A: OCR3A = map(phase, 0, 360, 0, ICR3); break; 364 | case CHANNEL_B: OCR3B = map(phase, 0, 360, 0, ICR3); break; 365 | case CHANNEL_C: OCR3C = map(phase, 0, 360, 0, ICR3); break; 366 | } 367 | } 368 | 369 | void Timer_4::phaseShift(uint8_t source, uint16_t phase) { 370 | switch (source) { 371 | case CHANNEL_A: OCR4A = map(phase, 0, 360, 0, ICR4); break; 372 | case CHANNEL_B: OCR4B = map(phase, 0, 360, 0, ICR4); break; 373 | case CHANNEL_C: OCR4C = map(phase, 0, 360, 0, ICR4); break; 374 | } 375 | } 376 | 377 | void Timer_5::phaseShift(uint8_t source, uint16_t phase) { 378 | switch (source) { 379 | case CHANNEL_A: OCR5A = map(phase, 0, 360, 0, ICR5); break; 380 | case CHANNEL_B: OCR5B = map(phase, 0, 360, 0, ICR5); break; 381 | case CHANNEL_C: OCR5C = map(phase, 0, 360, 0, ICR5); break; 382 | } 383 | } 384 | #endif 385 | 386 | 387 | // ========================== ENABLE ISR ========================== 388 | void Timer_0::enableISR(uint8_t source) { 389 | if (!source) TIMSK0 |= (1 << OCIE0A); 390 | else TIMSK0 |= (1 << OCIE0B); 391 | } 392 | 393 | void Timer_1::enableISR(uint8_t source) { 394 | switch (source) { 395 | case CHANNEL_A: TIMSK1 |= (1 << OCIE1A); break; 396 | case CHANNEL_B: TIMSK1 |= (1 << OCIE1B); break; 397 | #if defined(__AVR_ATmega2560__) 398 | case CHANNEL_C: TIMSK1 |= (1 << OCIE1C); break; 399 | #endif 400 | } 401 | } 402 | 403 | void Timer_2::enableISR(uint8_t source) { 404 | if (!source) TIMSK2 |= (1 << OCIE2A); 405 | else TIMSK2 |= (1 << OCIE2B); 406 | } 407 | 408 | #if defined(__AVR_ATmega2560__) 409 | 410 | void Timer_3::enableISR(uint8_t source) { 411 | switch (source) { 412 | case CHANNEL_A: TIMSK3 |= (1 << OCIE3A); break; 413 | case CHANNEL_B: TIMSK3 |= (1 << OCIE3B); break; 414 | case CHANNEL_C: TIMSK3 |= (1 << OCIE3C); break; 415 | } 416 | } 417 | 418 | void Timer_4::enableISR(uint8_t source) { 419 | switch (source) { 420 | case CHANNEL_A: TIMSK4 |= (1 << OCIE4A); break; 421 | case CHANNEL_B: TIMSK4 |= (1 << OCIE4B); break; 422 | case CHANNEL_C: TIMSK4 |= (1 << OCIE4C); break; 423 | } 424 | } 425 | 426 | void Timer_5::enableISR(uint8_t source) { 427 | switch (source) { 428 | case CHANNEL_A: TIMSK5 |= (1 << OCIE5A); break; 429 | case CHANNEL_B: TIMSK5 |= (1 << OCIE5B); break; 430 | case CHANNEL_C: TIMSK5 |= (1 << OCIE5C); break; 431 | } 432 | } 433 | #endif 434 | 435 | // ========================== SET FREQUENCY ========================== 436 | uint32_t Timer_0::setFrequency(uint32_t _timer0_frequency) { 437 | return 1000000UL / (Timer_0::setPeriod(1000000UL / _timer0_frequency)); 438 | } 439 | 440 | uint32_t Timer_1::setFrequency(uint32_t _timer1_frequency) { 441 | return 1000000UL / (Timer_1::setPeriod(1000000UL / _timer1_frequency)); 442 | } 443 | 444 | uint32_t Timer_2::setFrequency(uint32_t _timer2_frequency) { 445 | return 1000000UL / (Timer_2::setPeriod(1000000UL / _timer2_frequency)); 446 | } 447 | 448 | #if defined(__AVR_ATmega2560__) 449 | 450 | uint32_t Timer_3::setFrequency(uint32_t _timer3_frequency) { 451 | return 1000000UL / (Timer_3::setPeriod(1000000UL / _timer3_frequency)); 452 | } 453 | 454 | uint32_t Timer_4::setFrequency(uint32_t _timer4_frequency) { 455 | return 1000000UL / (Timer_4::setPeriod(1000000UL / _timer4_frequency)); 456 | } 457 | 458 | uint32_t Timer_5::setFrequency(uint32_t _timer5_frequency) { 459 | return 1000000UL / (Timer_5::setPeriod(1000000UL / _timer5_frequency)); 460 | } 461 | 462 | #endif 463 | 464 | 465 | // ========================== SET FREQUENCY FLOAT ========================== 466 | float Timer_0::setFrequencyFloat(float _timer0_frequency) { 467 | return 1000000.0F / (Timer_0::setPeriod(1000000.0F / _timer0_frequency)); 468 | } 469 | 470 | float Timer_1::setFrequencyFloat(float _timer1_frequency) { 471 | return 1000000.0F / (Timer_1::setPeriod(1000000.0F / _timer1_frequency)); 472 | } 473 | 474 | float Timer_2::setFrequencyFloat(float _timer2_frequency) { 475 | return 1000000.0F / (Timer_2::setPeriod(1000000.0F / _timer2_frequency)); 476 | } 477 | 478 | #if defined(__AVR_ATmega2560__) 479 | 480 | float Timer_3::setFrequencyFloat(float _timer3_frequency) { 481 | return 1000000.0F / (Timer_3::setPeriod(1000000.0F / _timer3_frequency)); 482 | } 483 | 484 | float Timer_4::setFrequencyFloat(float _timer4_frequency) { 485 | return 1000000.0F / (Timer_4::setPeriod(1000000.0F / _timer4_frequency)); 486 | } 487 | 488 | float Timer_5::setFrequencyFloat(float _timer5_frequency) { 489 | return 1000000.0F / (Timer_5::setPeriod(1000000.0F / _timer5_frequency)); 490 | } 491 | 492 | #endif 493 | 494 | // ========================== OUTPUT ENABLE ========================== 495 | void Timer_0::outputEnable(uint8_t channel, uint8_t mode) { 496 | switch (channel) { 497 | case CHANNEL_A: TCCR0A = (TCCR0A & 0x3F) | (mode << 6); break; 498 | case CHANNEL_B: TCCR0A = (TCCR0A & 0xCF) | (mode << 4); break; 499 | } 500 | } 501 | 502 | void Timer_1::outputEnable(uint8_t channel, uint8_t mode) { 503 | switch (channel) { 504 | case CHANNEL_A: TCCR1A = (TCCR1A & 0x3F) | (mode << 6); break; 505 | case CHANNEL_B: TCCR1A = (TCCR1A & 0xCF) | (mode << 4); break; 506 | #if defined(__AVR_ATmega2560__) 507 | case CHANNEL_C: TCCR1A = (TCCR1A & 0xF3) | (mode << 2); break; 508 | #endif 509 | } 510 | } 511 | 512 | void Timer_2::outputEnable(uint8_t channel, uint8_t mode) { 513 | switch (channel) { 514 | case CHANNEL_A: TCCR2A = (TCCR2A & 0x3F) | (mode << 6); break; 515 | case CHANNEL_B: TCCR2A = (TCCR2A & 0xCF) | (mode << 4); break; 516 | } 517 | } 518 | 519 | #if defined(__AVR_ATmega2560__) 520 | void Timer_3::outputEnable(uint8_t channel, uint8_t mode) { 521 | switch (channel) { 522 | case CHANNEL_A: TCCR3A = (TCCR3A & 0x3F) | (mode << 6); break; 523 | case CHANNEL_B: TCCR3A = (TCCR3A & 0xCF) | (mode << 4); break; 524 | case CHANNEL_C: TCCR3A = (TCCR3A & 0xF3) | (mode << 2); break; 525 | } 526 | } 527 | 528 | void Timer_4::outputEnable(uint8_t channel, uint8_t mode) { 529 | switch (channel) { 530 | case CHANNEL_A: TCCR4A = (TCCR4A & 0x3F) | (mode << 6); break; 531 | case CHANNEL_B: TCCR4A = (TCCR4A & 0xCF) | (mode << 4); break; 532 | case CHANNEL_C: TCCR4A = (TCCR4A & 0xF3) | (mode << 2); break; 533 | } 534 | } 535 | 536 | void Timer_5::outputEnable(uint8_t channel, uint8_t mode) { 537 | switch (channel) { 538 | case CHANNEL_A: TCCR5A = (TCCR5A & 0x3F) | (mode << 6); break; 539 | case CHANNEL_B: TCCR5A = (TCCR5A & 0xCF) | (mode << 4); break; 540 | case CHANNEL_C: TCCR5A = (TCCR5A & 0xF3) | (mode << 2); break; 541 | } 542 | } 543 | #endif 544 | 545 | 546 | // ========================== OUTPUT DISABLE ========================== 547 | void Timer_0::outputDisable(uint8_t channel) { 548 | switch (channel) { 549 | case CHANNEL_A: TCCR0A = (TCCR0A & 0x3F); break; 550 | case CHANNEL_B: TCCR0A = (TCCR0A & 0xCF); break; 551 | } 552 | } 553 | 554 | void Timer_1::outputDisable(uint8_t channel) { 555 | switch (channel) { 556 | case CHANNEL_A: TCCR1A = (TCCR1A & 0x3F); break; 557 | case CHANNEL_B: TCCR1A = (TCCR1A & 0xCF); break; 558 | #if defined(__AVR_ATmega2560__) 559 | case CHANNEL_C: TCCR1A = (TCCR1A & 0xF3); break; 560 | #endif 561 | } 562 | } 563 | 564 | void Timer_2::outputDisable(uint8_t channel) { 565 | switch (channel) { 566 | case CHANNEL_A: TCCR2A = (TCCR2A & 0x3F); break; 567 | case CHANNEL_B: TCCR2A = (TCCR2A & 0xCF); break; 568 | } 569 | } 570 | 571 | #if defined(__AVR_ATmega2560__) 572 | void Timer_3::outputDisable(uint8_t channel) { 573 | switch (channel) { 574 | case CHANNEL_A: TCCR3A = (TCCR3A & 0x3F); break; 575 | case CHANNEL_B: TCCR3A = (TCCR3A & 0xCF); break; 576 | case CHANNEL_C: TCCR3A = (TCCR3A & 0xF3); break; 577 | } 578 | } 579 | 580 | void Timer_4::outputDisable(uint8_t channel) { 581 | switch (channel) { 582 | case CHANNEL_A: TCCR4A = (TCCR4A & 0x3F); break; 583 | case CHANNEL_B: TCCR4A = (TCCR4A & 0xCF); break; 584 | case CHANNEL_C: TCCR4A = (TCCR4A & 0xF3); break; 585 | } 586 | } 587 | 588 | void Timer_5::outputDisable(uint8_t channel) { 589 | switch (channel) { 590 | case CHANNEL_A: TCCR5A = (TCCR5A & 0x3F); break; 591 | case CHANNEL_B: TCCR5A = (TCCR5A & 0xCF); break; 592 | case CHANNEL_C: TCCR5A = (TCCR5A & 0xF3); break; 593 | } 594 | } 595 | #endif 596 | 597 | 598 | 599 | // ========================== SET PERIOD ========================== 600 | uint32_t Timer_0::setPeriod(uint32_t _timer0_period) { 601 | _timer0_period = constrain(_timer0_period, 1, MAX_PERIOD_8); 602 | 603 | uint32_t _timer0_cycles = F_CPU / 1000000 * _timer0_period; // Calculation of the number of timer cycles per period 604 | uint8_t _timer0_prescaler = 0x00; 605 | uint16_t _timer0_divider = 0x00; 606 | 607 | if (_timer0_cycles < 256UL) { // Сhoose optimal divider for the timer 608 | _timer0_prescaler = 0x01; 609 | _timer0_divider = 1UL; 610 | } else if (_timer0_cycles < 256UL * 8) { 611 | _timer0_prescaler = 0x02; 612 | _timer0_divider = 8UL; 613 | } else if (_timer0_cycles < 256UL * 64) { 614 | _timer0_prescaler = 0x03; 615 | _timer0_divider = 64UL; 616 | } else if (_timer0_cycles < 256UL * 256) { 617 | _timer0_prescaler = 0x04; 618 | _timer0_divider = 256UL; 619 | } else { 620 | _timer0_prescaler = 0x05; 621 | _timer0_divider = 1024UL; 622 | } 623 | 624 | uint8_t _timer0_top = (_timer0_cycles < 256UL * 1024 ? (_timer0_cycles / _timer0_divider) : 256UL) ; 625 | 626 | TCCR0A = (TCCR0A & 0xF0) | (1 << WGM21); // CTC - mode 627 | TCCR0B = _timer0_prescaler; // Set timer prescaler 628 | OCR0A = _timer0_top - 1; // Set timer top 629 | _timer0_clock = (TCCR0B & 0x07); // Save timer clock settings 630 | 631 | return (1000000UL / ((F_CPU / _timer0_divider) / _timer0_top)); // Return real timer period 632 | } 633 | 634 | uint32_t Timer_1::setPeriod(uint32_t _timer1_period) { 635 | _timer1_period = constrain(_timer1_period, 1, MAX_PERIOD_16); 636 | 637 | uint32_t _timer1_cycles = F_CPU / 1000000 * _timer1_period; // Calculation of the number of timer cycles per period 638 | uint8_t _timer1_prescaler = 0x00; 639 | uint16_t _timer1_divider = 0x00; 640 | 641 | if (_timer1_cycles < 65536UL) { // Сhoose optimal divider for the timer 642 | _timer1_prescaler = 0x01; 643 | _timer1_divider = 1UL; 644 | } else if (_timer1_cycles < 65536UL * 8) { 645 | _timer1_prescaler = 0x02; 646 | _timer1_divider = 8UL; 647 | } else if (_timer1_cycles < 65536UL * 64) { 648 | _timer1_prescaler = 0x03; 649 | _timer1_divider = 64UL; 650 | } else if (_timer1_cycles < 65536UL * 256) { 651 | _timer1_prescaler = 0x04; 652 | _timer1_divider = 256UL; 653 | } else { 654 | _timer1_prescaler = 0x05; 655 | _timer1_divider = 1024UL; 656 | } 657 | 658 | uint16_t _timer1_top = (_timer1_cycles < 65536UL * 1024 ? (_timer1_cycles / _timer1_divider) : 65536UL) ; 659 | #if defined(__AVR_ATmega2560__) 660 | TCCR1A = (TCCR1A & 0xFC); 661 | #else 662 | TCCR1A = (TCCR1A & 0xF0); 663 | #endif 664 | TCCR1B = ((1 << WGM13) | (1 << WGM12) | _timer1_prescaler); // CTC mode + set prescaler 665 | ICR1 = _timer1_top - 1; // Set timer top 666 | _timer1_clock = (TCCR1B & 0x07); // Save timer clock settings 667 | return (1000000UL / ((F_CPU / _timer1_divider) / _timer1_top)); // Return real timer period 668 | } 669 | 670 | uint32_t Timer_2::setPeriod(uint32_t _timer2_period) { 671 | _timer2_period = constrain(_timer2_period, 1, MAX_PERIOD_8); 672 | 673 | uint32_t _timer2_cycles = F_CPU / 1000000 * _timer2_period; // Calculation of the number of timer cycles per period 674 | uint8_t _timer2_prescaler = 0x00; 675 | uint16_t _timer2_divider = 0x00; 676 | 677 | if (_timer2_cycles < 256UL) { // Сhoose optimal divider for the timer 678 | _timer2_prescaler = 0x01; 679 | _timer2_divider = 1UL; 680 | } else if (_timer2_cycles < 256UL * 8) { 681 | _timer2_prescaler = 0x02; 682 | _timer2_divider = 8UL; 683 | } else if (_timer2_cycles < 256UL * 32) { 684 | _timer2_prescaler = 0x03; 685 | _timer2_divider = 32UL; 686 | } else if (_timer2_cycles < 256UL * 64) { 687 | _timer2_prescaler = 0x04; 688 | _timer2_divider = 64UL; 689 | } else if (_timer2_cycles < 256UL * 128) { 690 | _timer2_prescaler = 0x05; 691 | _timer2_divider = 128UL; 692 | } else if (_timer2_cycles < 256UL * 256) { 693 | _timer2_prescaler = 0x06; 694 | _timer2_divider = 256UL; 695 | } else { 696 | _timer2_prescaler = 0x07; 697 | _timer2_divider = 1024UL; 698 | } 699 | 700 | uint8_t _timer2_top = (_timer2_cycles < 256UL * 1024 ? (_timer2_cycles / _timer2_divider) : 256UL); 701 | 702 | TCCR2A = (TCCR2A & 0xF0) | (1 << WGM21); // CTC - mode 703 | TCCR2B = _timer2_prescaler; // Set timer prescaler 704 | OCR2A = _timer2_top - 1; // Set timer top 705 | _timer2_clock = (TCCR2B & 0x07); // Save timer clock settings 706 | 707 | return (1000000UL / ((F_CPU / _timer2_divider) / _timer2_top)); // Return real timer period 708 | } 709 | 710 | #if defined(__AVR_ATmega2560__) 711 | 712 | uint32_t Timer_3::setPeriod(uint32_t _timer3_period) { 713 | _timer3_period = constrain(_timer3_period, 1, MAX_PERIOD_16); 714 | 715 | uint32_t _timer3_cycles = F_CPU / 1000000 * _timer3_period; // Calculation of the number of timer cycles per period 716 | uint8_t _timer3_prescaler = 0x00; 717 | uint16_t _timer3_divider = 0x00; 718 | 719 | if (_timer3_cycles < 65536UL) { // Сhoose optimal divider for the timer 720 | _timer3_prescaler = 0x01; 721 | _timer3_divider = 1UL; 722 | } else if (_timer3_cycles < 65536UL * 8) { 723 | _timer3_prescaler = 0x02; 724 | _timer3_divider = 8UL; 725 | } else if (_timer3_cycles < 65536UL * 64) { 726 | _timer3_prescaler = 0x03; 727 | _timer3_divider = 64UL; 728 | } else if (_timer3_cycles < 65536UL * 256) { 729 | _timer3_prescaler = 0x04; 730 | _timer3_divider = 256UL; 731 | } else { 732 | _timer3_prescaler = 0x05; 733 | _timer3_divider = 1024UL; 734 | } 735 | 736 | uint16_t _timer3_top = (_timer3_cycles < 65536UL * 1024 ? (_timer3_cycles / _timer3_divider) : 65536UL) ; 737 | 738 | TCCR3A = (TCCR3A & 0xFC); 739 | TCCR3B = ((1 << WGM33) | (1 << WGM32) | _timer3_prescaler); // CTC mode + set prescaler 740 | ICR3 = _timer3_top - 1; // Set timer top 741 | _timer3_clock = (TCCR3B & 0x07); // Save timer clock settings 742 | 743 | return (1000000UL / ((F_CPU / _timer3_divider) / _timer3_top)); // Return real timer period 744 | } 745 | 746 | uint32_t Timer_4::setPeriod(uint32_t _timer4_period) { 747 | _timer4_period = constrain(_timer4_period, 1, MAX_PERIOD_16); 748 | 749 | uint32_t _timer4_cycles = F_CPU / 1000000 * _timer4_period; // Calculation of the number of timer cycles per period 750 | uint8_t _timer4_prescaler = 0x00; 751 | uint16_t _timer4_divider = 0x00; 752 | 753 | if (_timer4_cycles < 65536UL) { // Сhoose optimal divider for the timer 754 | _timer4_prescaler = 0x01; 755 | _timer4_divider = 1UL; 756 | } else if (_timer4_cycles < 65536UL * 8) { 757 | _timer4_prescaler = 0x02; 758 | _timer4_divider = 8UL; 759 | } else if (_timer4_cycles < 65536UL * 64) { 760 | _timer4_prescaler = 0x03; 761 | _timer4_divider = 64UL; 762 | } else if (_timer4_cycles < 65536UL * 256) { 763 | _timer4_prescaler = 0x04; 764 | _timer4_divider = 256UL; 765 | } else { 766 | _timer4_prescaler = 0x05; 767 | _timer4_divider = 1024UL; 768 | } 769 | 770 | uint16_t _timer4_top = (_timer4_cycles < 65536UL * 1024 ? (_timer4_cycles / _timer4_divider) : 65536UL) ; 771 | 772 | TCCR4A = (TCCR4A & 0xFC); 773 | TCCR4B = ((1 << WGM43) | (1 << WGM42) | _timer4_prescaler); // CTC mode + set prescaler 774 | ICR4 = _timer4_top - 1; // Set timer top 775 | _timer4_clock = (TCCR4B & 0x07); // Save timer clock settings 776 | 777 | return (1000000UL / ((F_CPU / _timer4_divider) / _timer4_top)); // Return real timer period 778 | } 779 | 780 | uint32_t Timer_5::setPeriod(uint32_t _timer5_period) { 781 | _timer5_period = constrain(_timer5_period, 1, MAX_PERIOD_16); 782 | 783 | uint32_t _timer5_cycles = F_CPU / 1000000 * _timer5_period; // Calculation of the number of timer cycles per period 784 | uint8_t _timer5_prescaler = 0x00; 785 | uint16_t _timer5_divider = 0x00; 786 | 787 | if (_timer5_cycles < 65536UL) { // Сhoose optimal divider for the timer 788 | _timer5_prescaler = 0x01; 789 | _timer5_divider = 1UL; 790 | } else if (_timer5_cycles < 65536UL * 8) { 791 | _timer5_prescaler = 0x02; 792 | _timer5_divider = 8UL; 793 | } else if (_timer5_cycles < 65536UL * 64) { 794 | _timer5_prescaler = 0x03; 795 | _timer5_divider = 64UL; 796 | } else if (_timer5_cycles < 65536UL * 256) { 797 | _timer5_prescaler = 0x04; 798 | _timer5_divider = 256UL; 799 | } else { 800 | _timer5_prescaler = 0x05; 801 | _timer5_divider = 1024UL; 802 | } 803 | 804 | uint16_t _timer5_top = (_timer5_cycles < 65536UL * 1024 ? (_timer5_cycles / _timer5_divider) : 65536UL) ; 805 | 806 | TCCR5A = (TCCR5A & 0xFC); 807 | TCCR5B = ((1 << WGM53) | (1 << WGM52) | _timer5_prescaler); // CTC mode + set prescaler 808 | ICR5 = _timer5_top - 1; // Set timer top 809 | _timer5_clock = (TCCR5B & 0x07); // Save timer clock settings 810 | 811 | return (1000000UL / ((F_CPU / _timer5_divider) / _timer5_top)); // Return real timer period 812 | } 813 | 814 | #endif 815 | 816 | 817 | Timer_0 Timer0 = Timer_0(); 818 | Timer_1 Timer1 = Timer_1(); 819 | Timer_2 Timer2 = Timer_2(); 820 | 821 | #if defined(__AVR_ATmega2560__) 822 | Timer_3 Timer3 = Timer_3(); 823 | Timer_4 Timer4 = Timer_4(); 824 | Timer_5 Timer5 = Timer_5(); 825 | #endif -------------------------------------------------------------------------------- /src/GyverTimers.h: -------------------------------------------------------------------------------- 1 | /* 2 | Настройка и контроль прерываний по аппаратным таймерам ATmega328p, ATmega2560 3 | Документация: https://alexgyver.ru/gyvertimers/ 4 | GitHub: https://github.com/GyverLibs/GyverTimers 5 | Возможности: 6 | - Поддерживаются все три таймера на ATmega328 и шесть таймеров на ATmega2560; 7 | - Настройка периода (мкс) и частоты (Гц) прерываний: 8 | - 8 бит таймеры: 61 Гц - 1 МГц (16 384 мкс.. 1 мкс); 9 | - 16 бит таймеры: 0.24 Гц - 1 МГц (4 200 000 мкс.. 1 мкс); 10 | - Автоматическая корректировка настройки периода от частоты тактирования (F_CPU); 11 | - Функция возвращает точный установившийся период/частоту для отладки (частота ограничена разрешением таймера); 12 | - Поддержка многоканального режима работы: один таймер вызывает 2 (ATmega328) или 13 | 3 (ATmega2560, таймеры 1, 3, 4, 5) прерывания с настраиваемым сдвигом по фазе 0-360 градусов; 14 | - Настраиваемое действие аппаратного вывода таймера по прерыванию: высокий сигнал, низкий сигнал, переключение. 15 | Позволяет генерировать меандр (одно- и двухтактный); 16 | - Контроль работы таймера: старт/стоп/пауза/продолжить/инициализация; 17 | 18 | Egor 'Nich1con' Zaharov for AlexGyver, alex@alexgyver.ru 19 | https://alexgyver.ru/ 20 | MIT License 21 | 22 | Версии: 23 | v1.1 - исправлена ошибка в расчёте периодов 24 | v1.2 - код разбит на h и cpp 25 | v1.3 - поправлен незначительный баг 26 | v1.4 - исправлена таблица частот и периодов 27 | v1.5 - исправлен restart и resume 28 | v1.6 - phase shift вынесен отдельным методом 29 | v1.7 - поправлена документация 30 | v1.8 - исправлен баг с макс периодом 31 | v1.9 - исправлен баг с возвращаемым 2х периодом 32 | v1.10 - добавлен флаг ready 33 | */ 34 | 35 | /* 36 | -------------------------------- Arduino NANO 16 МГц (ATmega328) ------------------------------------ 37 | Таймер | Разрядность | Частоты | Периоды | Выходы | Пин Arduino | Пин МК| 38 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 39 | Timer0 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | D6 | PD6 | 40 | | | | | CHANNEL_B | D5 | PD5 | 41 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 42 | Timer1 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | D9 | PB1 | 43 | | | | | CHANNEL_B | D10 | PB2 | 44 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 45 | Timer2 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | D11 | PB3 | 46 | | | | | CHANNEL_B | D3 | PD3 | 47 | ---------------------------------------------------------------------------------------------------- 48 | 49 | ------------------------------ Arduino MEGA 16 МГц (ATmega2560) ------------------------------------- 50 | Таймер | Разрядность | Частоты | Периоды | Выходы | Пин Arduino | Пин МК| 51 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 52 | Timer0 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | 13 | PB7 | 53 | | | | | CHANNEL_B | 4 | PG5 | 54 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 55 | Timer1 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 11 | PB5 | 56 | | | | | CHANNEL_B | 12 | PB6 | 57 | | | | | CHANNEL_C | 13 | PB7 | 58 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 59 | Timer2 | 8 бит | 61 Гц - 1 МГц | 16 384.. 1 мкс | CHANNEL_A | 10 | PB4 | 60 | | | | | CHANNEL_B | 9 | PH6 | 61 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 62 | Timer3 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 5 | PE3 | 63 | | | | | CHANNEL_B | 2 | PE4 | 64 | | | | | CHANNEL_C | 3 | PE5 | 65 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 66 | Timer4 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 6 | PH3 | 67 | | | | | CHANNEL_B | 7 | PH4 | 68 | | | | | CHANNEL_C | 8 | PH5 | 69 | --------|---------------|-------------------|-------------------|-----------|---------------|-------| 70 | Timer5 | 16 бит | 0.24 Гц - 1 МГц | 4 200 000.. 1 мкс | CHANNEL_A | 46 | PL3 | 71 | | | | | CHANNEL_B | 45 | PL4 | 72 | | | | | CHANNEL_C | 44 | PL5 | 73 | ---------------------------------------------------------------------------------------------------- 74 | */ 75 | 76 | /* 77 | setPeriod(период) - установка периода в микросекундах и запуск таймера. Возвращает реальный период (точность ограничена разрешением таймера). 78 | setFrequency(частота) - установка частоты в Герцах и запуск таймера. Возвращает реальную частоту (точность ограничена разрешением таймера). 79 | setFrequencyFloat(частота float) - установка частоты в Герцах и запуск таймера, разрешены десятичные дроби. Возвращает реальную частоту (точность ограничена разрешением таймера). 80 | enableISR(источник) - включить прерывания, канал прерываний CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560) 81 | disableISR(источник) - выключить прерывания, канал CHANNEL_A или CHANNEL_B. Счёт таймера не останавливается (без указания параметров будет выключен канал А). 82 | pause() - приостановить счёт таймера, не сбрасывая счётчик 83 | resume() - продолжить счёт после паузы 84 | stop() - остановить счёт и сбросить счётчик 85 | restart() - перезапустить таймер (сбросить счётчик) 86 | setDefault() - установить параметры таймера по умолчанию ("Ардуино-умолчания") 87 | outputEnable(канал, режим) - канал: включить выход таймера CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560). Режим: TOGGLE_PIN, CLEAR_PIN, SET_PIN (переключить/выключить/включить пин по прерыванию) 88 | outputDisable(канал) - отключить выход таймера CHANNEL_A или CHANNEL_B (+ CHANNEL_C у Mega2560, см. такблицу таймеров) 89 | outputState(канал, состояние) - сменить состояние канала: HIGH / LOW 90 | phaseShift(источник, фаза) - сдвинуть фазу канала на 0-360 градусов (у 8 бит таймеров двигается только канал B) 91 | */ 92 | 93 | #define MAX_PERIOD_8 (1000000UL * 1024UL / F_CPU * 256UL) // 16384 (61 Гц) на 16 МГц 94 | #define MAX_PERIOD_16 (1000000UL * 1024UL / F_CPU * 65536UL) // 4194304 (0.24 Гц) на 16 МГц 95 | 96 | #ifndef GyverTimers_h 97 | #define GyverTimers_h 98 | #include 99 | 100 | /* ========== Константы ========== */ 101 | #define CHANNEL_A 0x00 102 | #define CHANNEL_B 0x01 103 | #define CHANNEL_C 0x02 104 | 105 | #define TOGGLE_PIN 0x01 106 | #define CLEAR_PIN 0x02 107 | #define SET_PIN 0x03 108 | 109 | #define TIMER0_A TIMER0_COMPA_vect 110 | #define TIMER0_B TIMER0_COMPB_vect 111 | #define TIMER1_A TIMER1_COMPA_vect 112 | #define TIMER1_B TIMER1_COMPB_vect 113 | #define TIMER2_A TIMER2_COMPA_vect 114 | #define TIMER2_B TIMER2_COMPB_vect 115 | 116 | #if defined(__AVR_ATmega2560__) 117 | #define TIMER1_C TIMER1_COMPC_vect 118 | #define TIMER3_A TIMER3_COMPA_vect 119 | #define TIMER3_B TIMER3_COMPB_vect 120 | #define TIMER3_C TIMER3_COMPC_vect 121 | #define TIMER4_A TIMER4_COMPA_vect 122 | #define TIMER4_B TIMER4_COMPB_vect 123 | #define TIMER4_C TIMER4_COMPC_vect 124 | #define TIMER5_A TIMER5_COMPA_vect 125 | #define TIMER5_B TIMER5_COMPB_vect 126 | #define TIMER5_C TIMER5_COMPC_vect 127 | #endif 128 | 129 | #define GYVERTIMERS_INLINE 130 | /*inline __attribute__((always_inline))*/ 131 | 132 | /* ================ Сlasses of timers ================ */ 133 | class Timer_0 { // Timer 0 134 | public: 135 | uint32_t setPeriod(uint32_t _timer0_period); // Set timer period [us] 136 | uint32_t setFrequency(uint32_t _timer0_frequency); // Set timer frequency [Hz] 137 | float setFrequencyFloat(float _timer0_frequency); // Set timer float frequency [Hz] 138 | 139 | GYVERTIMERS_INLINE 140 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 141 | 142 | GYVERTIMERS_INLINE 143 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 144 | 145 | GYVERTIMERS_INLINE 146 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 147 | 148 | GYVERTIMERS_INLINE 149 | void pause(void); // Disable timer clock , not cleaning the counter 150 | 151 | GYVERTIMERS_INLINE 152 | void resume(void); // Return clock timer settings 153 | 154 | GYVERTIMERS_INLINE 155 | void stop(void); // Disable timer clock , and cleaning the counter 156 | 157 | GYVERTIMERS_INLINE 158 | void restart(void); // Return clock timer settings & reset counter 159 | 160 | GYVERTIMERS_INLINE 161 | void setDefault(void); // Set default timer settings 162 | 163 | GYVERTIMERS_INLINE 164 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 165 | 166 | GYVERTIMERS_INLINE 167 | void outputDisable(uint8_t channel); // Disable timer hardware output 168 | 169 | GYVERTIMERS_INLINE 170 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 171 | 172 | GYVERTIMERS_INLINE 173 | void phaseShift(uint8_t source, uint16_t phase); 174 | 175 | private: 176 | uint8_t _timer0_clock = 0x00; // Variable to store timer clock settings 177 | }; 178 | 179 | class Timer_1 { // Timer 1 180 | public: 181 | uint32_t setPeriod(uint32_t _timer1_period); // Set timer period [Hz] 182 | uint32_t setFrequency(uint32_t _timer1_frequency); // Set timer frequency [Hz] 183 | float setFrequencyFloat(float _timer1_frequency); // Set timer float frequency [Hz] 184 | 185 | GYVERTIMERS_INLINE 186 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 187 | 188 | GYVERTIMERS_INLINE 189 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 190 | 191 | GYVERTIMERS_INLINE 192 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 193 | 194 | GYVERTIMERS_INLINE 195 | void pause(void); // Disable timer clock , not cleaning the counter 196 | 197 | GYVERTIMERS_INLINE 198 | void resume(void); // Return clock timer settings 199 | 200 | GYVERTIMERS_INLINE 201 | void stop(void); // Disable timer clock , and cleaning the counter 202 | 203 | GYVERTIMERS_INLINE 204 | void restart(void); // Return clock timer settings & reset counter 205 | 206 | GYVERTIMERS_INLINE 207 | void setDefault(void); // Set default timer settings 208 | 209 | GYVERTIMERS_INLINE 210 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 211 | 212 | GYVERTIMERS_INLINE 213 | void outputDisable(uint8_t channel); // Disable timer hardware output 214 | 215 | GYVERTIMERS_INLINE 216 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 217 | 218 | GYVERTIMERS_INLINE 219 | void phaseShift(uint8_t source, uint16_t phase); 220 | 221 | private: 222 | uint8_t _timer1_clock = 0x00; // Variable to store timer clock settings 223 | }; 224 | 225 | class Timer_2 { // Timer 2 226 | public: 227 | uint32_t setPeriod(uint32_t _timer2_period); // Set timer period [Hz] 228 | uint32_t setFrequency(uint32_t _timer2_frequency); // Set timer frequency [Hz] 229 | float setFrequencyFloat(float _timer2_frequency); // Set timer float frequency [Hz] 230 | 231 | GYVERTIMERS_INLINE 232 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 233 | 234 | GYVERTIMERS_INLINE 235 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 236 | 237 | GYVERTIMERS_INLINE 238 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 239 | 240 | GYVERTIMERS_INLINE 241 | void pause(void); // Disable timer clock , not cleaning the counter 242 | 243 | GYVERTIMERS_INLINE 244 | void resume(void); // Return clock timer settings 245 | 246 | GYVERTIMERS_INLINE 247 | void stop(void); // Disable timer clock , and cleaning the counter 248 | 249 | GYVERTIMERS_INLINE 250 | void restart(void); // Return clock timer settings & reset counter 251 | 252 | GYVERTIMERS_INLINE 253 | void setDefault(void); // Set default timer settings 254 | 255 | GYVERTIMERS_INLINE 256 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 257 | 258 | GYVERTIMERS_INLINE 259 | void outputDisable(uint8_t channel); // Disable timer hardware output 260 | 261 | GYVERTIMERS_INLINE 262 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 263 | 264 | GYVERTIMERS_INLINE 265 | void phaseShift(uint8_t source, uint16_t phase); 266 | 267 | private: 268 | uint8_t _timer2_clock = 0x00; // Variable to store timer clock settings 269 | }; 270 | 271 | #if defined(__AVR_ATmega2560__) 272 | class Timer_3 { // Timer 3 273 | public: 274 | uint32_t setPeriod(uint32_t _timer3_period); // Set timer period [Hz] 275 | uint32_t setFrequency(uint32_t _timer3_frequency); // Set timer frequency [Hz] 276 | float setFrequencyFloat(float _timer3_frequency); // Set timer float frequency [Hz] 277 | 278 | GYVERTIMERS_INLINE 279 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 280 | 281 | GYVERTIMERS_INLINE 282 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 283 | 284 | GYVERTIMERS_INLINE 285 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 286 | 287 | GYVERTIMERS_INLINE 288 | void pause(void); // Disable timer clock , not cleaning the counter 289 | 290 | GYVERTIMERS_INLINE 291 | void resume(void); // Return clock timer settings 292 | 293 | GYVERTIMERS_INLINE 294 | void stop(void); // Disable timer clock , and cleaning the counter 295 | 296 | GYVERTIMERS_INLINE 297 | void restart(void); // Return clock timer settings & reset counter 298 | 299 | GYVERTIMERS_INLINE 300 | void setDefault(void); // Set default timer settings 301 | 302 | GYVERTIMERS_INLINE 303 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 304 | 305 | GYVERTIMERS_INLINE 306 | void outputDisable(uint8_t channel); // Disable timer hardware output 307 | 308 | GYVERTIMERS_INLINE 309 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 310 | 311 | GYVERTIMERS_INLINE 312 | void phaseShift(uint8_t source, uint16_t phase); 313 | 314 | private: 315 | uint8_t _timer3_clock = 0x00; // Variable to store timer clock settings 316 | }; 317 | 318 | class Timer_4 { // Timer 4 319 | public: 320 | uint32_t setPeriod(uint32_t _timer4_period); // Set timer period [Hz] 321 | uint32_t setFrequency(uint32_t _timer4_frequency); // Set timer frequency [Hz] 322 | float setFrequencyFloat(float _timer4_frequency); // Set timer float frequency [Hz] 323 | 324 | GYVERTIMERS_INLINE 325 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 326 | 327 | GYVERTIMERS_INLINE 328 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 329 | 330 | GYVERTIMERS_INLINE 331 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 332 | 333 | GYVERTIMERS_INLINE 334 | void pause(void); // Disable timer clock , not cleaning the counter 335 | 336 | GYVERTIMERS_INLINE 337 | void resume(void); // Return clock timer settings 338 | 339 | GYVERTIMERS_INLINE 340 | void stop(void); // Disable timer clock , and cleaning the counter 341 | 342 | GYVERTIMERS_INLINE 343 | void restart(void); // Return clock timer settings & reset counter 344 | 345 | GYVERTIMERS_INLINE 346 | void setDefault(void); // Set default timer settings 347 | 348 | GYVERTIMERS_INLINE 349 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 350 | 351 | GYVERTIMERS_INLINE 352 | void outputDisable(uint8_t channel); // Disable timer hardware output 353 | 354 | GYVERTIMERS_INLINE 355 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 356 | 357 | GYVERTIMERS_INLINE 358 | void phaseShift(uint8_t source, uint16_t phase); 359 | 360 | private: 361 | uint8_t _timer4_clock = 0x00; // Variable to store timer clock settings 362 | }; 363 | 364 | class Timer_5 { // Timer 5 365 | public: 366 | uint32_t setPeriod(uint32_t _timer5_period); // Set timer period [Hz] 367 | uint32_t setFrequency(uint32_t _timer5_frequency); // Set timer frequency [Hz] 368 | float setFrequencyFloat(float _timer5_frequency); // Set timer float frequency [Hz] 369 | 370 | GYVERTIMERS_INLINE 371 | bool ready(uint8_t channel = CHANNEL_A); // Return true, is interrupt is ready, but not enabled 372 | 373 | GYVERTIMERS_INLINE 374 | void enableISR(uint8_t source = CHANNEL_A); // Enable timer interrupt , channel A or B 375 | 376 | GYVERTIMERS_INLINE 377 | void disableISR(uint8_t source = CHANNEL_A); // Disable timer interrupt , channel A or B 378 | 379 | GYVERTIMERS_INLINE 380 | void pause(void); // Disable timer clock , not cleaning the counter 381 | 382 | GYVERTIMERS_INLINE 383 | void resume(void); // Return clock timer settings 384 | 385 | GYVERTIMERS_INLINE 386 | void stop(void); // Disable timer clock , and cleaning the counter 387 | 388 | GYVERTIMERS_INLINE 389 | void restart(void); // Return clock timer settings & reset counter 390 | 391 | GYVERTIMERS_INLINE 392 | void setDefault(void); // Set default timer settings 393 | 394 | GYVERTIMERS_INLINE 395 | void outputEnable(uint8_t channel, uint8_t mode); // Enable and configurate timer hardware output 396 | 397 | GYVERTIMERS_INLINE 398 | void outputDisable(uint8_t channel); // Disable timer hardware output 399 | 400 | GYVERTIMERS_INLINE 401 | void outputState(uint8_t channel,bool state); // Set High / Low on the timer output 402 | 403 | GYVERTIMERS_INLINE 404 | void phaseShift(uint8_t source, uint16_t phase); 405 | 406 | private: 407 | uint8_t _timer5_clock = 0x00; // Variable to store timer clock settings 408 | }; 409 | 410 | #endif 411 | 412 | extern Timer_0 Timer0; 413 | extern Timer_1 Timer1; 414 | extern Timer_2 Timer2; 415 | 416 | #if defined(__AVR_ATmega2560__) 417 | extern Timer_3 Timer3; 418 | extern Timer_4 Timer4; 419 | extern Timer_5 Timer5; 420 | #endif 421 | 422 | #endif --------------------------------------------------------------------------------