51单片数字时钟显示(通过串口设置时间和设定闹钟)

本文介绍了如何用单片机通过串口设置时间和闹钟,包括数据帧格式设计、程序编写步骤、LCD显示功能和串口通信的实现。调试过程中注意晶振频率匹配,以确保准确性。
摘要由CSDN通过智能技术生成

 

文章目录

 

概要

用单片机实现数字时钟,要求采用串口进行时钟的设置和对闹钟的设定。

 

整体架构流程

一.首先,我们 ·要确定串口发送的数据帧格式,我这里采用的格式是->

  1.当想发送的是“设置时间”时就发送这个格式的数据帧:S-hour:min:sec\n

  2.当想发送的是“设定闹钟”时就发送这个格式的数据帧:D-hour:min:sec\n

 分析:首个字节是确定发送数据的类型,如果是S就表明是“设置时间”的数据;否则,D就是“设定闹钟”的数据。hour-时、min-分、sec秒,比如你想设定时间从10:11:00开始计时,你就在串口助手中发送这一串字符串:“S-10:11:00\n”,如果想设定闹钟在10:15:00响铃就发送“D-10:15:00\n”来设定闹钟;

d217b40ad2f24711bfa38e41e7b27da0.png

二、数据格式确定好后,咋们就开始编写程序实现我们的功能。

程序设计思路:

  1. 先编写出:数字时钟+LCD显示的功能模块程序
  2. 然后再编写:串口接送的功能模块程序

分析: 分步骤写程序是为了方便我们调试程序

三、烧录程序到开发板上进行调试

STC-ISP是一个既可以下载程序,又可以进行串口调试的软件

404489332b194efd8cb39d1b06927a3e.png

 

代码参考

#include <REG52.H>
#define uchar unsigned char
#define uint unsigned int
#define BUFFER_SIZE 11 // 假设接收缓冲区的大小为10个字节

uchar rx_buffer[BUFFER_SIZE]; // 接收缓冲区
uchar rx_index = 0; // 接收缓冲区索引
sbit  LED=P2^0;
sbit  Beep=P1^5;

sbit RS=P2^6;
sbit RW=P2^5;
sbit E=P2^7;

char hour=0,min=0,sec=0;//时分秒
char D_hour,D_min,D_sec;//闹钟时分秒
uchar con=0;

bit D_flag=0;
void delayms(uint ms)
{
  uchar i;
	while(ms--)
	for(i=0;i<123;i++);

}

void w_com(uchar com)
{
  RS=0;
	RW=0;
	E=1;
	P0=com;
	E=0;
	delayms(1);

}

void w_dat(uchar dat)
{
 RS=1;
	RW=0;
	E=1;
	P0=dat;
	E=0;
	delayms(1);

}

void lcd_init()
{
  delayms(10);
	 w_com(0x38);
	delayms(10);
	 w_com(0x0c);
	delayms(10);
	 w_com(0x06);
	delayms(10);
	 w_com(0x01);
	delayms(10);
	 w_com(0x38);
	delayms(10);
	
}

void T0_inti()//T0定时1s
{
	TMOD&=0xf0;
  TMOD|=0x01;//方式一16位定时器
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	TR0=0;
	ET0=0;
}

void usart ()	  //串口初始化	   配置串口的波特率(T1)
 {
 	SCON=0x50;
	PCON&=0x7f;
	TMOD&=0x0f;
	TMOD|=0x20;

	TH1=0xfd;	//设置串口为9600波特率
	TL1=0xfd;

	ET1=0;
	TR1=1;	//T1定时器启用
	EA=1;  //打开总中断使能
	ES=1;  //打开串口中断使能
 
 }
 
 void ProcessReceivedData(unsigned char *data_d)  
{
	uchar hour_s,hour_g,min_s,min_g,sec_s,sec_g;
	uchar D_hour_s,D_hour_g,D_min_s,D_min_g,D_sec_s,D_sec_g;
	   
		if(data_d[0]=='S')
	 {   TR0=0;
       ET0=0;		 
	     hour_s=data_d[2]-'0';
	     hour_g=data_d[3]-'0';
	    hour=hour_s*10+hour_g;
	
	     min_s=data_d[5]-'0';
	     min_g=data_d[6]-'0';
	    min=min_s*10+min_g;
	
	     sec_s=data_d[8]-'0';
	     sec_g=data_d[9]-'0';
	    sec=sec_s*10+sec_g;	
      	TR0=1	;
        ET0=1;		 
	 }
	 if(data_d[0]=='D')
	 {   D_flag=1;	
	     D_hour_s=data_d[2]-'0';
	     D_hour_g=data_d[3]-'0';
	    D_hour=D_hour_s*10+D_hour_g;
	
	     D_min_s=data_d[5]-'0';
	     D_min_g=data_d[6]-'0';
	    D_min=D_min_s*10+D_min_g;
	
	     D_sec_s=data_d[8]-'0';
	     D_sec_g=data_d[9]-'0';
	    D_sec=D_sec_s*10+D_sec_g;	
      	 
	 }
}
void sentdata()
{
	     uint i;
    for(i=0;i<BUFFER_SIZE;i++)	
	{
	  SBUF=rx_buffer[i];
		while(!TI);
		TI=0;
	}
}


void main()
{
	
  T0_inti();
	lcd_init();  
  usart ();				
	while(1)
	{
	       w_com(0x84);
				 w_dat(hour/10+0x30);
				 w_dat(hour%10+0x30);
		     w_dat(':');
		     w_dat(min/10+0x30);
				 w_dat(min%10+0x30);
		     w_dat(':');
		     w_dat(sec/10+0x30);
				 w_dat(sec%10+0x30);
        if(D_flag)
				{					
				 w_com(0xc0);
				 w_dat(D_hour/10+0x30);
				 w_dat(D_hour%10+0x30);
		     w_dat(':');
		     w_dat(D_min/10+0x30);
				 w_dat(D_min%10+0x30);
		     w_dat(':');
		     w_dat(D_sec/10+0x30);
				 w_dat(D_sec%10+0x30);
		    }
				if((hour==D_hour&&min==D_min&&sec==D_sec)&&D_flag)//闹钟响应函数
				{
									
				     Beep=0;
						delayms(3000);                                                          
						 Beep=1;									
				}
				
	
	}

}

void T0_EX0()interrupt 1//T0用于计时50ms*20=1s
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
    if(++con==20)//1s
	{
		con=0;
		if(++sec==60)//1min
		{
			  sec=0;
				if(++min==60)//1hour
				{		min=0;
						if(++hour==24)//1day
							hour=0;
				}		
		}

  }
	
}

void Serial_ISR() interrupt 4 
{
	
    if (RI) { // 接收中断标志置位
        RI = 0; // 清除接收中断标志			
        rx_buffer[rx_index++] = SBUF; // 将接收到的数据存入缓冲区
        
        // 检查是否接收到完整的数据包(例如,以换行符结束)
        if (rx_buffer[rx_index - 1] == '\n' )
					{
            // 处理接收到的数据
					   sentdata();
						rx_index=0;
            ProcessReceivedData(rx_buffer);
           
         }
			
			
			
    }
		
    
}

调试与结果

下载好程序后,进入窗口调试窗口进行数据的发送。先发送时钟信息,然后再发送闹钟信息

.发送设置时钟的数据

5126dd23d8ab4fceb047cecb7d192851.png

.发送设置闹钟的数据

ae1ba3c68f9a439892a18a3aaf092841.png .实现效果

8bfb770c17fc4849bbcd00b228ce8285.png

小结

