串口程控时钟设计

设计要求:

1、定时器T0,方式2,实现一次定时200us。中断5000次实现定时1s,作为计时的秒时间。

2、数码管显示时、分、秒,24小时制,时(0~23),分(0~59),秒(0~59)。显示格式hh-mm-ss。

3、通过按键设置当前时间和闹钟时间。

4、闹钟时间到蜂鸣器鸣响10秒,10秒后自动停止鸣响。

5、单片机串口和PC机串口通信,设置单片机串口波特率4800bps,1位起始位,8位数据位,1位停止位,无奇偶校验位。

PC通过串口给单片机发送命令设置当前时间,命令格式如下:

SetTime:hh-mm-ss\r\n

单片机收到后回复PC机SetTime OK\r\n

PC通过串口给单片机发送命令设置闹钟时间,命令格式如下:

Set Alarm:hh-mm-ss\r\n

单片机收到后回复PC机Set Alarm OK\r\n

 /*********************************************************************************
 *********************************************************************************/
 //------------------------------------------------------------------------------//
 //																				                                       
 //
 //标题:程控闹钟设计								 									 									         
 //
 //创建人:朽木自雕i		[email protected]														 						 
 //
 //日期:2021/12/09				修改日期:2021/12/10													 		     
 //
 //设计要求:																										 								 
 //
 //  1、定时器T0,方式2,实现一次定时200us。中断5000次实现定时1s,作为计时的秒时 
 //     间。
 //  2、数码管显示时、分、秒,24小时制,时(0~23),分(0~59),秒(0~59)。
 //     显示格式hh-mm-ss。
 //  3、通过按键设置当前时间和闹钟时间。
 //  4、闹钟时间到蜂鸣器鸣响10秒,10秒后自动停止鸣响。
 //  5、单片机串口和PC机串口通信,设置单片机串口波特率4800bps,1位起始位,8位数
 //     据位,1位停止位,无奇偶校验位。
 //     PC通过串口给单片机发送命令设置当前时间,命令格式如下:
 //     SetTime:hh-mm-ss\r\n
 //     单片机收到后回复PC机SetTime OK\r\n
 //     PC通过串口给单片机发送命令设置闹钟时间,命令格式如下:
 //     Set Alarm:hh-mm-ss\r\n
 //     单片机收到后回复PC机Set Alarm OK\r\n。			                       //
 //操作描述:			                            			                             
 //
 //   1、按K3按键进入设置模式,依次为:时钟页面(秒>分>时)>闹钟页面(秒>分>时)>退出//
 //   2、按K4按键对相应时钟选择进行加操作                                         //
 //   3、用串口对单片机时钟更改参考上述设计要求第五点                              //
 //注:因在普中科技单片机开发试验上完成此设计,所以电路请参考有关原理图。            //
 //                                                                            //
 //声明:									 									 									 									 
 //
 //      以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处,		   //
 //      如有商业用途请与作者联系。																					     
 //
 //																													  							 	   
 //
 //------------------------------------------------------------------------------//
 /*********************************************************************************
 *********************************************************************************/
 
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit KEY1 = P3^2;
sbit KEY2 = P3^3;
sbit BEEP = P1^5;

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};//显示0~F的值

u16 Time_tt = 0,Time_tt_1 = 0,Beep_tt = 0;  //定义一些时间变量,实现在定时器里自加功能
u16 Time_Shi = 23,Time_Fen = 59,Time_Miao = 50;  //定义时钟时分秒
u16 Time_Nao_Shi = 0,Time_Nao_Fen = 0,Time_Nao_Miao = 0;  //定义闹钟时分秒
u16 Time_Shi_fla,Time_Fen_fla,Time_Miao_fla;    //定义时钟时分秒暂存变量
u16 Time_Nao_Shi_fla,Time_Nao_Fen_fla,Time_Nao_Miao_fla;    //定义闹钟时分秒暂存变量
u8 dis_buff[8];   //数码管位显示数组
u8 SheZhi = 0;    //设置标志位
u8 beep_kai = 0;  //蜂鸣器开标志位
u8 SMG_Shan = 0;  //数码管闪标志位
 
unsigned char Tx_buf[30];   //定义发送字符存储数组
unsigned char Rx_buf[30];   //定义接收字符存储数组
unsigned int Receive_num = 0;
unsigned char Receive_Flag = 0,Receive_Over = 0;
 
