第一张图片:
第二张图片:
代码:
#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,没有影响。
当然这里只是笔者的愚见,还请前辈多多指点~