c51单片机之利用外部中断实现数字时钟,且具有调时功能

仿真图:

代码段:

/*整体功能:用八位共阳极数目管作电子时钟显示,并用key0位控制进行时分秒位的选择,当按一次时代表选中时位,两次选中分位,三次选中秒位,第四次取消选中时钟正常运行
且选中时该位的小数点会亮代表该位已被选中;key1按键用来对位进行加一操作,key2用来对位进行减一操作*/
#include<reg52.h>
#define uint unsigned int      //重定义,方便使用
#define uchar unsigned char
sbit key0=P3^1;         //位定义,此处赋予key0设置功能,通过对key0的操作来选中时钟的三个位
sbit key1=P3^2;        //赋予key1按一次加一功能
sbit key2=P3^3;        //赋予key2按一次减一功能
sbit DU=P2^0;         //P2^0为段选开关,即数码管段码显示的开关
sbit WE=P2^1;         //P2^1为位选开关,即数码管位数选择的开关
void delay(uint z);    //延时函数
void display();        //数码管显示函数      
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};   //此处用共阳极八段数码管,前十位为0~9显示的段码,第十一个即table[10]为显示位之间的横杠的段码
uchar code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};    //74HC573芯片,第二片控制位选,高四位二进制数决定位选,最高位为第一位。
uchar a[8];    //缓冲区变量,用来存放八个数码管要显示的数字;
uchar hour=05;    //设置小时的初始量为05
uchar minute=21;  //设置分钟的初始量为21
uchar second=00;   //设置秒的初始量为00
uchar n;         //定义变量n ,表示定时器T0的中断次数,以50ms一个中断,要中断20次为一秒
uchar t=0;      //定义变量t,用来统计key0按下的次数,依次为条件对时分秒位进行选中之后的操作
/********延时函数 **********/
void delay(uint z){    //此处延迟函数带一个参数z,这样方便对延迟的控制,也可以不带参数,但那样要改变延迟的话只能对函数内的条件进行改变
  uint j,k;
	for(j=0;j<z;j++)
	for(k=0;k<25;k++);
}
/******数码管显示函数******/
void display (uchar t) {
		uint i;                
	  for(i=0;i<8;i++){
			P0=wei[i];    //先送位选信号,即先选择对哪一位进行显示,由于74HC573芯片的锁存特性,故对此进行一个方波的脉冲信号即可进行数据的锁存,但应先送数据后进行脉冲
			WE=0;
			WE=1; 
			WE=0;           //由于控制位选的芯片和控制段选的信号连接在C51的同一个P0口处,因此当向74HC573送段选信号时,应关闭位选开关
			if(t>0&&t==i){         //此处对key0按下的次数t进行判断,用来让选择的那一位的小数点亮
						P0=table[a[i]]&0x7f;     //注意:此处的&为与操作符,目的是让对应的数字和数字的小数点同时点亮
						DU=0;
						DU=1;
						DU=0;	
						delay(10);				
		}
			else{
			P0=table[a[i]];    //对没有选中的位进行段码的输出显示
			DU=0;
			DU=1;
			DU=0;
			delay(10);		   //延迟
		}
		 }
			}
/******主函数*******/
void main () {
	a[2]=a[5]=10;    //让数码管的第3和第6位显示-
	TMOD=0x01;       //由于单次中断定时为50ms,因此应使用16位定时器,对应的工作方式的状态字为01,即TMOD=0x01                 课本P83 表3.2
	TH0=0x3C;        //单片机的晶振频率为12M,定时时间为50ms,对应的时间常数的十六位显示为3CB0,往TH0中送入高八位3C 					课本P86  例
	TL0=0xB0;        //往TL0中送入低八位B0                                                                                   
	IE=0x82;         //IE位的第7位为EA为CPU中断允许标志,第0位为定时器T0中断允许位,将这两位和EX0置1,对应的状态字为0x82    课本P79
	TR0=1;           //启动定时器T0                  课本P83
	IT0=1; 					 //设置外部中断为眺沿触发                课本P78最后一行
	IT1=1;    			 //同理
	while(1){
		display(t);    //开启状态对初始设定值进行显示
		if(key0==0){    //当按键按下时
			t++;          //t自加,记录按下的次数,调时
			EX0=1;        //调时状态下允许外部INT0,INT1中断,即只有按下key0后,再按key1,key2才有作用
			EX1=1;        //用来调小时,分,秒
			if(t>7){      //当调完即跳出选中状态时  
				t=0;        //灭小数点,对计数器归零
				n=0;        //中断次数计数器也归零,准备开始计时
				TR0=1;      //启动计数器T0
				EX0=0;      //关闭外部中断
				EX1=0;
}
			else if(t==2) t=4;  //调分   当按键按下两次后,为了让选中位为分的个位,让t=4,即此时选中数码管的第5位(最左侧为第一位)
			else if(t==5) t=7;  //调秒   同理,选中秒的个位  
			while(key0==0)  display(t);   //等待按键松开
	}
		if(n>=20&&t==0){      //中断20次,1秒到,正常计时状态下时钟计时
			n=0;
			second++;
			if(second>=60){
				second=0;
				minute++;
				if(minute>=60){
					minute=0;
					hour++;
					if(hour>=24)
					 hour=0;
}
		}
				}
    a[0]=hour/10;      //把八位要显示的数字放在a[]中,方便使用
		a[1]=hour%10;
		a[3]=minute/10;
		a[4]=minute%10;
		a[6]=second/10;
    a[7]=second%10;
						}
								}
void T0_0() interrupt 1{    //定时器T0中断服务程序
		TH0=0x3C;
	  TL0=0xb0;              //送时间常数
	  n++;                   //n计数,中断次数加一
}
void INT0_0() interrupt 0{   //外部中断INT0服务程序,为加一操作
	if(t==1){          //调小时
			hour++;       
			if(hour>=24)
			hour=0;
}
	if(t==4){         //调分
		minute++;       
		if(minute>=60)
		minute=0;
}
	if(t==7){          //调秒
		second++;  
		if(second>=60)
		second=0;
}
	}
void INT1_0() interrupt 2{       //外部中断INT1服务程序,为减一操作
	if(t==1){       //调小时
		hour--; 
		if(hour==0xff)
		hour=23;
}
	if(t==4){       //调分钟
		minute--;  
		if(minute==0xff)
		minute=59;
}
	if(t==7){       //调秒
		second--;
		if(second==0xff)
		second=59;
}
	}

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值