设计要求:
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、用串口对单片机时钟更改参考上述设计要求第五点;
注:因在普中科技单片机开发试验上完成此设计,所以电路请参考有关原理图。
❤原创不易,分享需要勇气,被支持会多一些动力~❤