提示:如果要用51单片机做出这个效果,硬件这方面晶振一定要是11.0592MHz,如果是开发板上的晶振是12MHz会导致发送的数据丢失、不准确

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是一个简单的c51单片机显示温度的数字电子时钟c语言代码,仅供参考: ```c #include<reg52.h> #include<intrins.h> #include<stdio.h> #define uchar unsigned char #define uint unsigned int typedef unsigned char BYTE; typedef unsigned int WORD; sbit DSPORT=P3^7; sbit DS18B20=P3^6; uchar temperature; // 存储温度值 uchar Tempdata[2]; // 存储DS18B20返回的温度数据 uchar code table[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, // 0~9的数码管编码 0x77,0x7c,0x39,0x5e,0x79,0x71 // A~F的数码管编码 }; uchar code Weekday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; uchar code Month[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; uchar hour,minute,second; // 存储时分秒 uchar hour_disp,minute_disp,second_disp; // 存储时分秒的显示值 uchar hour_alarm,minute_alarm; // 存储闹钟的时分值 uchar alarm_flag; // 闹钟响铃标志 uchar display_flag; // 显示标志 uchar key_code; // 存储按键值 uchar key_status; // 存储按键状态 uchar key_hold; // 存储按键长按状态 void delay(int time) // 延时函数 { int i,j; for(i=0;i<time;i++) for(j=0;j<110;j++); } void ds_init() // DS18B20的初始化 { uchar i=0; DS18B20=1; DSPORT=0; i++; i++; i++; i++; i++; DSPORT=1; i++; i++; DS18B20=DSPORT; i++; i++; if(DS18B20==0) { i=0; while(!DS18B20 && i<200) // 等待DS18B20拉低 { i++; delay(1); } i=0; while(DS18B20 && i<240) // 等待DS18B20拉高 { i++; delay(1); } } } void ds_write_byte(uchar dat) // 向DS18B20写入一个字节的数据 { uchar i; for(i=0;i<8;i++) { DSPORT=0; _nop_(); _nop_(); DSPORT=dat&0x01; // 写入最低位的数据 dat>>=1; _nop_(); _nop_(); DSPORT=1; } } uchar ds_read_byte() // 从DS18B20读取一个字节的数据 { uchar i,dat=0; for(i=0;i<8;i++) { DSPORT=0; _nop_(); _nop_(); dat>>=1; if(DS18B20) dat|=0x80; // 读取最低位的数据 _nop_(); _nop_(); DSPORT=1; } return dat; } void ds_start() // 向DS18B20发送开始信号 { DS18B20=1; DSPORT=0; _nop_(); _nop_(); DSPORT=1; delay(1); DSPORT=0; delay(600); DSPORT=1; } void ds_get_temp() // 读取DS18B20的温度值 { ds_start(); // 发送开始信号 ds_write_byte(0xcc); // 发送跳过ROM指令 ds_write_byte(0x44); // 发送温度转换指令 delay(80); // 等待转换完成 ds_start(); // 发送开始信号 ds_write_byte(0xcc); // 发送跳过ROM指令 ds_write_byte(0xbe); // 发送读取指令 Tempdata[0]=ds_read_byte(); // 读取温度值的低8位 Tempdata[1]=ds_read_byte(); // 读取温度值的高8位 temperature=Tempdata[0]>>1; // 计算得到温度值 if(Tempdata[1]&0x80) temperature|=0x80; // 判断温度值的符号 } void get_time() // 获取当前时间 { uchar i; uchar time_array[8]; time_array[0]=0; for(i=1;i<8;i++) { time_array[i]=ds_read_byte(); // 读取DS1302的时间数据 } second=time_array[1]; minute=time_array[2]; hour=time_array[3]; } void set_time() // 设置当前时间 { uchar i; uchar time_array[8]; time_array[0]=0; for(i=1;i<8;i++) { time_array[i]=ds_read_byte(); // 读取DS1302的时间数据 } ds_start(); // 发送开始信号 ds_write_byte(0xbe); // 发送写入指令 for(i=1;i<8;i++) { ds_write_byte(time_array[i]); // 写入时间数据 } ds_start(); // 发送开始信号 ds_write_byte(0x8e); // 发送写入控制指令 ds_write_byte(0); // 允许写入 } void display_time() // 显示当前时间 { uchar hour_disp,minute_disp,second_disp; hour_disp=hour/10; minute_disp=minute/10; second_disp=second/10; P1=0x7f; // 选择小时的数码管 P0=table[hour_disp]; delay(5); P1=0xbf; // 选择分钟的数码管 P0=table[minute_disp]; delay(5); P1=0xdf; // 选择秒钟的数码管 P0=table[second_disp]; delay(5); } void alarm() // 闹钟响铃 { uchar i,j; for(j=0;j<5;j++) { for(i=0;i<8;i++) { P1=0x7f; // 选择小时的数码管 P0=table[hour_disp]; delay(5); P1=0xbf; // 选择分钟的数码管 P0=table[minute_disp]; delay(5); P1=0xdf; // 选择秒钟的数码管 P0=table[second_disp]; delay(5); } } } void main() { ds_init(); // DS18B20的初始化 ds_write_byte(0x8e); // 发送写入控制指令 ds_write_byte(0x00); // 允许写入 ds_write_byte(0x80); // 关闭写保护 ds_write_byte(0); // 写入0 ds_start(); // 发送开始信号 ds_write_byte(0x8e); // 发送写入控制指令 ds_write_byte(0x80); // 开启写保护 get_time(); // 获取当前时间 while(1) { get_time(); // 获取当前时间 display_time(); // 显示当前时间 ds_get_temp(); // 获取温度值 delay(100); // 延时 } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小郑TE_Lab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值