KST-51单片机:c语言编程实现数码管动态显示秒表的倒计时

/*60S倒计时*/
/*个位每1S变一次,从0~9*/
/*十位,个位为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
};

void main()
{
	unsigned int cnt=0; //记录中断次数
	unsigned int sec=0; //记录秒数
	unsigned char g=0;   //个位数码管
	unsigned char s=6;   //十位数码管 

	ENLED=0;			 //使能U3 选中数码管DS1
	TMOD=0x01;			 //T0为模式1
	TH0=0xB8;			 //T0赋初值0xB800
	TL0=0x00;
	TR0=1;				 //启动T0

	while(1)
	{
		ADDR3=1;
		P0=0xff;
		ADDR2=0;
		ADDR1=0;
		ADDR0=0;
		P0=LedChar[g];   //选中个位数码管
				
		if(TF0==1)		 //判断T0是否溢出
		{
			TF0=0;		 //T0溢出后清零中断标志
			TH0=0xB8;        //并重新赋值
			TL0=0x00;
			cnt++;
		}
		if(cnt>=50)	  //判断溢出是否达到50次
		{
			cnt=0;    //达到五十次(1s)清零
			sec--;    //秒数累加
		}

		P0=0xff;
		ADDR0=1;
		P0=LedChar[s];   //选中十位数码管,并显示当前秒数下的数字

		if(s==0&&g==0)    //避免00状态的出现,状态60~60时间为60s
			s=6;
		if(g==0&&sec%10==1)
			s--;
		if(sec%10!=0)
		{
			g=10-sec%10;
		}
		if(sec%10==0)
		{
			g=0;
		}
	}
}

(1)实际上数码管状态变化为01~00~60,只不过00存在的时间过短,无法被人眼识别。

(2)在切换数码管前先让 P0=0xff 避免了前一个数码管留下的余辉。

 

上面程序较为繁琐,以下为更新程序:

/*60倒计时*/


#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
};

unsigned int cnt=0;     //记录中断次数
unsigned char flag=0;   //中断标志位
unsigned char i=0;	//遍历
unsigned char g=0xff;   //初始化个位数码管
unsigned char s=0xff;   //初始化十位数码管
unsigned int sec=61;    //秒数

void main()
{

	EA=1;           //定时器总中断
	ENLED=0;	//?使能U3
	ADDR3=1;        //T0模式为1
	TMOD=0x01;	//定时1ms
	TH0=0xfc;	
	TL0=0x67;
	ET0=1;
	TR0=1;		//启动T0

	while(1)
	{
		if(flag==1)            //中断标志
		{		
			g=sec%10; 
			s=sec/10;
			flag=0;        //标志清0
			if(sec==0)     //重新倒计时
				sec=61;

		}
	}
}
void InterruptTimer0() interrupt 1
{
	TH0=0xfc;			 //重新赋值
	TL0=0x67;
	cnt++;
	if(cnt>=1000)	  //中断累计1000 1s
	{
		cnt=0;    //清0
		flag=1;
		sec--;    //秒数自减	
	}
	P0=0xff;
	switch(i)
	{
		case 0:ADDR0=0;ADDR1=0;ADDR2=0;P0=LedChar[g];i++;break;   //选中个位数码管
		case 1:ADDR0=1;ADDR1=0;ADDR2=0;P0=LedChar[s];i=0;break;   //选中十位数码管
		default:break;
	}
}

改进后,程序更为简洁直观。采用中断+switch遍历优化程序。

注意:遍历中,为了使几个数码管看起来像是同时亮,故大大缩短了定时时间,由20ms变为1ms。

  • 16
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值