基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯

本文主要是介绍基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于51单片机万年历

  • 准备硬件
  • 功能介绍
    • 修改时间
    • 修改日期(并且校正星期)
    • 闹钟模式
    • 调节灯模式
    • 调节风扇模式
    • 按键播报时间
    • 温度控制风扇
    • 主程序代码
  • 项目演示

前段时间做了一个 基于51单片机的万年历加温度控制风扇以及按键播报时间。在这里做一下笔记。

准备硬件

1:51单片机(我这里用的是STC89C52)
2:语音播报模块(我这里用的是SYN6288)
3:DS1302时钟模块
4:DS18B20温度模块
5:LCD1602显示屏
6:L298N电机驱动
7:蜂鸣器
8:电机
9:按键 5个
10:灯

功能介绍

功能
1:修改时间
2:修改日期(软件自动校正日期)
3:闹钟模式
4:温度控制风扇速度
5:调节灯亮度
6:播报时间

主界面设置
下面是大概的流程图 位置不够没画全。。。
在这里插入图片描述

由于代码较多,这里就不全部贴出来了。

修改时间

当我们进入到修改时间的界面,我们屏幕得显示出刚按下的时间,然后我们得让
1: LCD1602显示时间
2:按键的操作
按键 1:让时 / 分 /秒+1 或者按下按键2 让时 / 分 /秒 -1,然后通过按键3 来切换我到底是 调整时 / 分 /秒
3:按键4按下 退出
4:提示是否保存时间(1:保存,4:不保存)
如果保存我们再写入到DS1302这样就完成了修改时间的功能

在这里插入图片描述

