以往,如果要在程序里非堵塞式地延时一段时间,比如说我发了一包数据,然后要等待一段时间,如果时间到了还没收到回复,则认为超时,如果在等待时间内没有收到数据,我也不能停下来空等,而应该去做别的事。一般情况下,我们会设置一个定时器,让他周期中断,然后定一个全局变量,这个全局变量在这个定时器的中断里累加,程序中凡是需要延时的地方,可以通过读取这个全局变量,来知道时间流逝,这个全局变量一般取名叫tick。在需要延时的时间,把当前的tick保存下来,然后每次程序执行到需要延时的地方,就拿当前的tick减去保存的tick,查看一下过去了多长时间,以此来判断超时时间是否一到。
这里这个tick的减的操作,大部分情况下都是没问题的。因为一般情况下,tick的累加间隔一般设置1ms,而tick的大小一般也定为32位,要让这个tick累加到溢出变成0,要经过49天。讨论这个tick溢出问题,是因为这个减的操作,只有在tick没溢出的时候是没问题的。试想一下,如果在等待的期间tick溢出了,那么保存的值就会比当前的tick的值要大了,无符号数,用小的减去大的会怎么样?
可能你会想,考虑到这个情况,那每次减之前,判断一下当前tick与保存的tick的大小,保证用大的减去小的,一样能准确获得延时时间。这样做也确实能够避免溢出的问题,可是程序里就会很繁琐很啰嗦。
可以有另外一种更有效的计算延时的方法。
在需要延时的时候,读取当前tick,然后把当前tick的值加上你要延时的时间,保存下来。像这样end_tick = OS_GetTick() + delay_ms然后在判断延时的时候,是判断当前tick跟保存下来的这个值是否相同。if(end_tick == OS_GetTick()),如果相同了,则说明延时时间已到。这个方法的巧妙利用了溢出。试想一下,tick溢出的情况,你把tick加上delay_ms,已经超过32位的表示范围,例如0xffff fff0 + 0x20,那么结果会是0x10。保存的值就是0x10,而tick从当前的0xffff fff0累加到溢出也没关系,溢出后tick从0又开始计数,计到0x10,就刚好到了我们想要的时间。这种方法,永远也不用考虑溢出的情况