STC单片机STC12C5160S2,是1T的单片机。把T0,T1的中断都用上了:
void t0(void) interrupt 1 using 0
{
dispcnt++; //切换不同的显示
。。。。
}
void t1(void) interrupt 3
{
tcnt++;
} //END INTERRUPT
tcnt用于累计一秒的计数量3600次。
在主程序中循环判断:
if(tcnt>=3600) //3600次,表示过了一秒钟,晶体11.0592
{
tcnt-=3600;
加一秒
}
结果发现:走时严重不准!!越走越快!!一小时能快上10~20%,无规律性。即tcnt越加越多。
怎么看程序都是对的,找了很久找不到原因!!
以为是using 0的问题,造成中断服务程序变量混乱,结果不是,把using 0去掉,一样不行!!
以为是T1中断触发不正确,但加一个端口翻转,测端口频率,也正确。
T1与T2中断服务程序不能同时存在?晕了。。。
把tcnt-=3600;这句改成tcnt=0; 咦,走时正确了!!
难道单片机做tcnt的减法不行???
后来用串口监控tcnt,发现tcnt会变成负值,即对于unsigned int来说,值忽然变大了,造成多了额外的秒。
查看汇编,发现tcnt做减法时会被分解成多条语句。
知道了!原来做减法时,要多条汇编语句,有可能做到一半语句,会被T1中断程序中断掉,中断程序中又是使用了tcnt作加法,这样导致最后减法做出来的值不正确!!
而tcnt=0;这句比较简单,即使被中断中断掉,最后也是清0,故就没有影响。
改成:
ET1=0;
if(tcnt>=3600) //3600次,表示过了一秒钟,晶体11.0592
{
tcnt-=3600;
ET1=1;
加一秒
}
else ET1=1
正常了!
结论:
在主程序中,如果用到了中断程序中的变量,则要先禁用掉中断,用完这个变量再打开中断,避免中断干扰造成值计算错误。