基于51单片机时钟设计—数码管显示

基于51单片机时钟设计

(仿真+程序)

功能介绍

具体功能:

1.采用数码管显示时间时-分-秒;

2.可按键设置时分秒、清零;

3.可按键切换至显示年月日;

4.年月日和初始时间可在程序中修改;

​演示视频:

基于51单片机时钟设计—数码管显示 

添加图片注释,不超过 140 字(可选)

程序

#include<reg52.h> 		   //52单片机头文件
/***微信公众号:木子单片机********/



uchar wei=0X01,duan=0;
void smg()//数码管扫描送显示函数
{
	P1=wei;     		   // 选择要点亮的数码管是哪一个
	P2=table[val[duan]];   // 给改数码管送显示数据
    wei=_crol_(wei,1);     // 移位,为点亮下一个数码管做准备
	duan++;				 
	if(duan>7)	duan=0;	  
} 

void delay(uint z)	 //1毫秒
{
	uint x,y;
    for(x=z;x>0;x--)
      for(y=110;y>0;y--);   
}

void time0init()	   //  定时器0初始化函数
{
	TMOD=0x01;					//设置定时器0为工作方式1(M1M0为01)
	TH0=(65536-2000)/256;		//装初值12M晶振定时2ms数为2000
	TL0=(65536-2000)%256;
	EA=1;						//开总中断
	ET0=1;						//开定时器0中断
	TR0=1;						//启动定时器0
}

uint num=0,keytime=0,time;		//时间更新  1s,20ms扫描一次按键, 控制修改项闪烁
void time0() interrupt 1
{
	TH0=(65536-2000)/256;		//装初值12M晶振定时2ms数为2000
	TL0=(65536-2000)%256;
	keytime++;					//20ms扫描一次按键
	time++;						//控制修改项闪烁
	num++;						//时间更新  1s
	smg();
}  

 
 uchar key()
{			   
  static  uchar kzt=0;	 //推动循环,每次执行一次case
  uchar sb=NOT_Break;	 //任意赋值避开条件
  switch(kzt)			 //按顺序依次执行
  {
//------------case 0:------------//
	 case 0:			 //第一步
	 P3=0xff;			 //P3做读入状态时,应该要先写1的,才能正确读入数据	 
                         //按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
	 if(P3!=0xff)		 //如果有按键按下
	 {
		 kzt=1;			 //向下执行第二步
		 return NOT_Break;		 //返回一个无关的值,用来跳出此次循环	
		}
	 break;				 //如果没有按键按下,直接跳出
//------------case 1:------------//
	case 1:				 //第二步
	P3=0xff;			 //P3做读入状态时,应该要先写1的,才能正确读入数据	 
                         //按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
	if(P3!=0xff)		 //有按键按下
	{
		switch(P3)
		{
		 case 0xfe:		 //第一个按键按下
		 sb=0;
		 break;			 //直接跳出
		 case 0xfd:		 //第二个按键按下
		 sb=1;
		 break;			 //直接跳出
		 case 0xfb:		 //第三个按键按下
		 sb=2;
		 break;		 	 //直接跳出	 
		 case 0xf7:	     //第四个按键按下
		 sb=3;
		 break;			 //直接跳出			 			 				 								
		}
	kzt=2;				 //如果无按键按下  向下执行第三步
	return sb;			 //返回sb的值
 	}
	 else				 //如果无按键按下  回到第一步
	 {
	  kzt=0;
	  return NOT_Break;	 //返回一个无关的值,用来跳出此次循环	
	  }
	break;
//------------case 2:------------//
	case 2:				 //第三步
	P3=0xff;			 //P3做读入状态时,应该要先写1的,才能正确读入数据	 
                         //按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
	if(P3==0xff)		 //如果没有按键按下
	{
	 kzt=0;				 //如果无按键按下  回到第一步
	 return NOT_Break;
	 }			 
	 break;				 //如果有按键按下  直接跳出
		}			
	return NOT_Break;	
 }
	
	

