Skip to content

Commit 103a44f

Browse files
支持运行时指定重复次数
1 parent 6178d69 commit 103a44f

File tree

5 files changed

+147
-3
lines changed

5 files changed

+147
-3
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
音响、方波、延迟任务、定时重复,这些任务都需要应用开发板上的计时器才能完成。有时你甚至需要多个计时器同步运行,实现多线程任务。但是,当前Arduino社区并没有提供比较完善的计时器运行库。它们能够执行的任务模式非常有限,而且用户无法指定具体要使用哪个计时器。其结果就是,经常有一些使用计时器的库发生冲突,或者和用户自己的应用发生冲突。本项目旨在将计时器可能需要使用的所有功能在所有计时器上实现,最关键的是允许用户手动指定要是用的硬件计时器,避免冲突。
55

6-
**由于作者精力有限,目前本项目所有函数,仅时长参数可以在运行时动态设置,其它参数必须为编译期常量,作为模板参数。后续有空会实现更多可以动态设置参数的API。当然更欢迎上GitHub主页贡献Pull request。**
6+
**由于作者精力有限,目前本项目所有函数,仅时长、重复次数参数可以在运行时动态设置,其它参数必须为编译期常量,作为模板参数。后续有空会实现更多可以动态设置参数的API。当然更欢迎上GitHub主页贡献Pull request。**
77
# 硬件计时器
88
本库所有公开API的第一个模板参数,都是计时器的编号。不同计时器之间完全独立运行,互不干扰。用户必须在代码中手动指定要使用哪个硬件计时器来执行功能。不同CPU中的计时器数目和属性各不相同,此处以Arduino Mega开发板上常用的ATMega2560系列CPU为例:
99
## 计时器0
@@ -24,7 +24,7 @@ Make full use of all your hardware timers on your Arduino board.
2424

2525
The only library you can choose any hardware timer you like to use in your timing function. Tones, square waves, delayed tasks, timed repetitive tasks are provided as building blocks for your own sophisticated multi-timer tasks. My library hides hardware register details for you.
2626

27-
**Currently, for all APIs, only time length arguments can be specified at runtime. Other arguments are all template arguments, i.e., they must be known as constexprs at compiling time. I'll implement more runtime arguments if I have more free time. Pull requests are fully welcomed on my GitHub site.**
27+
**Currently, for all APIs, only time length and RepeatTimes arguments can be specified at runtime. Other arguments are all template arguments, i.e., they must be known as constexprs at compiling time. I'll implement more runtime arguments if I have more free time. Pull requests are fully welcomed on my GitHub site.**
2828
# Timers
2929
All public APIs are under namespace TimersOneForAll, and require TimerCode as the first template argument. TimerCode indicates which hardware timer you want to use. Hardware timers vary by CPUs. For ATMega2560 (Arduino Mega), there're 6 timers:
3030
## Timer 0
@@ -65,6 +65,9 @@ void RepeatAfter();
6565
//Specify milliseconds at runtime. After all repeats done, DoneCallback is called.
6666
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes, void (*DoneCallback)() = nullptr>
6767
void RepeatAfter(uint16_t IntervalMilliseconds);
68+
//每隔指定毫秒数重复执行任务。重复次数若为负数,或不指定重复次数,则默认无限重复
69+
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), void (*DoneCallback)() = nullptr>
70+
void RepeatAfter(int32_t RepeatTimes);
6871

6972
//将当前时刻设为0,计量经过的毫秒数。读取MillisecondsElapsed变量来获得经过的毫秒数。
7073
//Set the time now as 0 and start to record time elapsed. Read MillisecondsElapsed variable to get the time elapsed.
@@ -104,6 +107,10 @@ void SquareWave();
104107
//Specify milliseconds at runtime. After all cycles done, DoneCallback is called.
105108
template <uint8_t TimerCode, uint8_t PinCode, int16_t RepeatTimes, void (*DoneCallback)() = nullptr>
106109
void SquareWave(uint16_t HighMilliseconds, uint16_t LowMilliseconds);
110+
//允许运行时动态设置重复次数。重复次数不指定的话则为无限重复。
111+
//Specify RepeatTimes at runtime. Infinitely repeat if not specified.
112+
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, void (*DoneCallback)() = nullptr>
113+
void SquareWave(int16_t RepeatTimes);
107114

108115
//阻塞当前代码执行指定毫秒数
109116
//Block current code from running for DelayMilliseconds

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=TimersOneForAll
2-
version=1.3.0
2+
version=1.4.0
33
author=EbolaChan <[email protected]>
44
maintainer=EbolaChan <[email protected]>
55
sentence=Make full use of all your hardware timers on your Arduino board. 充分利用你开发板上所有的硬件计时器

src/Internal/Kernel.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,62 @@ namespace TimersOneForAll
450450
}
451451
}
452452
}
453+
#pragma endregion
454+
#pragma region 重复次数可变实现
455+
template <uint8_t TimerCode, uint32_t TCNT, uint8_t PrescalerBits, void (*DoTask)(), void (*DoneCallback)()>
456+
void SLRepeaterSet(int32_t RepeatTimes)
457+
{
458+
TIMSK<TimerCode> = 0;
459+
if (RepeatTimes != 0)
460+
{
461+
constexpr uint32_t TM = TimerMax[TimerCode];
462+
constexpr uint16_t IdealRepeats = TCNT / (TM - (TimerCode == 0));
463+
constexpr bool Timer02 = TimerCode == 0 || TimerCode == 2;
464+
if (Timer02)
465+
TCCRB<TimerCode> = PrescalerBits;
466+
else
467+
TCCRA<TimerCode> = 0;
468+
if (RepeatTimes > 0)
469+
LR<TimerCode> = RepeatTimes;
470+
if (IdealRepeats * TM < TCNT || TimerCode == 0) //Timer0的OVF不可用
471+
{
472+
if (Timer02)
473+
TCCRA<TimerCode> = 2;
474+
else
475+
TCCRB<TimerCode> = PrescalerBits + 8;
476+
constexpr uint16_t ActualRepeats = IdealRepeats + 1;
477+
constexpr uint16_t Tcnt1 = TCNT / ActualRepeats;
478+
constexpr uint16_t Tcnt2 = Tcnt1 + 1;
479+
constexpr uint16_t SR1 = ActualRepeats * Tcnt2 - TCNT; //必大于0
480+
constexpr uint16_t SR2 = TCNT - ActualRepeats * Tcnt1;
481+
SetOCRA<TimerCode>(Tcnt1);
482+
SR<TimerCode> = SR1;
483+
if (SR2)
484+
{
485+
COMPA<TimerCode> = RepeatTimes < 0 ? Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, true, DoneCallback> : Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, false, DoneCallback>;
486+
if (Tcnt2 == TM)
487+
OVF<TimerCode> = RepeatTimes < 0 ? Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, true, DoneCallback> : Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, false, DoneCallback>;
488+
}
489+
else
490+
COMPA<TimerCode> = RepeatTimes < 0 ? Compa0<TimerCode, DoTask, SR1, true, DoneCallback> : Compa0<TimerCode, DoTask, SR1, false, DoneCallback>;
491+
SetTCNT<TimerCode>(0);
492+
TIFR<TimerCode> = 255;
493+
TIMSK<TimerCode> = 2;
494+
}
495+
else
496+
{
497+
SR<TimerCode> = IdealRepeats;
498+
OVF<TimerCode> = RepeatTimes < 0 ? Compa0<TimerCode, DoTask, IdealRepeats, true, DoneCallback> : Compa0<TimerCode, DoTask, IdealRepeats, false, DoneCallback>;
499+
if (Timer02)
500+
TCCRA<TimerCode> = 0;
501+
else
502+
TCCRB<TimerCode> = PrescalerBits;
503+
SetTCNT<TimerCode>(0);
504+
TIFR<TimerCode> = 255;
505+
TIMSK<TimerCode> = 1;
506+
}
507+
}
508+
}
453509
#pragma endregion
454510
}
455511
}

src/Internal/RepeatAfter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ namespace TimersOneForAll
1616
Internal::TimerSetting TS = Internal::GetTimerSetting<TimerCode>(IntervalMilliseconds);
1717
Internal::SLRepeaterSet<TimerCode, DoTask, RepeatTimes, DoneCallback>(TS.TCNT, TS.PrescalerBits);
1818
}
19+
//每隔指定毫秒数重复执行任务。重复次数若为负数,或不指定重复次数,则默认无限重复
20+
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), void (*DoneCallback)() = nullptr>
21+
void RepeatAfter(int32_t RepeatTimes = -1)
22+
{
23+
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, IntervalMilliseconds);
24+
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, DoTask, DoneCallback>(RepeatTimes);
25+
}
1926
}

src/Internal/SquareWave.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,74 @@ namespace TimersOneForAll
183183
}
184184
}
185185
}
186+
//重复次数可变实现
187+
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, void (*DoneCallback)()>
188+
void InternalSW(int32_t RepeatTimes)
189+
{
190+
switch (RepeatTimes)
191+
{
192+
case 0:
193+
TIMSK<TimerCode> = 0;
194+
if (DoneCallback)
195+
DoneCallback();
196+
break;
197+
case 1:
198+
Gifts::EfficientDigitalWrite<PinCode, HIGH>();
199+
DoAfter<TimerCode, HighMilliseconds, OneShotSWDone<PinCode, DoneCallback>>();
200+
break;
201+
default:
202+
if (HighMilliseconds == LowMilliseconds)
203+
{
204+
constexpr TimerSetting TS = GetTimerSetting(TimerCode, HighMilliseconds);
205+
Gifts::EfficientDigitalWrite<PinCode, HIGH>();
206+
SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>, DoneCallback>(RepeatTimes < 0 ? -1 : RepeatTimes * 2 - 1);
207+
}
208+
else
209+
{
210+
constexpr uint32_t TM = TimerMax[TimerCode];
211+
constexpr uint32_t FullCycle = HighMilliseconds + LowMilliseconds;
212+
constexpr TimerSetting TryTS = GetTimerSetting(TimerCode, FullCycle);
213+
constexpr bool Timer02 = TimerCode == 0 || TimerCode == 2;
214+
if (TryTS.TCNT < TM)
215+
{
216+
TIMSK<TimerCode> = 0;
217+
if (Timer02)
218+
{
219+
TCCRA<TimerCode> = 2;
220+
TCCRB<TimerCode> = TryTS.PrescalerBits;
221+
}
222+
else
223+
{
224+
TCCRA<TimerCode> = 0;
225+
TCCRB<TimerCode> = TryTS.PrescalerBits + 8;
226+
}
227+
SetOCRA<TimerCode>(TryTS.TCNT);
228+
SetOCRB<TimerCode>(TryTS.TCNT * HighMilliseconds / FullCycle);
229+
LR<TimerCode> = RepeatTimes;
230+
COMPA<TimerCode> = Gifts::EfficientDigitalWrite<PinCode, HIGH>;
231+
COMPB<TimerCode> = RepeatTimes > 0 ? []
232+
{
233+
Gifts::EfficientDigitalWrite<PinCode, LOW>();
234+
if (!--LR<TimerCode>)
235+
{
236+
TIMSK<TimerCode> = 0;
237+
if (DoneCallback)
238+
DoneCallback();
239+
}
240+
}
241+
: Gifts::EfficientDigitalWrite<PinCode, LOW>;
242+
Gifts::EfficientDigitalWrite<PinCode, HIGH>();
243+
SetTCNT<TimerCode>(0);
244+
TIFR<TimerCode> = 255;
245+
TIMSK<TimerCode> = 6;
246+
}
247+
else if (RepeatTimes < 0)
248+
SquareWaveToHigh<TimerCode, PinCode, HighMilliseconds, LowMilliseconds, true, DoneCallback>();
249+
else
250+
SquareWaveToHigh<TimerCode, PinCode, HighMilliseconds, LowMilliseconds, false, DoneCallback>();
251+
}
252+
}
253+
}
186254
}
187255
//生成循环数有限的方波。如不指定循环次数,默认无限循环
188256
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, int16_t RepeatTimes = -1, void (*DoneCallback)() = nullptr>
@@ -196,4 +264,10 @@ namespace TimersOneForAll
196264
{
197265
Internal::InternalSW<TimerCode, PinCode, RepeatTimes, DoneCallback>(HighMilliseconds, LowMilliseconds);
198266
}
267+
//生成循环数有限的方波。如不指定循环次数,默认无限循环
268+
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, void (*DoneCallback)() = nullptr>
269+
void SquareWave(int16_t RepeatTimes = -1)
270+
{
271+
Internal::InternalSW<TimerCode, PinCode, HighMilliseconds, LowMilliseconds, DoneCallback>(RepeatTimes);
272+
}
199273
}

0 commit comments

Comments
 (0)