课程设计题三:日历和数字钟

要求:

1、数字钟:时、分,小时用二十四进制显示,分钟用六十进制显示。

2、显示采用动态数码管显示方式

3、动态时显示六位:时 分 秒 用按键可切换显示年月日

4、具有清零的功能,且能够对小时、分钟进行调整(校时)。

5、具有整点、半点报时功能,整点用声音次数报时,半点特殊声音报时。

获取该 程序+protues 的方式:

1、CSDN下载:

https://download.csdn.net/download/qq_38351824/11274668

2、关注微信公众号下载:

     ① 关注微信公众号:Tech云  

     ②

3、可以关注点赞并在下方评论,我给你邮箱发过去。

一、Protues仿真图:

课程设计题三:日历和数字钟_第1张图片

课程设计题三:日历和数字钟_第2张图片

课程设计题三:日历和数字钟_第3张图片

二、程序源码:

因为注释非常的全,这里就不再进行讲解了。

/*******************************************************************************
================================================================================
【平    台】STC89C51_sumjess平台
【编    写】sumjess
【E-mail  】[email protected]
【软件版本】V2.0
【最后更新】2019年06月10日
【相关信息参考下列地址】
【网    站】
           https://blog.csdn.net/qq_38351824
           http://www.51hei.com/bbs/mcu-2-1.html
---------------------------------------------------------------------------------
【dev.env.】MDK4.02及以上版本
【Target  】STC89C51
第一次修订:2019/05/09
第二次修订:2019/05/21
第三次修订:2019/06/10
【problem 】
    (1)库内补充的不全面;
    (2)库内解释部分不全面;
    (3)库内还存在一定的bug;
【direction】
      下一步的目标就是把库继续集成!
【explain 】
      为了方便使用,我也自己写了很多的库,和优化了算法和表示方式!
【warning】
      目前程序中暂无错误 !   
---------------------------------------------------------------------------------
没有完美的代码,只有不断的奉献,大家一起努力;
赠人玫瑰手留余香,欢迎大家反馈bug!
================================================================================
********************************************************************************/	
#include 		   //52单片机头文件
#include"intrins.h"	 	   //循环移位函数头文件
#define uint unsigned int  // 宏定义
#define uchar unsigned char
#define NOT_Break  25      //任意赋值避开条件
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0XBF,0xff}; //共阳极数码管编码0-9和“—”
uchar val[8]={2,3,10,5,9,10,5,5};

sbit key0 = P0^0;		   //清零
sbit key1 = P0^1;		   //时间---年月日转换
sbit BEEP = P3^7;		   //蜂鸣器

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]=1;
		val[3]=9;
		val[4]=0;
		val[5]=7;		
		val[6]=0;
		val[7]=4;
		 }
		 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;			 
	 }	 
///
	 }			 

}

 

你可能感兴趣的:(北京交通大学海滨学院单片机课设,STC51精通+项目)