void main()
{  
   char shi=23,fen=59,miao=55,qh=0;	  //初始化时分秒   状态标志位(0:正常,1:改变秒钟,2:改变分钟,3:改变时钟)
   char flag=0;						  //标志位---年月日&&时分秒
   char keycode=NOT_Break;			  //键值
   P0=0xff;
   P1=0xff;
   P2=0xff;
   P3=0xff;
   delay(10);						  //保证上面三条指令顺利完成
   time0init();						  //定时器0初始化函数
   while(1)	
	{ 	
	    if(key0==0)				      //清零按键按下
		{
		  shi=0;fen=0;miao=0;		  //时分秒清零
		  qh=0;						  //开始显示
		  }
	    if(key1==0)				      //年月日&&时分秒按键按下
		{
		  while(!key1);				  //等待放开按键
		  if(flag==0) flag=1;		  //年月日&&时分秒
		  else  flag=0;  
		  qh=0;						  //开始显示
		  }		  	    
	    if(keytime>9)				  //2ms*10=20ms
		{
		  keytime=0;				  //计数清零
		  keycode=key(); 			  //检测是否有按键按下		 
		}
//---时间更新---//		
		 if((num>=500)&&(qh==0))	 //时间更新	 2ms*500=1s
		 {
			num=0;					 //计数清零
			miao++;					 //秒数加1
			if(miao>59)				 //如果miao等于60
			{
				miao=0;				 //miao赋值为0
				fen++;				 //分钟加1
				if(fen>59)			 //如果fen等于60
				{
					fen=0;			 //fen赋值为0
					shi++;			 //小时加1
					if(shi>23) shi=0;//如果shi等于24  shi赋值为0
				}
			}
		 }
///		

//---按键检测---///

///---第一个按键按下---///
	  if(keycode==0)		 //第一个按键按下	选择
	  {
		qh++;				 //状态标志位(0:正常,1:改变秒钟,2:改变分钟,3:改变时钟)
		if(qh>3) qh=1;    	 //如果qh等于4,qh赋值为1		 
		keycode=NOT_Break;	 //任意赋值避开条件
		}
///---第二个按键按下---///
	  if(keycode==1)		  //第二个按键按下	  加
       {
		if(qh==1)
        {
		   miao++; 					
           if(miao>59) miao=0;//如果miao等于60 miao赋值为0
		 		 
	   	 }
        if(qh==2)
        {
	       fen++;				
          if(fen>59) fen=0;   //如果fen等于60 fen赋值为0
	 		 
    	}
       if(qh==3)
        {
	     shi++;					
         if(shi>23)shi=0;	  //如果shi等于24 shi赋值为0	 		 
   	   }
	   keycode=NOT_Break;	  //任意赋值避开条件
	  }
///---第三个按键按下---///
	if(keycode==2)			   //第三个按键按下	  减
       {
		if(qh==1)
        {
		   miao--; 					
           if(miao<0)  miao=59;//如果miao等于-1 miao赋值为59	 		 
	   	 }
        if(qh==2)
        {
	      fen--;				
          if(fen<0) fen=59;	  //如果fen等于-1 fen赋值为59		 
    	}
       if(qh==3)
        {
	      shi--;					
         if(shi<0) shi=23;	  //如果shi等于-1 shi赋值为23	 		 
   	   }
	   keycode=NOT_Break;	  //任意赋值避开条件
	  }	
///---第四个按键按下---///	  
	   if(keycode==3)		  //第四个按键按下	   确定
	   {
		 qh=0; 		
		 keycode=NOT_Break;	  //任意赋值避开条件
		}
///
		
///---显示函数---///   
	 switch(qh)		 	   //按键按下后立即显示
	 {	
	 //正常显示		 
		case 0:	
		if(flag==1)		 //显示日期 年月日
		{		  
		val[0]=2;
		val[1]=0;
		val[2]=2;
		val[3]=4;
		val[4]=0;
		val[5]=1;		
		val[6]=0;
		val[7]=1;
		 }
		 else
		 {
		val[0]=shi/10;	 //显示时间 时分秒
		val[1]=shi%10;
		val[2]=10;
		val[3]=fen/10;
		val[4]=fen%10;
		if(fen==30) {  BEEP=0;delay(200);BEEP=1; }
		else if(fen==0) {  BEEP=0;delay(100);BEEP=1;} 
		val[5]=10;		
		val[6]=miao/10;
		val[7]=miao%10;
		  }
		break;
	 //秒钟修改后显示  其中秒钟部分在闪烁
		case 1:
		if(time<250)	     //2ms*250=0.5s
		{			 
	    val[0]=shi/10;
		val[1]=shi%10;
		val[3]=fen/10;
		val[4]=fen%10;		
		val[6]=miao/10;
		val[7]=miao%10;		  		 
		 }
		else if(time<500)	 //2ms*500=1s		
		{
	     	val[0]=shi/10;
			val[1]=shi%10;
			val[3]=fen/10;
			val[4]=fen%10;		
			val[6]=11;
			val[7]=11;			
		 }
		else if(time>500)	 //2ms*500=1s
		{ 
			time=0;
		 }									
		break;
	 //分钟修改后显示  其中分钟部分在闪烁
		case 2:
		if(time<250)
		 {
	    val[0]=shi/10;
		val[1]=shi%10;
		val[3]=fen/10;
		val[4]=fen%10;		
		val[6]=miao/10;
		val[7]=miao%10;			 
		 }
		else if(time<500)
		 { 
    	val[0]=shi/10;
		val[1]=shi%10;
		val[3]=11;
		val[4]=11;		
		val[6]=miao/10;
		val[7]=miao%10;			  		  
		 }
		else if(time>500)
		 {
			time=0;
		 }
		 break;
	 //时钟修改后显示  其中时钟部分在闪烁
		 case 3:
		 if(time<250)
			{
		val[0]=shi/10;
		val[1]=shi%10;
		val[3]=fen/10;
		val[4]=fen%10;		
		val[6]=miao/10;
		val[7]=miao%10;				
			}
		else if(time<500) 
		 {
		val[0]=11;
		val[1]=11;
		val[3]=fen/10;
		val[4]=fen%10;		
		val[6]=miao/10;
		val[7]=miao%10;			 		 
		 }
		else if(time>500)
		 {
		 time=0;
		 }
		break;			 
	 }	 
///
	 }			 

}

硬件设计

使用元器件:

单片机:AT89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计!具体如图!

添加图片注释,不超过 140 字(可选)

02程序

本设计使用软件keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

03设计资料

        资料获取请关注同名公众号,全部资料包括程序(含注释)、仿真源文件等。具体内容如下,全网最全!!

添加图片注释,不超过 140 字(可选)

资料获取请观看前面演示视频!

点赞分享一起学习成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值