CONFIGにて選択されたRtc/Tca/Tca8/Tcbクラスのどれかをタイマーとして利用し無制限かつマイクロ秒精度のタイマー機能を提供する。
割込みとポーリング処理に対応しTcbはポーリングのみ、Tca8は特定のCPUクロック(1/2/4/16MHz)でのみ動作するので注意するべし。
※時間はTimer.us2tick(マイクロ秒)の戻り値(タイマーカウント値)を指定すること。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
/* Rtc/Tca/Tca8/Tcbのどれをタイマーとして利用するかを設定 */ #define CONFIG_ALARM_TIMER TIMER_RTC // #define CONFIG_ALARM_TIMER TIMER_TCA // #define CONFIG_ALARM_TIMER TIMER_TCA8 // #define CONFIG_ALARM_TIMER TIMER_TCB /* タイマーとして利用するTcaの詳細設定 */ #define CONFIG_ALARM_TIMER_TCA TCA0 #define CONFIG_ALARM_TIMER_TCA_CMP TcaBase::CMP2 /* タイマーとして利用するTcbの詳細設定 */ #define CONFIG_ALARM_TIMER_TCB TCB0 |
【割り込みで一秒毎にLチカするサンプル・コード】
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "avr8_port.h" #include "avr8_alarm.h" #define LED Port::PC6 Alarm alarm; bool AlarmCallback(Alarm& alarm) { Port::digitalWrite(LED, Port::TOGGLE); return true; // true: Continue, false: Stop. } int main(void) { sei(); Port::pinMode(LED, Port::OUTPUT); AlarmTimer.start(alarm.interval(Timer.us2tick(1000000)).handler(AlarmCallback)); while (1) ; } |
【ポーリングで一秒毎にLチカするサンプル・コード】
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include "avr8_port.h" #include "avr8_alarm.h" #define LED Port::PC6 Alarm alarm; int main(void) { sei(); Port::pinMode(LED, Port::OUTPUT); alarm.interval(Timer.us2tick(1000000)); while (1) { if (alarm.expire()) Port::digitalWrite(LED, Port::TOGGLE); } } |
【ライブラリ】
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
/* avr8_alarm.h - Alarm Library for Microchip AVR8 Series Copyright (c) 2025 Sasapea's Lab. All right reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #pragma once #include "avr8_config.h" #if CONFIG_TASK_USE || CONFIG_ALARM_USE #include <stddef.h> #include <stdint.h> #include <stdbool.h> #include "avr8_timer.h" class Alarm : public TimerClass { public: typedef bool (*handler_t)(Alarm& alarm); Alarm& interval(int32_t interval, bool fromnow = true); int32_t interval(void); Alarm& handler(handler_t handler); handler_t handler(void); Alarm& param(uint8_t num, void *val); void *param(uint8_t num); bool expire(void); protected: friend class AlarmClass; Alarm *_next; uint32_t _alarm; int32_t _interval; handler_t _handler; void *_params[4]; }; class AlarmClass : protected TimerClass { public: AlarmClass(void); void begin(void); bool start(Alarm& alarm); void cancel(Alarm& alarm); void cancel(uint8_t num, void *arg); void handle(void); protected: bool add(Alarm& alarm); private: bool timeup(void); #if (CONFIG_ALARM_TIMER == TIMER_TCA) || (CONFIG_ALARM_TIMER == TIMER_TCA8) friend void AlarmClass_timeup(TcaBase::CMP); #else friend void AlarmClass_timeup(void); #endif Alarm *_alarm_list; bool _poll_mode; }; extern AlarmClass AlarmTimer; #endif |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
/* avr8_alarm.cpp - Alarm Library for Microchip AVR8 Series Copyright (c) 2025 Sasapea's Lab. All right reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <stddef.h> #include "avr8_alarm.h" #if CONFIG_TASK_USE || CONFIG_ALARM_USE #define lengthof(a) (sizeof(a)/sizeof(a[0])) AlarmClass AlarmTimer; Alarm& Alarm::interval(int32_t interval, bool fromnow) { if (fromnow) _alarm = Timer.read() + interval; _interval = interval; return *this; } int32_t Alarm::interval(void) { return _interval; } Alarm& Alarm::handler(Alarm::handler_t handler) { _handler = handler; return *this; } Alarm::handler_t Alarm::handler(void) { return _handler; } Alarm& Alarm::param(uint8_t num, void *val) { if (num < lengthof(_params)) _params[num] = val; return *this; } void *Alarm::param(uint8_t num) { return num < lengthof(_params) ? _params[num] : NULL; } bool Alarm::expire(void) { if ((int32_t)(Timer.read() - _alarm) < 0) return false; _alarm += _interval; return true; } AlarmClass::AlarmClass(void) : _alarm_list(0), _poll_mode(0) { } void AlarmClass::begin(void) { _poll_mode = !setupAlarmTimer(); } bool AlarmClass::start(Alarm& alarm) { if ((alarm._interval < 1) || !alarm._handler) return false; sreg_t state = disableAndSaveInterrupts(); if (add(alarm) && !_poll_mode) startAlarmTimer(_alarm_list->_alarm - Timer.read()); restoreInterrupts(state); return true; } void AlarmClass::cancel(Alarm& alarm) { sreg_t state = disableAndSaveInterrupts(); for (Alarm **p = &_alarm_list; *p; p = &(*p)->_next) { if (*p == &alarm) { *p = (*p)->_next; break; } } restoreInterrupts(state); } void AlarmClass::cancel(uint8_t num, void *arg) { if ((num < lengthof(Alarm::_params)) && arg) { sreg_t state = disableAndSaveInterrupts(); for (Alarm **p = &_alarm_list; *p; p = &(*p)->_next) { if ((*p)->_params[num] == arg) { *p = (*p)->_next; break; } } restoreInterrupts(state); } } bool AlarmClass::add(Alarm& alarm) { Alarm **p; for (p = &_alarm_list; *p && ((int32_t)((*p)->_alarm - alarm._alarm) <= 0); p = &(*p)->_next) continue; alarm._next = *p; *p = &alarm; return p == &_alarm_list; } bool AlarmClass::timeup(void) { Alarm *p = NULL; while (_alarm_list) { int32_t t = _alarm_list->_alarm - Timer.read(); if (p || (t > 0)) { if (!_poll_mode) startAlarmTimer(t); return true; } _alarm_list = (p = _alarm_list)->_next; if (p->_handler(*p)) { p->_alarm += p->_interval; if (!add(*p)) p = NULL; } else p = NULL; } return false; } void AlarmClass::handle(void) { if (_poll_mode) { Timer.poll(); sreg_t state = disableAndSaveInterrupts(); timeup(); restoreInterrupts(state); } } #endif |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
/* avr8_timer.h - Timer Library for Microchip AVR8 Series Copyright (c) 2025 Sasapea's Lab. All right reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #pragma once #include <stddef.h> #include <stdint.h> #include <stdbool.h> #include "avr8_config.h" #if CONFIG_TASK_USE || CONFIG_ALARM_USE typedef uint8_t sreg_t; class TimerClass { public: /* Interrupt Control */ static sreg_t disableAndSaveInterrupts(void); static void restoreInterrupts(sreg_t save); static void idle(void); protected: /* For Alarm Class */ static bool setupAlarmTimer(void); static void startAlarmTimer(int32_t interval); }; #define TIMER_RTC 1 #define TIMER_TCA 2 #define TIMER_TCA8 3 #define TIMER_TCB 4 #if CONFIG_ALARM_TIMER == TIMER_RTC #include "avr8_rtc.h" extern Rtc Timer; #elif CONFIG_ALARM_TIMER == TIMER_TCA #include "avr8_tca.h" extern Tca Timer; #elif CONFIG_ALARM_TIMER == TIMER_TCA8 #include "avr8_tca.h" extern Tca8 Timer; #elif CONFIG_ALARM_TIMER == TIMER_TCB #include "avr8_tcb.h" extern Tcb Timer; #else #error "CONFIG_ALARM_TIMER mistake" #endif #endif |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
/* avr8_timer.cpp - Timer Library for Microchip AVR8 Series Copyright (c) 2025 Sasapea's Lab. All right reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include "avr8_config.h" #if CONFIG_TASK_USE || CONFIG_ALARM_USE #include "avr8_timer.h" #include "avr8_alarm.h" #if CONFIG_ALARM_TIMER == TIMER_RTC Rtc Timer; #elif CONFIG_ALARM_TIMER == TIMER_TCA Tca Timer(CONFIG_ALARM_TIMER_TCA); #elif CONFIG_ALARM_TIMER == TIMER_TCA8 Tca8 Timer(CONFIG_ALARM_TIMER_TCA); #elif CONFIG_ALARM_TIMER == TIMER_TCB Tcb Timer(CONFIG_ALARM_TIMER_TCB); #endif /* RTC Timer */ #if CONFIG_ALARM_TIMER == TIMER_RTC void AlarmClass_timeup(void) { AlarmTimer.timeup(); } bool TimerClass::setupAlarmTimer(void) { Timer.begin(); Timer.callback(AlarmClass_timeup); Timer.run(); return true; } void TimerClass::startAlarmTimer(int32_t interval) { Timer.interrupt(interval); } /* Tca Timer */ #elif CONFIG_ALARM_TIMER == TIMER_TCA void AlarmClass_timeup(TcaBase::CMP cmp) { (void)cmp; AlarmTimer.timeup(); } bool TimerClass::setupAlarmTimer(void) { Timer.begin(); Timer.callback(CONFIG_ALARM_TIMER_TCA_CMP, AlarmClass_timeup); Timer.run(); #if CONFIG_TCA_ISR return true; #else return false; #endif } void TimerClass::startAlarmTimer(int32_t interval) { Timer.interrupt(CONFIG_ALARM_TIMER_TCA_CMP, interval); } /* Tca8 Timer */ #elif CONFIG_ALARM_TIMER == TIMER_TCA8 void AlarmClass_timeup(TcaBase::CMP cmp) { (void)cmp; AlarmTimer.timeup(); } bool TimerClass::setupAlarmTimer(void) { if (!Timer.begin()) return false; Timer.callback(CONFIG_ALARM_TIMER_TCA_CMP, AlarmClass_timeup); Timer.run(); #if CONFIG_TCA_ISR return true; #else return false; #endif } void TimerClass::startAlarmTimer(int32_t interval) { Timer.interrupt(CONFIG_ALARM_TIMER_TCA_CMP, interval); } /* Tcb Timer */ #elif CONFIG_ALARM_TIMER == TIMER_TCB bool TimerClass::setupAlarmTimer(void) { Timer.begin(); Timer.run(); return false; } void TimerClass::startAlarmTimer(int32_t interval) { (void)interval; } #endif sreg_t TimerClass::disableAndSaveInterrupts(void) { sreg_t rv = SREG; cli(); return rv; } void TimerClass::restoreInterrupts(sreg_t save) { SREG = save; } void TimerClass::idle(void) { sei(); } #endif |
【関連投稿】
Microchip AVR8 用のライブラリを自作する。(GPIO)
Microchip AVR8 用のライブラリを自作する。(FUSE)
Microchip AVR8 用のライブラリを自作する。(CLOCK)
Microchip AVR8 用のライブラリを自作する。(RESET)
Microchip AVR8 用のライブラリを自作する。(PORTMUX)
Microchip AVR8 用のライブラリを自作する。(USART)
Microchip AVR8 用のライブラリを自作する。(RTC)
Microchip AVR8 用のライブラリを自作する。(TCA)
Microchip AVR8 用のライブラリを自作する。(TCB)
Microchip AVR8 用のライブラリを自作する。(VREF)
Microchip AVR8 用のライブラリを自作する。(DAC)
Microchip AVR8 用のライブラリを自作する。(AC)
Microchip AVR8 用のライブラリを自作する。(ADC)
Microchip AVR8 用のライブラリを自作する。(ZCD)
Microchip AVR8 用のライブラリを自作する。(SPI)
Microchip AVR8 用のライブラリを自作する。(TWI)
Microchip AVR8 用のライブラリを自作する。(MAIN)
Microchip AVR8 用のライブラリを自作する。(CONFIG)
Microchip AVR8 用のライブラリを自作する。(ALARM)
Microchip AVR8 用のライブラリを自作する。(TASK)
Microchip AVR8 用のライブラリを自作する。(DOWNLOAD)
