时钟及规定时间闹钟

题目要求:用按键设定时钟的时、分、秒。要求用4键方式,即选择、加、减、确认键,选择键用于选择修改起始时、分、秒值,每按一次,被修改数码管顺序移动并闪烁。用+,- 键修改数值,确认键确定修改结束。用扫描方式动态显示时、分、秒,第2,4 数码管加小数点,并且要求第4数码管小数点每秒闪烁一次。可以设置闹钟,到时间蜂鸣器报警

难点及技巧:

1、通过在定时器中断来设置标志位来控制数码管的闪烁
2、八位数码管小数点的点亮,0x80,通过或与句(|0x80)
3、数码管的闪烁,通过if语句,对标志位进行求余(闪烁,对2求余即可)

话不多说,直接看代码

代码讲解:

源代码:

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include<intrins.h> typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;sbit LSA=P2^2;			  //38译码器
sbit LSB=P2^3;
sbit LSC=P2^4;sbit buzz=P2^5;	 //蜂鸣器sbit k1=P3^1;  //选择键
sbit k2=P3^0;  //加一				
sbit k3=P3^2;  //减一 
sbit k4=P3^3;  //确认健//数码表
u8 code lzl[17]={    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79, 0x71};u8 ssec,sec,min,hour; //毫秒,秒,分,时
u8 model,sign;    //标志位
u8 wei[8];u8 uhour=0,umin=0,usec=5;	   //闹钟时间设定void delay(u16 i);	  //延时函数
void Timer0Init();	  //中断函数初始化
void display();	      //动态显示
void show();	      //显示数码管
void key_scan();      //按键功能    k1:选择健   k2:加一   k3:减一   k4:确认健
void start();         //函数总和void delay(u16 i)	 //延时函数
{while(i--);	
}void Timer0Init()
{TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。TH0=0Xd8;	//给定时器赋初值,定时10msTL0=0Xf0;	ET0=1;//打开定时器0中断允许               //注:稍后用K2控制总中断,实现暂停功能EA=1;//打开总中断	TR0=1;//打开定时器				 防止未按就计时
}//动态显示函数
void display(){u8 i;for(i=0;i<8;i++){switch(i)	 //位选,选择点亮的数码管,{case(0):LSA=1;LSB=1;LSC=1; break;case(1):LSA=0;LSB=1;LSC=1; break;case(2):LSA=1;LSB=0;LSC=1; break;case(3):LSA=0;LSB=0;LSC=1; break;case(4):LSA=1;LSB=1;LSC=0; break; case(5):LSA=0;LSB=1;LSC=0; break;case(6):LSA=1;LSB=0;LSC=0; break;case(7):LSA=0;LSB=0;LSC=0; break;	}P0=wei[i];			//发送段码delay(100); 		//间隔一段时间扫描	P0=0x00;}}//记录数码管显示void show()		{wei[2]=0;wei[5]=0;switch(model){case 0:{wei[0]=lzl[hour/10];		if(sign%2==0)						wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];break;}case 1:{if(sign%2==0){								wei[0]=lzl[hour/10];		if(sign%2==0)wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=0x00;wei[7]=0x00;}else{							 wei[0]=lzl[hour/10];		if(sign%2==0)wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];}break;}case 2:					  {if(sign%2==0){wei[0]=lzl[hour/10];						if(sign%2==0)wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=0x00;wei[4]=0x00|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];}else{wei[0]=lzl[hour/10];		if(sign%2==0)wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];}}break;case 3:{if(sign%2==0)										   {wei[0]=0x00;		if(sign%2==0)wei[1]=0x00|0x80;elsewei[1]=0x00;wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];}else{wei[0]=lzl[hour/10];		if(sign%2==0)wei[1]=lzl[hour%10]|0x80;elsewei[1]=lzl[hour%10];wei[3]=lzl[min/10];wei[4]=lzl[min%10]|0x80;wei[6]=lzl[sec/10];wei[7]=lzl[sec%10];}break;}}}//按键扫描及处理void key_scan(){if(k1==0){delay(1000);if(k1==0){model++;while(!k1);if(model==4)model=0;}}if(k2==0){delay(1000);if(k2==0){if(model==1)		//修改秒{sec++;	if(sec>=60)sec=0;}else if(model==2)	//修改分钟{min++;	if(min>=60)min=0;}else if(model==3)	//修改小时{hour++;	if(hour>=24)hour=0;}while(!k2);}}if(k3==0){delay(1000);if(k3==0){if(model==1)		//修改秒{sec--;	if(sec==255)sec=59;}else if(model==2)	//修改分钟{min--;	if(min==255)min=59;}else if(model==3)	//修改小时{hour--;	if(hour==255)hour=23;}while(!k3);}}if(k4==0)				  //恢复初态{delay(1000);if(k4==0)model=0;while(!k4);}if(min==umin)				//闹钟,自己定义时间{if(hour==uhour){if(sec==usec){buzz=~buzz;}}}}void start()
{display();show();key_scan();	
}//主函数
void main()
{Timer0Init(); //设置外部中断	while(1){start();}}void Timer0() interrupt 1
{TH0=0Xd8;	//给定时器赋初值,定时10msTL0=0Xf0;ssec++;if(ssec>=100)  //1s{ssec=0;sec++;sign++;if(sec>=60){sec=0;min++;if(min>=60){	  min=0;hour++;if(hour>=24){hour=0;}}}	}}