C51数码管鬼影产生的一个解决方法(中断)

C51数码管鬼影产生的一个解决方法

(这个方法有助于加深对于中断的理解)

在今天设计一个关于数码管的秒表时,采用了 以下代码:

#include <reg52.h>


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] = 
{
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char i=0;
unsigned int cnt=0;
unsigned char flag=0;
void main()
{
	unsigned long sec=0;
	EA=1;ENLED=0;ADDR3=1;TMOD=0X01;
	TH0=0XFC;TL0=0X67;ET0=1;TR0=1;
	while(1)
	{
		if(flag==1)
		{
			flag=0;sec++;
			LedBuff[0] = LedChar[sec%10];
            LedBuff[1] = LedChar[sec/10%10];
            LedBuff[2] = LedChar[sec/100%10];
				   if (sec/100%10==0&&sec/10%10==0)
						{
						LedBuff[2] = 0xFF;
						LedBuff[1] = 0xFF;
						};
					 if (sec/100%10==0&&sec/10%10!=0)
						{
						LedBuff[2] = 0xFF;
						};
			LedBuff[3] = 0x40;
            LedBuff[4] = 0x4F;
            LedBuff[5] = 0x5B;
		}
	}
}
void InterruptTimer0() interrupt 1
{
	TH0=0XFC;TL0=0X67;cnt++;
	if(cnt>=1000){cnt=0;flag=1;}
	P0=0X00;
	switch (i)
       {
        case 0: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=~LedBuff[0]; break;
        case 1: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=~LedBuff[1]; break;
        case 2: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=~LedBuff[2]; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[3]; break;
        case 4: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[4]; break;
        case 5: ADDR2=0; ADDR1=0; ADDR0=0; i=0; P0=LedBuff[5]; break;
        default: break;
        }
}
;

原本目的是三位秒表如果百位为0则不会亮,但是却出现了鬼影现象,这是为什么呢?
个人的理解是,在以下代码处,由于原本采用的定时器中断方式,在定时器即将溢出时,代码刚好运行到 if 之前,则会带着错误的LedBuff值进入中断程序,产生鬼影

  LedBuff[1] = LedChar[sec/10%10];
  LedBuff[2] = LedChar[sec/100%10];
				   if (sec/100%10==0&&sec/10%10==0)

下面是改进之后的代码,也就是将相关赋值放在中断程序中进行,就能消除鬼影啦(但是有的单片机型号不同值得留意)

#include <reg52.h>

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] = 
{
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char i = 0;
unsigned int cnt = 0;
unsigned char flag = 0;
unsigned long sec = 0;
void main()
{
	
	EA=1;ENLED=0;ADDR3=1;TMOD=0X01;
	TH0=0XFC;TL0=0X67;ET0=1;TR0=1;
	while(1);
}

void InterruptTimer0() interrupt 1
{
		  	LedBuff[3] = 0x40;
            LedBuff[4] = 0x4F;
            LedBuff[5] = 0x5B;
		if(flag==1)
		{
			flag=0;sec++;
			LedBuff[0] = LedChar[sec%10];
            LedBuff[1] = LedChar[sec/10%10]; 
            LedBuff[2] = LedChar[sec/100%10];
				   if (sec/100%10==0&&sec/10%10==0){
						LedBuff[2] = 0xFF;
						LedBuff[1] = 0xFF;
						}
				   if (sec/100%10==0&&sec/10%10!=0){
						LedBuff[2] = 0xFF;
						}            
		}
	TH0 = 0XFC;
	TL0 = 0X67;
	cnt++;
	if(cnt >= 1000){
	cnt = 0;
	flag = 1;
	}
	P0=0X00;
	switch (i)
       {
        case 0: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=~LedBuff[0]; break;
        case 1: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=~LedBuff[1]; break;
        case 2: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=~LedBuff[2]; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[3]; break;
        case 4: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[4]; break;
        case 5: ADDR2=0; ADDR1=0; ADDR0=0; i=0; P0=LedBuff[5]; break;
        default: break;
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值