您的位置:首页 > 其它

关于51单片机中断标志的一个小问题

2016-09-21 11:57 232 查看

第一张图片:





第二张图片:






代码:

#include

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

unsigned char code LedChar[]={
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[6]={
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

unsigned int cnt = 0;

void main()
{

unsigned long sec = 0;

ENLED = 0;
ADDR3 = 1;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
TR0 = 1;
EA = 1;
ET0 = 1;

while(1)
{
if(cnt >= 1000)
{
cnt = 0;
sec++;
LedBuff[0] = LedChar[sec%10];
LedBuff[1] = LedChar[sec/10%10];
LedBuff[2] = LedChar[sec/100%10];
LedBuff[3] = LedChar[sec/1000%10];
LedBuff[4] = LedChar[sec/10000%10];
LedBuff[5] = LedChar[sec/100000%10];
}
}
}

unsigned char i = 0;
void InterruptTimer0()  interrupt 1
{
TH0 = 0xFC;
TL0 = 0x67;
cnt++;
P0 = 0xFF;
switch(i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0];break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1];break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2];break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3];break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4];break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5];break;
default:break;
}
}


此为数码管显示计数的程序,但笔者发现,当代码为第一张图片时候,当计数到30s时候,实际秒表是24s,而第二张图片加一个标志位时候确与实际一致。以下为笔者分析,有不足之处望前辈指点~
分析如下:
第一张图片程序实际上是有问题的,因为cnt是int型,也就是2个字节,51单片机是8位的,一次只能读写1个字节,所以当你判断cnt>=1000的时候是要执行好几条指令的,而如果刚判断了低字节还没来得及判断高字节,这时中断中cnt的值就变了,那就有可能导致判断错误。
也就是说假设当进行if (cnt>=1000)判断的时候,1ms到了进入中断cnt++可能cnt变成了1001或者更多,这样中断结束返回判断的时候cnt的值就不再是1000了,时间就变长了。
而第二张图片加了一个flag判断标志位,假设在满足了flag为1,if(flag==1)判断时,进入中断,可是cnt在中断时已经清0了,又是从1开始加(flag在这里始终为1),所以对中断完回去判断if,没有影响。

当然这里只是笔者的愚见,还请前辈多多指点~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: