基于51单片机万年历设计—显示温度农历

基于51单片机万年历设计

(仿真+程序+原理图+设计报告)

功能介绍

具体功能:

本系统采用单片机+DS1302时钟芯片+LCD1602液晶+18b20温度传感器+按键+蜂鸣器设计而成。

1.可以显示年月日、时分秒、星期、温度值。

2.DS18B20测温;

3.按键可设置时间、闹钟,切换农历查看;

​演示视频:

基于51单片机万年历设计—显示温度农历 

添加图片注释,不超过 140 字(可选)

程序

#include <reg52.h>	         //调用单片机头文件
/***公众号:木子单片机****/
#define uchar unsigned char  //无符号字符型 宏定义	变量范围0~255
#define uint  unsigned int	 //无符号整型 宏定义	变量范围0~65535
#include "eeprom52.h"
#include "nongli.h"bit flag_200ms ;
bit flag_100ms ;
sbit beep = P3^7;	  //蜂鸣器定义
bit flag_beep_en;
uint clock_value;     //用作闹钟用的sbit dq   = P3^1;	  //18b20 IO口的定义uint temperature ;    //温度变量
uchar flag_nl;        //农历 阳历显示标志位uchar menu_1,menu_2;uchar key_time,flag_value;      //用做连加的中间变量
bit key_500ms  ;
uchar n_nian,n_yue,n_ri;		//农历显示的函数#include "ds1302.h"
#include "lcd1602.h"/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{SectorErase(0x2000);byte_write(0x2000, fen1);byte_write(0x2001, shi1);byte_write(0x2002, open1);byte_write(0x2058, a_a);	
}/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{fen1  = byte_read(0x2000);shi1  = byte_read(0x2001);open1  = byte_read(0x2002);a_a      = byte_read(0x2058);
}/**************开机自检eeprom初始化*****************/
void init_eeprom()
{read_eeprom();		//先读if(a_a != 1)		//新的单片机初始单片机内问eeprom{fen1  = 3;shi1  = 8;open1  = 1;a_a = 1;write_eeprom();	   //保存数据}	
}/***********************18b20初始化函数*****************************/
void init_18b20()
{bit q;dq = 1;				//把总线拿高delay_uint(1);	    //15usdq = 0;				//给复位脉冲delay_uint(80);		//750usdq = 1;				//把总线拿高 等待delay_uint(10);		//110usq = dq;				//读取18b20初始化信号delay_uint(20);		//200usdq = 1;				//把总线拿高 释放总线
}/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{uchar i;for(i=0;i<8;i++){					 //写数据是低位开始dq = 0;			 //把总线拿低写时间隙开始 dq = dat & 0x01; //向18b20总线写数据了delay_uint(5);	 // 60usdq = 1;			 //释放总线dat >>= 1;}	
}/*************读取18b20内的数据***************/
uchar read_18b20()
{uchar i,value;for(i=0;i<8;i++){dq = 0;			 //把总线拿低读时间隙开始 value >>= 1;	 //读数据是低位开始dq = 1;			 //释放总线if(dq == 1)		 //开始读写数据 value |= 0x80;delay_uint(5);	 //60us	读一个时间隙最少要保持60us的时间}return value;		 //返回数据
}/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{uint value;uchar low;			   //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序init_18b20();		   //初始化18b20write_18b20(0xcc);	   //跳过64位ROMwrite_18b20(0x44);	   //启动一次温度转换命令delay_uint(50);		   //500usinit_18b20();		   //初始化18b20write_18b20(0xcc);	   //跳过64位ROMwrite_18b20(0xbe);	   //发出读取暂存器命令EA = 0;low = read_18b20();	   //读温度低字节value = read_18b20();  //读温度高字节EA = 1;value <<= 8;		   //把温度的高位左移8位value |= low;		   //把读出的温度低位放到value的低八位中value *= 0.625;	       //转换到温度值 小数return value;		   //返回读出的温度 带小数
}/******************1ms 延时函数*******************/
void delay_1ms(uint q)
{uint i,j;for(i=0;i<q;i++)for(j=0;j<120;j++);
}/******************写星期函数*******************/
void write_week(uchar hang,uchar add,uchar week)//写星期函数
{if(hang==1)   write_com(0x80+add);elsewrite_com(0x80+0x40+add);	  switch(week){case 1:write_data('M');//星期数为1时,显示write_data('O');write_data('N');break;case 2:write_data('T');//星期数据为2时显示write_data('U');write_data('E');break;case 3:write_data('W');//星期数据为3时显示write_data('E');write_data('D');break;case 4:write_data('T');//星期数据为4是显示write_data('H');write_data('U');break;case 5:write_data('F');//星期数据为5时显示write_data('R');write_data('I');break;case 6:write_data('S');//星期数据为6时显示write_data('T');write_data('A');break;case 0:write_data('S');//星期数据为7时显示write_data('U');write_data('N');break;}
}/*************时钟显示***************/
void init_1602_ds1302()
{write_sfm2_ds1302(1,1,shi);		   //显示时write_sfm2_ds1302(1,4,fen);		   //显示分write_sfm2_ds1302(1,7,miao);	   //显示秒write_week(2,12,week);
//	write_sfm1(1,14,week);			   //显示星期write_sfm3_18B20(1,11,temperature);	   //显示温度if(flag_nl == 0)  //显示阳历{write_sfm2_ds1302(2,2,nian);   //显示年write_sfm2_ds1302(2,5,yue);	   //显示月	write_sfm2_ds1302(2,8,ri);	   //显示日 	}else 			 //显示农历{write_sfm2_ds1302(2,2,n_nian);	//显示年write_sfm2_ds1302(2,5,n_yue);	//显示月	write_sfm2_ds1302(2,8,n_ri);	//显示日 }}									   /*************定时器0初始化程序***************/
void init_time0()	  
{EA   = 1;	 	  //开总中断TMOD = 0X01;	  //定时器0、工作方式1ET0  = 1;		  //开定时器0中断 TR0  = 1;		  //允许定时器0定时
}/*************闹钟报警函数***************/
void menu_dis()
{static uchar mm,value;if(flag_100ms == 1)		  //100ms执行一次{flag_100ms = 0;if(open1 == 1)	//如果闹钟打开{if((miao == 0) && (fen == fen1) && (shi == shi1)) {		flag_beep_en = 1;	//有报警 打开蜂鸣器响的标志位				}		if(flag_beep_en == 1)	//闹钟以被打开{clock_value++;if(clock_value <= 30)	 beep = ~beep;	   //蜂鸣器叫3秒else if(clock_value > 30){beep = 1;		    //蜂鸣器停1秒if(clock_value > 40){clock_value = 0;}}//  1 分钟后自动关闭闹钟value ++;if(value >= 10){value = 0;mm++;if(mm >= 60){mm = 0;flag_beep_en = 0;beep = 1;	}}					}}	}
}/********************独立按键程序*****************/
uchar key_can;	 //按键值void key()	 //独立按键程序
{static uchar key_new;key_can = 20;                   //按键值还原P3 |= 0x78;                     //对应的按键IO口输出为1if((P3 & 0x78) != 0x78)		//按键按下{delay_1ms(1);	     	//按键消抖动if(((P3 & 0x78) != 0x78) && (key_new == 1)){						//确认是按键按下key_new = 0;switch(P3 & 0x78){case 0x70:  key_can = 4;  break;	 //得到按键值case 0x68:  key_can = 3;  break;	 //得到按键值case 0x58:  key_can = 2;  break;	 //得到按键值case 0x38:  key_can = 1;  break;	 //得到按键值}
//			write_sfm2(1,0,key_can);				 //显示按键值}			}else key_new = 1;	
}/**********************设置函数************************/
void key_with()
{if(key_can == 1)	//设置键{menu_1++;if(menu_1 == 1)	  //设置时间{menu_2 = 1;write_string(1,0,"    :  :    W:  ");			write_string(2,0," 20  -  -       ");	}if(menu_1 == 2)	  //设置闹钟{menu_2 = 1;write_string(1,0,"   set clock    ");			write_string(2,0,"    Y  00:00      ");	}if(menu_1 > 2)    //回到正常显示{menu_1 = 0;write_guanbiao(1,2,0);	 //关闭光标init_1602_dis_csf();      //初始化液晶显示		}}if(key_can == 2)	//选择键{flag_200ms = 1;if(menu_1 == 1)		  //设置时间{menu_2 ++;if(menu_2 > 7)menu_2 = 1;}if(menu_1 == 2)		 //设置闹钟{menu_2 ++;if(menu_2 > 3)menu_2 = 1;				}}if(menu_1 == 1){if(menu_2 == 1)		  //设置时{if(key_can == 3)	//加{shi+=0x01;if((shi & 0x0f) >= 0x0a)shi = (shi & 0xf0) + 0x10;if(shi >= 0x24)shi = 0;}		if(key_can == 4)	//减{if(shi == 0x00)shi = 0x24;if((shi & 0x0f) == 0x00)shi = (shi | 0x0a) - 0x10;shi -- ; }	  				}if(menu_2 == 2)		  //设置分{if(key_can == 3)	//加{fen+=0x01;if((fen & 0x0f) >= 0x0a)fen = (fen & 0xf0) + 0x10;if(fen >= 0x60)fen = 0;}		if(key_can == 4)	//减	  {if(fen == 0x00)fen = 0x5a;if((fen & 0x0f) == 0x00)fen = (fen | 0x0a) - 0x10;fen -- ;}	}if(menu_2 == 3)		  //设置秒{if(key_can == 3)	//加{miao+=0x01;if((miao & 0x0f) >= 0x0a)miao = (miao & 0xf0) + 0x10;if(miao >= 0x60)miao = 0;}	if(key_can == 4)	//减	  {if(miao == 0x00)miao = 0x5a;if((miao & 0x0f) == 0x00)miao = (miao | 0x0a) - 0x10;miao -- ;			}}if(menu_2 == 4)		  //设置星期{if(key_can == 3)	//加{week+=0x01;if((week & 0x0f) >= 0x0a)week = (week & 0xf0) + 0x10;if(week >= 0x08)week = 1;}		if(key_can == 4)	//减	  {if(week == 0x01)week = 0x08;if((week & 0x0f) == 0x00)week = (week | 0x0a) - 0x10;week -- ;}	}if(menu_2 == 5)		  //设置年{if(key_can == 3)	//加{nian+=0x01;if((nian & 0x0f) >= 0x0a)nian = (nian & 0xf0) + 0x10;if(nian >= 0x9a)nian = 1;}		if(key_can == 4)	//减	  {if(nian == 0x01)nian = 0x9a;if((nian & 0x0f) == 0x00)nian = (nian | 0x0a) - 0x10;nian -- ;		}	}if(menu_2 == 6)		  //设置月{if(key_can == 3)	//加{yue+=0x01;if((yue & 0x0f) >= 0x0a)yue = (yue & 0xf0) + 0x10;if(yue >= 0x13)yue = 1;}		if(key_can == 4)	//减	  {if(yue == 0x01)yue = 0x13;if((yue & 0x0f) == 0x00)yue = (yue | 0x0a) - 0x10;yue -- ;					}	}if(menu_2 == 7)		  //设置日{if(key_can == 3)	//加{ri+=0x01;if((ri & 0x0f) >= 0x0a)ri = (ri & 0xf0) + 0x10;if(ri >= 0x32)ri = 0;			}		if(key_can == 4)	//减	  {if(ri == 0x01)ri = 0x32;if((ri & 0x0f) == 0x00)ri = (ri | 0x0a) - 0x10;ri -- ;			}	}write_sfm2_ds1302(1,2,shi);	   //显示时write_sfm2_ds1302(1,5,fen);	   //显示分write_sfm2_ds1302(1,8,miao);	   //显示秒write_sfm1(1,14,week);	   //显示星期					write_sfm2_ds1302(2,3,nian);	   //显示年write_sfm2_ds1302(2,6,yue);	   //显示月write_sfm2_ds1302(2,9,ri);	   //显示日switch(menu_2)	   // 光标显示{case 1:  write_guanbiao(1,2,1);  break;case 2:  write_guanbiao(1,5,1);  break;case 3:  write_guanbiao(1,8,1);  break;case 4:  write_guanbiao(1,14,1);  break;case 5:  write_guanbiao(2,3,1);  break;case 6:  write_guanbiao(2,6,1);  break;case 7:  write_guanbiao(2,9,1);  break;}write_time();	   //把时间写进去}	
/***************设置闹钟*********************/if(menu_1 == 2){if(menu_2 == 1)		  //设置闹钟开关{if(key_can == 3)	{open1 = 1;	  //闹钟开}		if(key_can == 4)	{open1 = 0;	  //闹钟关}	  				}if(menu_2 == 2)		  //设置闹钟时{if(key_can == 3)	//加{shi1+=0x01;if((shi1 & 0x0f) >= 0x0a)shi1 = (shi1 & 0xf0) + 0x10;if(shi1 >= 0x24)shi1 = 0;}		if(key_can == 4)	//减	  {if(shi1 == 0x00)shi1 = 0x5a;if((shi1 & 0x0f) == 0x00)shi1 = (shi1 | 0x0a) - 0x10;shi1 -- ;}	}if(menu_2 == 3)		  //设置秒{if(key_can == 3)	//加{fen1+=0x01;if((fen1 & 0x0f) >= 0x0a)fen1 = (fen1 & 0xf0) + 0x10;if(fen1 >= 0x60)fen1 = 0;}	if(key_can == 4)	//减	  {if(fen1 == 0x00)fen1 = 0x5a;if((fen1 & 0x0f) == 0x00)fen1 = (fen1 | 0x0a) - 0x10;fen1 -- ;			}}if(open1 == 1)write_string(2,4,"Y");	else write_string(2,4,"N");	write_sfm2_ds1302(2,7,shi1);	   //显示闹钟时write_sfm2_ds1302(2,10,fen1);	   //显示闹钟分switch(menu_2)	   // 光标显示{case 1:  write_guanbiao(2,4,1);  break;case 2:  write_guanbiao(2,7,1);  break;case 3:  write_guanbiao(2,10,1);  break;}	write_eeprom();     //保存闹钟时间}			
}/*****************主函数********************/

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

蜂鸣器;电池座;

直插电解电容;直插瓷片电容;

LCD1602液晶显示器;

DC电源插座;排针4-Pin;

PNP 三极管;色环电阻;

按键6X6X5MM;12MHZ晶振;

自锁开关;DS18B20;

导线:若干;

添加图片注释,不超过 140 字(可选)

流程图:

 

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计!具体如图!

添加图片注释,不超过 140 字(可选)

02原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

03程序

本设计使用软件keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

04设计报告

一万字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

05设计资料

        资料获取请关注同名公众号,全部资料包括仿真源文件 、AD原理图、程序(含注释)、任务书、开题报告、设计报告、流程图、实物图、元件清单、实物演示视频等。具体内容如下,全网最全! !

 

可以关注下方公众号!

点赞分享一起学习成长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/853915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

掌握Mock.js基本使用:快速模拟API实现增删改查

在项目中使用Mock.js进行增删改查操作&#xff0c;可以模拟后端接口&#xff0c;方便前端开发和测试。下面是一个简单的示例&#xff0c;展示如何在Vue 2项目中使用Mock.js实现增删改查功能。 1. 安装依赖 npm install mockjs --save2. 配置Mock.js 在项目的根目录下创建一个…

代码随想录算法训练营DAY36补| 435. 无重叠区间、 763.划分字母区间

训练营计划更新了&#xff0c;补一下DAY36多出来的两道题 435. 无重叠区间 题目链接&#xff1a;435. 无重叠区间 class Solution(object):def eraseOverlapIntervals(self, intervals):""":type intervals: List[List[int]]:rtype: int"""if…

前端跨域问题的解决办法,两种类型

跨域问题是由于同源策略的原因&#xff0c;在协议(HTTP或HTTPS)不同、端口号(8080或8881)不同、主机IP(182.92.178.25或者182.92.178.26)不同时而导致的不能进行数据交换的问题。 当后端没有做跨域时&#xff0c;前端就需要自己配置。 类型一&#xff1a;使用代理服务器的方法…

《书生·浦语大模型实战营》第4课 学习笔记:XTuner 微调 LLM:1.8B、多模态、Agent

文章大纲 1. 大模型微调简介2 快速上手2.1 环境安装2.2 前期准备2.2.1 数据集准备2.2.2 模型准备2.2.3 配置文件选择2.2.4 小结 2.3 配置文件修改2.4 模型训练2.4.1 常规训练2.4.2 使用 deepspeed 来加速训练2.4.3 训练结果2.4.4 小结 2.5 模型转换、整合、测试及部署2.5.1 模型…

【QT5】<重点> QT串口编程

目录 前言 一、串口编程步骤 0. 添加串口模块 1. 自动搜索已连接的串口 2. 创建串口对象 3. 初始化串口 4. 打开串口 5. 关闭串口 6. 发送数据 7. 接收数据 二、简易串口助手 1. 实现效果 2. 程序源码 3. 实现效果二 前言 本篇记录QT串口编程相关内容&#xff0…

常见的中间件都在解决什么问题?

常见的中间件都在解决什么问题 RocketMQ RocketMQ 是一款功能强大的分布式消息系统。 RocketMQ 源码地址&#xff1a;https://github.com/apache/rocketmq(opens new window) RocketMQ 官方网站&#xff1a;https://rocketmq.apache.org 什么场景下用 RocketMQ&#xff1f…

线程安全的解决方案(概念版本)

线程安全其实本质 讲的是内存的安全。 多个线程对统一资源的操作可能导致这个资源的数据不一致性。 举例说明&#xff1a;比如 张三有100块钱&#xff0c;现在线程A是要花50元&#xff0c;线程二是要存300元&#xff0c;当线程A花50元后&#xff0c;还没有内存值修改&#xff0…

19.channel相关方法

channel close()可以用来关闭channel closeFuture()用来处理channel的关闭 sync方法作用是同步等待channel关闭 addListener方法是异步等待channel关闭 pipeline() 方法添加处理器 write() 方法将数据写入 writeAndFlush() 方法将数据写入并刷出 write()方法,将数据写入到…

Optional详解和常用API

目录 一、Optional简介 二、构建Optional对象三种方式 2.1 Optional.of(value) 2.1.1 使用案例 2.2 Optional.ofNullable(value) 2.2.1 使用案例 2.3 Optional.empty() 2.3.1 使用案例 三、Optional常用的api解析和使用案例 3.1 isPresent 3.1.1 使用案例 3.2 ifPrese…

登录MySQL方式

登录MySQL方式 方式一&#xff1a;通过MySQL自带的客户端 MySQL 客户端输入命令即可 方式二&#xff1a;通过window自带的客户端 从命令端&#xff08;cmd&#xff09;进入 mysql -h localhost -P 3306 -u root -p Enter password:密码登录方式&#xff1a; mysql -h 主…

深入理解指针(四)

目录 1. 回调函数是什么? ​2. qsort使用举例 2.1冒泡排序 2.2使用qsort函数排序整型数据 ​2.3 使用qsort排序结构数据(名字) 2.4 使用qsort排序结构数据(年龄) 3. qsort函数的模拟实现 1. 回调函数是什么? 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数…

VMware各版本镜像下载站

CDS Repository - /var/www/public/stage/session-120/cds/vmw-desktop/ws 参考&#xff1a; VMware各版本下载的镜像站(含windows和linux)_vm win7映像文件下载-CSDN博客

混淆矩阵-召回率、精确率、准确率

混淆矩阵 1 混淆矩阵2 混淆矩阵指标2.1 准确率2.2 精确率2.3 召回率2.4 特异度2.4 假正率2.5 假负率2.6 F1 分数 3 总结 1 混淆矩阵 混淆矩阵是一种用于评估分类模型性能的重要工具。它通过矩阵形式清晰地展示了模型对样本进行分类的结果&#xff0c;帮助我们理解模型在不同类…

【嵌入式】CAN总线详解

【嵌入式】CAN总线详解 一、CAN总线简介 CAN总线是一种控制器局域网总线&#xff0c;每一个挂载在CAN局域网的设备&#xff0c;都可以利用CAN去发送信息&#xff0c;也可以接收局域网的各种信息&#xff0c;每个设备都是平等的&#xff0c;共享CAN的资源。广泛应用于汽车、嵌…

从0开发一个Chrome插件:项目实战——翻译插件(附带申请谷歌翻译、百度翻译教程)

前言 这是《从0开发一个Chrome插件》系列的第十八篇文章,本系列教你如何从0去开发一个Chrome插件,每篇文章都会好好打磨,写清楚我在开发过程遇到的问题,还有开发经验和技巧。 专栏: 从0开发一个Chrome插件:什么是Chrome插件?从0开发一个Chrome插件:开发Chrome插件的必…

LabVIEW程序的常见加密方式

LabVIEW程序的加密对于保护知识产权和敏感数据至关重要。本文将详细介绍LabVIEW程序常用的加密方式&#xff0c;包括VI加密、代码保护、文件加密和通信加密等&#xff0c;帮助开发者选择合适的加密方法来确保程序的安全性和完整性。 LabVIEW程序的常见加密方式 VI加密&#xf…

【宠粉赠书】科研绘图神器:MATLAB科技绘图与数据分析

小智送书第二期~ 为了回馈粉丝们的厚爱&#xff0c;今天小智给大家送上一套科研绘图的必备书籍——MATLAB科技绘图与数据分析。下面我会详细给大家介绍这套图书&#xff0c;文末留有领取方式。 图书介绍 《MATLAB科技绘图与数据分析》是一本综合性强、内容丰富的书籍&#x…

Mybatis做批量操作

动态标签foreach&#xff0c;做过批量操作&#xff0c;但是foreach只能处理记录数不多的批量操作&#xff0c;数据量大了后&#xff0c;先不说效率&#xff0c;能不能成功操作都是问题&#xff0c;所以这里讲一讲Mybatis正确的批量操作方法&#xff1a; 在获取opensession对象…

动态规划解题步骤

状态规划题一般要列一个dp表 1、状态表示(重要) 什么是状态表示&#xff1f; 简单来说就是dp表里的值的含义 怎么得到状态表示&#xff1f; 1.题目要求 2.经验题目要求 3&#xff0c;分析问题的过程中发现重复子问题&#xff0c;找到状态表示 2、状态转移方程(重要) d…

Flutter学习(一)

1.Dart环境安装 官网&#xff1a;Get the Dart SDK | Dart Mac环境&#xff1a; Install Homebrew if needed. https://brew.sh/ Add the official tap. $ brew tap dart-lang/dart Install the Dart SDK. $ brew install dart 2.vscode配置 安装dart插件 安装code r…