以下是我在固件中发现的延迟功能。它看起来有些危险,或者至少使读者感到困惑。
全局变量
static int32u masterTimerCounter; // 32-bit unsigned timer counter
系统滴答中断处理程序
/* Called Every Millisecond */
void sysTickIrqHandler(void)
{
masterTimerCounter++;
}
设置计时器到期功能
void setTimerExpiration(int32u *timerExpiration, int32u delay)
{
*timerExpiration = masterTimerCounter + delay;
}
检查计时器是否过期功能
boolean timerExpired(int32u timerExpiration, int32u delay)
{
if((masterTimerCounter - timerExpiration) < delay)
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
设置计时器到期并阻止直到计时器到期
int32u timerExpiration;
setTimerExpiration(&timerExpiration, 15); // Set expiration timer to 15 milliseconds
while(!timerExpired(timerExpiration, 15) // Block until timer has expired
continue;
题
如您在
timerExpired()
中看到的,masterTimerCounter
被timerExpiration
减去。如果计时器尚未到期,则计算将产生非常大的数字(因为两个操作数均为无符号数字)。当计时器到期时,计算将得出小于延迟量的值。尽管这似乎可以正常工作,但似乎可能很危险,或者至少会使读者感到困惑(我必须阅读几次才能理解原始程序员的意图)。
如果必须编写与此类似的内容,则可以如下定义
timerExpired
函数:boolean timerExpired(int32u timerExpiration)
{
if(timerExpiration > masterTimerCounter)
return FALSE; // Timer still active
else
return TRUE; // Timer has expired
}
我应该重新定义'timerExpired()`吗?
注意:函数和变量名称已更改,以保护无辜。
最佳答案
您遇到的问题是,如果masterTimerCounter + delay
导致32位int的翻转,则timerExpired
测试会立即通过。
我认为在可能发生翻转的情况下执行整数计时器的最直接方法是这样的:
void startTimer(int32u *timerValue)
{
*timerValue = masterTimerCounter;
}
检查计时器是否过期功能
boolean timerExpired(int32u timerVal, int32u delay)
{
if ((masterTimerCounter - timerVal) >= delay)
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
用法:
int32u timer;
startTimer(&timer); // Start timing
while(!timerExpired(timer, 15) // Block for 15 ticks
continue;
即使
timerExpired
中的减法下溢也会返回正确的结果。