在嵌入式开发过程中,经常会遇到溢出问题,例如在使用软定时判断时间是否超时。如下:
if (timer_ticks >= timeout)
{
}
timer_ticks
是一个无符号数,假如是一个无符号8位,当timer_ticks
为254,超时时间为2个tick,则timeout
为0,这时候条件成立,判断出错。
解决如上问题,有以下3种方法:
把timer_ticks
定义成无符号64位数,假设一个tick是1ms时间,则溢出时间为583344214年,基本不会出现溢出问题
增加两个变量,一个是开始时间,另外是超时间隔,如下:
#define TICKS_MAX 0xFFFFFFFF
uint32_t timer_start = ticks_get();
uint32_t interval = 10;
//......
uint32_t now_ticks = ticks_get();
if ( now_ticks >= timer_start)
{
if ((now_ticks - timer_start) >= interval)
{
// timeout
}
}
else
{
if ((now_ticks + (TICKS_MAX - timer_start) + 1) >= interval)
{
// timeout
}
}
if((int32_t)((uint32_t)(timeout -timer_ticks)) <= 0)
{
}
以一个字节的长度为例,
当 timer_ticks=254
时,定时3ms,即 timeout=1
时发生超时,根据timeout - timer_ticks <= 0
条件:
当 timer_ticks=254
时,1-254=3,大于0,未超时
当 timer_ticks=255
时,1-255=2,大于0,未超时
当 timer_ticks=0
时,1-0=1,大于0,未超时
当 timer_ticks=1
时,1-1=0,等于0,超时
考虑到超时判断是在主循环进行的,可能会出现判断的时候错过了timer_ticks=1
的情况
当 timer_ticks=2
时,1-2=-1,小于0,超时
当 timer_ticks=3
时,1-3=-2,小于0,超时
限制:使用该种方式时,要求 interval 不能大于 TICK_MAX / 2
其中
timeout = timer_ticks + interval