情景描述:我们利用定时器定时2ms,然后利用定时器来定时1s钟。见下面程序:
unsigned int time_flag //1s定时标志位
void main()
{
while(1)
{
pro();任意的处理函数,在这里的意思是需要处理器一定时间去处理
if(time_flag == 500)//到达一秒
{
time_flag = 0; //清零,为下一个1s定时
pro(); //同上
}
}
}
void time_2() interrupt 12 //定时器2中断
{
time_flag++;
}
问题描述:请问上面这样的程序有问题吗?有!并且十分隐蔽。实际上我就遇到了这样的一个问题:实际上,当程序执行接近40s时,if语句里面的内容将不会被执行!!!!但是if外面的语句不会受到影响。
问题分析:我们首先可以想到的是,if语句不执行的原因是其条件不满足。但是为什么条件会不满足呢?每次都有清零的处理啊。在实际debug中,我曾经怀疑过两个中断的优先级导致的错误(实际上我的程序有两个中断),但是事实证明一个中断同样会发生这样的情况。其实还是中断的错!!!如果在if语句执行前,不发生中断,那么当time_flag==500时,就会执行里面的内容。但是当time_flag == 500时,在进入if语句之前发生了中断,那么time_flag++之后就大于500了,那么time_flag就‘永远’不会等于500了。其实它加到65535那也需要两分钟。有人要可能要问,这样的概率也太小了,确实不大。但是在程序执行的时间是很长的,在接近一分钟的时间之内,有近30000次中断,可以确定的是概率绝对不会是30000的高阶无穷小!即必然发生!!!!!!!
问题解决:其实我们知道了异常发生的愿意,解决问题的方法也很简单——对异常情况加以限制。
unsigned int time_flag //1s定时标志位
void main()
{
while(1)
{
pro();任意的处理函数,在这里的意思是需要处理器一定时间去处理
if(time_flag == 500)//到达一秒
{
time_flag = 0; //清零,为下一个1s定时
pro(); //同上
}
if(time_flag >500) time_flag = 0; //对异常情况加以限制!!!!!!关键步骤!!
}
}
void time_2() interrupt 12 //定时器2中断
{
time_flag++;
}
有人可能要说,在中断函数中放入if语句就可以避免这种情况的发生了。事实上确实如此,但是我认为这种方法并不是非常好,因为如果我们定时器定时时间非常短的话,在中断函数执行太多语句反而会降低程序的效率。当然这是个人观点,可能是有错误的。但是还有一点,就是放入中断函数中还需要添加标志位,这同时也增大了内存的开销,所以这也是我把if语句放进主函数的原因。
问题的现象大家可以观看我B站的视频,其中有一段的内容是描述这个问题的:
第七届蓝桥杯单片机组程序题zhe_哔哩哔哩_bilibili
(这个bug在视频的后半部分!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)