/*******************************************************************************
                           //---定义全局函数---//
*******************************************************************************/
void Timer0Init(void);		//200微秒@11.0592MHz
void delay(u16 i);      //延时1us函数
void DelayMs(u16 n);     //延时1ms函数
void keyscan();         //按键函数
void DigDisplay(u8* dis_dat,u8 num);  //数码管显示函数 
void Nao_Beep();      //闹钟报警函数
void UsartInit();     //串口初始化函数
void SendString(unsigned char *str);    //字符串显示函数
void SendByte(unsigned char dat);    //字节显示函数
		
		
/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	UsartInit();  //	串口初始化
	Timer0Init();
	
	while(1)
	{	
		keyscan();
		Nao_Beep();
		DigDisplay(dis_buff,sizeof(dis_buff));  //数码管显示函数
		if(SheZhi == 0)
		{
			if(Receive_Over==1)
			{
				Receive_Over=0;
				Receive_num=0;
				//SetTime:hh-mm-ss\r\n
				if((Rx_buf[0]=='S')&&(Rx_buf[1]=='e')&&(Rx_buf[2]=='t')&&(Rx_buf[3]=='T')
				&&(Rx_buf[4]=='i')&&(Rx_buf[5]=='m')&&(Rx_buf[6]=='e')&&(Rx_buf[7]==':')
				&&(Rx_buf[10]=='-')&&(Rx_buf[13]=='-')&&(Rx_buf[16]=='\r')&&(Rx_buf[17]=='\n'))
				{
					Time_Shi_fla = (((Rx_buf[8]-48)*10)+(Rx_buf[9]-48));dis_buff[5]= 10;
					Time_Fen_fla = (((Rx_buf[11]-48)*10)+(Rx_buf[12]-48));dis_buff[2]= 10;
					Time_Miao_fla = (((Rx_buf[14]-48)*10)+(Rx_buf[15]-48));
					if(((Time_Shi_fla >= 0)&&(Time_Shi_fla <= 23))&&((Time_Fen_fla >= 0)&&(Time_Fen_fla <= 59))&&((Time_Miao_fla >= 0)&&(Time_Miao_fla <= 59)))
					{
						Time_Shi = Time_Shi_fla;
						Time_Fen = Time_Fen_fla;
						Time_Miao = Time_Miao_fla;
						SendString("SetTime OK\r\n");
					}
				}	
				//Set Alarm:hh-mm-ss\r\n
				else if((Rx_buf[0]=='S')&&(Rx_buf[1]=='e')&&(Rx_buf[2]=='t')&&(Rx_buf[3]==' ')
				&&(Rx_buf[4]=='A')&&(Rx_buf[5]=='l')&&(Rx_buf[6]=='a')&&(Rx_buf[7]=='r')
				&&(Rx_buf[8]=='m')&&(Rx_buf[9]==':')&&(Rx_buf[12]=='-')&&(Rx_buf[15]=='-')
				&&(Rx_buf[18]=='\r')&&(Rx_buf[19]=='\n'))
				{
					Time_Nao_Shi_fla = (((Rx_buf[10]-48)*10)+(Rx_buf[11]-48));dis_buff[5]= 10;
					Time_Nao_Fen_fla = (((Rx_buf[13]-48)*10)+(Rx_buf[14]-48));dis_buff[2]= 10;
					Time_Nao_Miao_fla = (((Rx_buf[16]-48)*10)+(Rx_buf[17]-48));
					if(((Time_Nao_Shi_fla >= 0)&&(Time_Nao_Shi_fla <= 23))&&((Time_Nao_Fen_fla >= 0)&&(Time_Nao_Fen_fla <= 59))&&((Time_Nao_Miao_fla >= 0)&&(Time_Nao_Miao_fla <= 59)))
					{
						Time_Nao_Shi = Time_Nao_Shi_fla;
						Time_Nao_Fen = Time_Nao_Fen_fla;
						Time_Nao_Miao = Time_Nao_Miao_fla;
						SendString("Set Alarm OK\r\n");
					}
				}	
			}
			dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
			dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
			dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
		}
		else if(SheZhi == 1)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
			}
			else 
			{
				dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= 11;dis_buff[0]= 11;
			}
		}
		else if(SheZhi == 2)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
			}
			else 
			{
				dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= 11;dis_buff[3]= 11;dis_buff[2]= 10;
				dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
			}
		}
		else if(SheZhi == 3)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Shi/10;dis_buff[6]= Time_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
			}
			else 
			{
				dis_buff[7]= 11;dis_buff[6]= 11;dis_buff[5]= 10;
				dis_buff[4]= Time_Fen/10;dis_buff[3]= Time_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Miao/10;dis_buff[0]= Time_Miao%10;
			}
		}
		else if(SheZhi == 4)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Nao_Shi/10;dis_buff[6]= Time_Nao_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Nao_Fen/10;dis_buff[3]= Time_Nao_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Nao_Miao/10;dis_buff[0]= Time_Nao_Miao%10;
			}
			else 
			{
				dis_buff[7]= Time_Nao_Shi/10;dis_buff[6]= Time_Nao_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Nao_Fen/10;dis_buff[3]= Time_Nao_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= 11;dis_buff[0]= 11;
			}
		}
		else if(SheZhi == 5)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Nao_Shi/10;dis_buff[6]= Time_Nao_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Nao_Fen/10;dis_buff[3]= Time_Nao_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Nao_Miao/10;dis_buff[0]= Time_Nao_Miao%10;
			}
			else 
			{
				dis_buff[7]= Time_Nao_Shi/10;dis_buff[6]= Time_Nao_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= 11;dis_buff[3]= 11;dis_buff[2]= 10;
				dis_buff[1]= Time_Nao_Miao/10;dis_buff[0]= Time_Nao_Miao%10;
			}
		}
		else if(SheZhi == 6)
		{
			if(Time_Miao%2 == 0)
			{
				dis_buff[7]= Time_Nao_Shi/10;dis_buff[6]= Time_Nao_Shi%10;dis_buff[5]= 10;
				dis_buff[4]= Time_Nao_Fen/10;dis_buff[3]= Time_Nao_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Nao_Miao/10;dis_buff[0]= Time_Nao_Miao%10;
			}
			else 
			{
				dis_buff[7]= 11;dis_buff[6]= 11;dis_buff[5]= 10;
				dis_buff[4]= Time_Nao_Fen/10;dis_buff[3]= Time_Nao_Fen%10;dis_buff[2]= 10;
				dis_buff[1]= Time_Nao_Miao/10;dis_buff[0]= Time_Nao_Miao%10;
			}
		}	
	}		
}
/*******************************************************************************
* 函数名         :Nao_Beep()
* 函数功能		   :蜂鸣器报警函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Nao_Beep()
{
	if((Time_Shi==Time_Nao_Shi)&&(Time_Fen==Time_Nao_Fen)&&(Time_Miao==Time_Nao_Miao))
	{
		beep_kai = 1;
	}
}
/*******************************************************************************
* 函数名         :Timer0Init(void)		//200微秒@11.0592MHz
* 函数功能		   :设置定时器0,工作方式2
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Timer0Init(void)		//200微秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x02;		//设置定时器模式
	TL0 = 0x48;		//设置定时初值
	TH0 = 0x48;		//设置定时重载值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;ET0 = 1;
}
/*******************************************************************************
* 函 数 名: DelayMs
* 函数功能: 延时函数,n=1时,大约延时1ms
*******************************************************************************/
void DelayMs(u16 n)
{
	u16 i;
	while(n--)
	for(i=0;i<113;i++);
}
/*******************************************************************************
* 函 数 名: delay
* 函数功能: 延时函数,n=1时,大约延时1us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函数名         :keyscan()
* 函数功能		   :按键扫描函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void keyscan()
{
	if(KEY1 == 0)
	{
		DelayMs(5);
		if(KEY1 == 0)
		{
			if(SheZhi == 0)SheZhi = 1;
			else if(SheZhi == 1)SheZhi = 2;
			else if(SheZhi == 2)SheZhi = 3;
			else if(SheZhi == 3)SheZhi = 4;
			else if(SheZhi == 4)SheZhi = 5;
			else if(SheZhi == 5)SheZhi = 6;
			else if(SheZhi == 6)SheZhi = 0;
		}
		while(!KEY1);
	}
	else if(KEY2 == 0)
	{
		DelayMs(5);
		if(KEY2 == 0)
		{
			if(SheZhi == 1)
			{
				if(Time_Miao >= 59)Time_Miao = 0;
				else Time_Miao++;
			}
			else if(SheZhi == 2)
			{
				if(Time_Fen >= 59)Time_Fen = 0;
				else Time_Fen++;
			}
			else if(SheZhi == 3)
			{
				if(Time_Shi >= 23)Time_Shi = 0;
				else Time_Shi++;
			}
			else if(SheZhi == 4)
			{
				if(Time_Nao_Miao >= 59)Time_Nao_Miao = 0;
				else Time_Nao_Miao++;
			}
			else if(SheZhi == 5)
			{
				if(Time_Nao_Fen >= 59)Time_Nao_Fen = 0;
				else Time_Nao_Fen++;
			}
			else if(SheZhi == 6)
			{
				if(Time_Nao_Shi >= 23)Time_Nao_Shi = 0;
				else Time_Nao_Shi++;
			}
		}
		while(!KEY2);
	}
}
/*******************************************************************************
* 函数名         : Time0() interrupt 1
* 函数功能		   : 定时器中断函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Time0() interrupt 1
{
	Time_tt++;
	if(Time_tt == 100)
	{
		Time_tt_1++;
		if(Time_tt_1 == 50)
		{
			if(Time_Miao >= 59)
			{
				Time_Miao = 0;
				if(Time_Fen >= 59)
				{
					Time_Fen = 0;
					if(Time_Shi >= 23)
					{
						Time_Shi = 0;
					}
					else Time_Shi ++;
				}
				else Time_Fen ++;
			}
			else Time_Miao++;
			Time_tt_1 = 0;
		}
		Time_tt = 0;
	}
	if(beep_kai == 1)
	{
		Beep_tt++;
		BEEP = ~BEEP;
		if(Beep_tt == 50000)
		{
			beep_kai = 0;Beep_tt = 0;
		}		
	}
	if(Receive_Flag>=1)
	{
		Receive_Flag++;
		if(Receive_Flag>=30)
		{
			Receive_Flag=0;
			Receive_Over=1;
		}
	}
}
/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能		   : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay(u8* dis_dat,u8 num)
{
	u8 i;
	for(i=0;i<num;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第1位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第2位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第3位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第4位
			case(4):
				LSA=0;LSB=0;LSC=1; break;//显示第5位
			case(5):
				LSA=1;LSB=0;LSC=1; break;//显示第6位
			case(6):
				LSA=0;LSB=1;LSC=1; break;//显示第7位
			case(7):
				LSA=1;LSB=1;LSC=1; break;//显示第8位
		}
		P0=smgduan[dis_dat[i]];//发送段码
		delay(1); //间隔一段时间扫描	
		P0=0x00;//消隐
	}
}
/*******************************************************************************
* 函数名         :UsartInit()
* 函数功能		   :设置串口
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void UsartInit()
{
	TMOD=0X20;			//设置计数器工作方式2
	TH1=0XF3;				//计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
	TR1=1;					//打开计数器
	
	SCON=0X50;			//设置为工作方式1
	PCON=0X80;			//波特率加倍
	
	ES=1;						//打开接收中断
	EA=1;						//打开总中断
}
/*******************************************************************************
* 函数名         : Usart() interrupt 4
* 函数功能		   : 串口通信中断函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Service_Uart() interrupt 4
{
	if(RI)
	{
		Rx_buf[Receive_num]=SBUF;
		Receive_num++;
		Receive_Flag = 1;
		RI=0;
	}
}
/*******************************************************************************
* 函数名         : SendByte(unsigned char dat)
* 函数功能		   : 写字节
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void SendByte(unsigned char dat)
{
	SBUF = dat;
	while(TI == 0);
	TI = 0;
}
/*******************************************************************************
* 函数名         :SendString(unsigned char *str)
* 函数功能		   : 写字符串
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void SendString(unsigned char *str)
{
	while(*str !='\0')
	{
		SendByte(*str++);
	}
}

操作描述:                                                                                 

1、按K3按键进入设置模式,依次为:时钟页面(秒>分>时)>闹钟页面(秒>分>时)>退出;

2、按K4按键对相应时钟选择进行加操作;  

3、用串口对单片机时钟更改参考上述设计要求第五点;

注:因在普中科技单片机开发试验上完成此设计,所以电路请参考有关原理图。

                           原创不易,分享需要勇气,被支持会多一些动力~❤

猜你喜欢

转载自blog.csdn.net/qq_45385706/article/details/121863296