/*时间数值 加 函数*/
unsigned char time_add(unsigned char cursor)
{unsigned char hour_high,hour_low;unsigned char min_high, min_low;unsigned char sec_high, sec_low;switch(cursor){case 0: //修改 时++hour_high = temp[2] >> 4;hour_low  = temp[2] & 0x0f;hour_low = hour_low++;if(hour_low == 4 && hour_high == 2) //如果等于24时 变00{hour_low = 0;hour_high = 0;	}else if(hour_low == 10){hour_low = 0;if(hour_high == 2)hour_high = 0;elsehour_high = hour_high + 1;	}hour_high = hour_high << 4;hour_high = hour_high | hour_low;temp[2] = hour_high;lcd_display_byte(5,0,(temp[2]>>4) + 0x30);lcd_display_byte(6,0,(temp[2]&0x0f) + 0x30);write_com(0x86);break;case 1://修改 分++	min_high  = temp[1] >> 4;min_low   = temp[1] & 0x0f;min_low++;if(min_low == 10){min_high++;min_low = 0;if(min_high == 6 && min_low == 0){min_high = 0;min_low = 0;}}min_high = min_high << 4;min_high = min_high | min_low;temp[1] =  min_high;lcd_display_byte(8,0,(temp[1]>>4) + 0x30);lcd_display_byte(9,0,(temp[1]&0x0f) + 0x30);write_com(0x89);break;case 2://修改 秒++sec_high  = temp[0] >> 4;sec_low   = temp[0] & 0x0f;sec_low++;if(sec_low == 10){sec_low = 0;sec_high++;if(sec_high == 6 && sec_low == 0){sec_low = 0;sec_high = 0;	}}sec_high = sec_high << 4;sec_high = sec_high | sec_low;temp[0] =  sec_high;lcd_display_byte(11,0,(temp[0]>>4) + 0x30);lcd_display_byte(12,0,(temp[0]&0x0f) + 0x30);write_com(0x8c);break;	default :break;}	return cursor;				
}

修改日期(并且校正星期)

当我们进入到修改日期的界面,我们屏幕得显示出刚按下的日期,然后我们得让
1: LCD1602显示日期
2:按键的操作
按键 1:让年/月/日+1 或者按下按键2 让年/月/日 -1,然后通过按键3 来切换我到底是 调整年/月/日
3:按键4按下 退出
4:提示是否保存日期(1:保存,4:不保存)
5:星期的自动调整
星期 = (月份对应的数字+日期数字) / 7 余数:则是星期几 0位周日
如果保存我们再写入到DS1302这样就完成了修改日期的功能

/*自动修正星期 函数*/
void revision_week()
{unsigned char num;unsigned char month;unsigned char day;unsigned char week;//星期 = (月份对应数字+日期数字) / 7 余数:则是星期几  0位周日month = ((temp[4]>>4)*10 + (temp[4]&0x0f));//将月份BCD码转为十进制day = ((temp[3]>>4)*10 + (temp[3]&0x0f));  //将日BCD码转为十进制 	switch(month){//月份对应数字case 5:	num = 5; break;case 6: num = 1; break;case 8:	num = 6; break;case 1:	case 10: num = 4; break;case 4: case 7:  num = 3; break;case 9:	case 12: num = 2; break;case 2:  case 3:  case 11: num = 0; break;	 }week = (num+day)%7;if(week == 0) temp[5] = 0x07;elsetemp[5] = week;} 

闹钟模式

进入到闹钟模式,设置闹钟的时间 选择周几,选择响铃时长。
时间的设置 跟修改时间的设置一模一样,等设置完时间,我们调到设置星期,按键1是 切换周一到 周日,按键2是确认选择当前这个星期,按键3是取消选择当前这个星期。
按键4:是否保存? 不保存就退出了,如果保存继续跳转到选择闹钟时间的界面。这里就没啥了。然后保存退出。主界面OFF 变成 ON 表示开启了

/* 选择/取消星期几 响闹钟*/
/* 周几++   打开   关闭  退出  */  
void lcd_dispaly_chooseClockWeek()
{unsigned char s = 0;unsigned char week;LCD1602_CLS; //清屏lcd_display_str(0,0,"week:  2:ON3:OFF");lcd_display_str(0,1,"clock:");week = temp[5];	while(1){lcd_display_byte(5,0,(week & 0x0f) + 0x30); //显示当前星期for(s=0;s<7;s++){if((alarmClockWeek>>s)&0x01 == 1)lcd_display_byte(s+6,1,(s+1)+0x30);	}write_com(0x85);menu = gather_key(); //采集哪个按键被按下函数	switch(menu) {case 1:week++;if(week >= 8)week = 1;			break;case 2:switch(week){	  			case 1:	alarmClockWeek |= 0x01; lcd_display_byte(6,1,'1'); break;//0000 0001case 2:	alarmClockWeek |= 0x02; lcd_display_byte(7,1,'2'); break;//0000 0010case 3:	alarmClockWeek |= 0x04; lcd_display_byte(8,1,'3'); break;//0000 0100case 4:	alarmClockWeek |= 0x08; lcd_display_byte(9,1,'4'); break;//0000 1000case 5:	alarmClockWeek |= 0x10; lcd_display_byte(10,1,'5'); break;//0001 0000case 6:	alarmClockWeek |= 0x20; lcd_display_byte(11,1,'6'); break;//0010 0000case 7:	alarmClockWeek |= 0x40; lcd_display_byte(12,1,'7'); break;//0100 0000}break;case 3:switch(week){case 1:	alarmClockWeek &= ~0x01; lcd_display_byte(6,1,' '); break;case 2:	alarmClockWeek &= ~0x02; lcd_display_byte(7,1,' '); break;case 3:	alarmClockWeek &= ~0x04; lcd_display_byte(8,1,' '); break;case 4:	alarmClockWeek &= ~0x08; lcd_display_byte(9,1,' '); break;case 5:	alarmClockWeek &= ~0x10; lcd_display_byte(10,1,' '); break;case 6:	alarmClockWeek &= ~0x20; lcd_display_byte(11,1,' '); break;case 7:	alarmClockWeek &= ~0x40; lcd_display_byte(12,1,' '); break;}break;case 4:s = lcd_display_saveTimeOrDate_YesOrNo(3);//保存? 不:清空为0  保则不清空if(s){ALARM_CLOCK_OFF; //关闭闹钟//闹钟日期清空alarmClockWeek = 0;	LCD1602_CLS; //清屏return;				}ALARM_CLOCK_ON;  //开启闹钟LCD1602_CLS; //清屏return;}}			}

调节灯模式

/*修改灯亮度 函数*/
void modifLightMode()
{unsigned char s = 0;s = lcd_display_light_menu(); //显示修改灯亮度菜单if(s){write_com(CLEAR_SCREEN);//清屏exitFlag = 1;return;	}lcd_display_str(0,0,"Light gear:");TR0 = 1;while(menu != 4){lcd_display_byte(11,0,light_gear+0x30);//显示灯档位menu = gather_key(); //检测是否有按键按下switch(menu){case 1:light_gear++;if(light_gear>=3){light_gear = 3;TR0 = 0;LED = 0;}else if(light_gear == 0){TR0 = 0;LED = 1;}else{TR0 = 1;LED = 0;}break;case 2:if(light_gear>=1){light_gear--;			}	else{light_gear = 0;}if(light_gear == 3){TR0 = 0;LED = 0;}else if(light_gear == 0){TR0 = 0;LED = 1;}else{TR0 = 1;LED = 0;					}break;case 4:exitFlag = 1;return;}	}		
}

调节风扇模式

/*修改风扇速度 函数*/
void modifFanMode()
{unsigned char s = 0;s = lcd_display_fan_menu(); //显示修改风扇速度菜单if(s){write_com(CLEAR_SCREEN);//清屏exitFlag = 1;return;	}lcd_display_str(0,0,"Fan gear:");TR1 = 1;while(menu != 4){lcd_display_byte(9,0,fan_gear+0x30);//显示风扇档位menu = gather_key(); //检测是否有按键按下switch(menu){case 1:fan_gear++;if(fan_gear>=3){FAN = 1;TR1 = 0;fan_gear = 3;}else if(fan_gear == 0){FAN = 0;TR1 = 0;}else{FAN = 1;TR1 = 1;	}break;case 2:if(fan_gear>=1){fan_gear--;}if(fan_gear == 0){FAN = 0;TR1 = 0;					fan_gear = 0;}else if(fan_gear == 3){FAN = 1;TR1 = 0;										}else{TR1 = 1;FAN = 1;}break;case 4:exitFlag = 1;return;}	}		
}

按键播报时间

这里我是用外部中断做。


/*SYN6288播报时间*/
void playTime(void)
{unsigned char syn6288_time[5] = {'\0'};syn6288_time[0] = (time[2]>>4)+48; 	 //时syn6288_time[1] = (time[2]&0x0f)+48;syn6288_time[2] = ':';syn6288_time[3] = (time[1]>>4)+48;	 //分syn6288_time[4] = (time[1]&0x0f)+48;SYN_FrameInfo(0, "[v16][t5]当前时间");delay(2000);SYN_FrameInfo(0,syn6288_time);delay(2000);
}void key_handler(void) interrupt 0
{delay(15);  //消抖作用if(kk == 0){	EX0 = 0;playTime(); //播报时间EX0 = 1;}
}

温度控制风扇

/*风扇速度控制 函数*/
void fan_speed_control()
{/*在此修改 温度的阈值 从而控制速度 */if(temperature[0] >= 20 && temperature[0] <= 25){fan_gear = 1;FAN = 1;TR1 = 1;				}else if(temperature[0] >= 26 && temperature[0] <= 30){fan_gear = 2;FAN = 1;TR1 = 1;		}else if(temperature[0] > 30){fan_gear = 3;FAN = 1;TR1 = 0;			}else{fan_gear = 0;FAN = 0;TR1 = 0;				}}

主程序代码

#include <reg52.h>
#include "lcd1602.h"
#include "ds1302.h"
#include "key.h"
#include "alarmClock.h"
#include "light.h"
#include "ds18b20.h"
#include "fan.h"
#include "uart.h"
#include "syn6288.h"
#include "delay.h"void main()
{	lcd_init();   //初始化LCD1602 ds1302_init();//初始化DS1302key_init();   //初始化按键light_init(); //初始化灯ds18b20_init();//初始化DS18B20fan_init();	  //初始化风扇uart_init();  //初始化串口while(1){menu = gather_key(); //检测是否有按键按下switch(menu){/*	默认模式 显示时间*/case 0:		if(exitFlag == 0){lcd_display_time();//LCD1602显示时间lcd_display_date();//显示日期exitFlag = 2;}ds1302_burst_read(DS1302_READ_TIME); //读取日期和时间 以及显示温度	lcd_display_dateAndTimeAndTemp(); //1602显示日期以及闹钟状态	if(alarmClock_flag){detectionAlarmClock();//检测闹钟							}	break;/*显示修改界面 时间/日期/闹钟修改  /  灯亮度修改  /  温度控制风扇阈值修改  /  返回主页*/case 1:case 2:case 3:lcd_display_menu(); //显示菜单界面	break;}}
}

项目演示

在这里插入图片描述
如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈
需要整个工程代码,欢迎大家打赏,评论区留上你的邮箱 or vx or qq。o( ̄︶ ̄)o 或者+我Q 844797079

这篇关于基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/415682

相关文章

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

电脑显示hdmi无信号怎么办? 电脑显示器无信号的终极解决指南

《电脑显示hdmi无信号怎么办?电脑显示器无信号的终极解决指南》HDMI无信号的问题却让人头疼不已,遇到这种情况该怎么办?针对这种情况,我们可以采取一系列步骤来逐一排查并解决问题,以下是详细的方法... 无论你是试图为笔记本电脑设置多个显示器还是使用外部显示器,都可能会弹出“无HDMI信号”错误。此消息可能

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount