基于单片机C51的简单万年历设计
- 格式:doc
- 大小:330.00 KB
- 文档页数:26
51单片机做的12864万年历这是我花了一个星期时间做的万年历;一开始是一些图片,后面是这个制作的C语言源程序;希望大家稀饭:Main.c#include "reg52.h"#include "macroconst.h"#include "keyscan.h"#include "screen.h"#include "18b20.h"#include "ds1302.h"#include "atao_12864.h"#include "24c02.h"idata unsigned char state1[1];unsigned char screennum=1;//屏幕号#define time_task_sec 200 //节拍200Hz#define clock 24000000 //晶振#define max_task 4 //最大任务数idata unsigned char task_delay[4];#define task_delay0 time_task_sec/1 //2赫兹18b20 #define task_delay1 time_task_sec/5 //10赫兹屏幕#define task_delay2 time_task_sec/3 //4赫兹1302 #define task_delay3 time_task_sec/20 //20赫兹键盘void init(){unsigned char i;init18b20();ds1302_init();initina1(); //---------------------------LCD字库初始化程序RdFromROM(state1,8,1);state[0]=state1[0]; //-------界面RdFromROM(state1,15,1);state[1]=state1[0];//------- 闹钟RdFromROM(state1,11,1);key_sound=state1[0];//-------按键音// state[2]=state1[2];// state[3]=state1[3];screennum=1;//------默认一号屏for(i=0;i<max_task;i++)//清除任务延时{task_delay[i]=0;}TMOD=0x11;EA=1;TH0=255-clock/time_task_sec/12/526;TL0=255-clock/time_task_sec/12%526;ET0=1;TR0=1;}void main(){init();while(1){ if(task_delay[0]==0){readtemp(); task_delay[0]=task_delay0;} if(task_delay[3]==0){MenuCheckKey();task_delay[3]=task_delay1;}if(task_delay[1]==0){screen_select(screennum);task_delay[1]=task_delay1;} if(task_delay[2]==0){ds1302_read_time(); task_delay[2]=task_delay0;} }}void timer0() interrupt 1{uchar i=0;TH0=255-clock/time_task_sec/12/526;TH1=255-clock/time_task_sec/12%526;for(i=0;i<max_task;i++)if(task_delay[i]) task_delay[i]--; // miao=21,fen=33,xiaomiao=94;if(ma_start==1){tt++;if(tt==8){tt=0;xiaomiao++;if(xiaomiao==99){xiaomiao=0;miao++;if(miao==60){miao=0;fen++;if(fen==99){fen=0;}}}}}}Screen.c:#include "reg52.h"#include "macroconst.h"#include "delay.h"#include "18b20.h"#include "atao_12864.h"#include "ds1302.h"#include "24c02.h"#include "festival.h"#include "keyscan.h"idata unsigned char miao=0,fen=78,xiaomiao=0,tt=0;idata unsigned char bai,shi,ge,shinian,genian,shiyue,geyue,shiri,geri,shishi,geshi,shifen,gefen,shimi ao,gemiao;idata unsigned char Number[4];unsigned char code mainmenu[]={" 主菜单""3.查询 4.温度""1.调时 2.秒表""5.设置 6.返回"};unsigned char code setmenu[]={" 设置""3.查温 4.按键""1.界面 2.闹铃""5.报时 6.返回"};void gettime(){shinian=(time_buf1[1]%100)/10;genian=(time_buf1[1]%100)%10;shiyue=(time_buf1[2])/10;geyue=(time_buf1[2])%10;shiri=(time_buf1[3])/10;geri=(time_buf1[3])%10;shishi=(time_buf1[4])/10;geshi=(time_buf1[4])%10;shifen=(time_buf1[5])/10;gefen=(time_buf1[5])%10;shimiao=(time_buf1[6])/10;gemiao=(time_buf1[6])%10;}void screen_select(uchar num){// initina1();gettime() ;if(num==1) //----------主界面{Lcd_Set_Post(1,0);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);TransferData('/',1);TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);TransferData('/',1);TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);Lcd_Set_Post(1,4);if(state[1]==1)//----------------闹铃的状态图标{TransferData(' ',1);TransferData(14,1);}Lcd_Set_Post(1,5);if(key_sound==1){TransferData(13,1);}if(state[0]==0){Lcd_Set_Post(1,7); //----------------农历年nian(0);Lcd_Set_Post(2,0);//----------------------- 农历日月LCD_WRITE_CHAR("农历");Conversion(0,time_buf[1],time_buf[2],time_buf[3]);TransferData(month_moon/16+'0',1);TransferData(month_moon%16+'0',1);TransferData('/',1);TransferData(day_moon/16+'0',1);TransferData(day_moon%16+'0',1);}if(state[0]==1){Lcd_Set_Post(3,5);}else {Lcd_Set_Post(2,5);}LCD_WRITE_CHAR("星期");//----------------------星期if(time_buf1[7]==7) {LCD_WRITE_CHAR("日");}if(time_buf1[7]==6) {LCD_WRITE_CHAR("六");}if(time_buf1[7]==5) {LCD_WRITE_CHAR("五");}if(time_buf1[7]==4) {LCD_WRITE_CHAR("四");}if(time_buf1[7]==3) {LCD_WRITE_CHAR("三");}if(time_buf1[7]==2) {LCD_WRITE_CHAR("二");}if(time_buf1[7]==1) {LCD_WRITE_CHAR("一");}Lcd_Set_Post(3,0);TransferData(shishi+48,1);//----------------------时TransferData(geshi+48,1);TransferData(58,1);TransferData(shifen+48,1);//----------------------分TransferData(gefen+48,1);TransferData(58,1);TransferData(shimiao+48,1);//----------------------秒TransferData(gemiao+48,1);if(state[0]==0){bai=(temph/100); //---------------------------------温度shi=(temph%100)/10;ge=(temph%100)%10;Lcd_Set_Post(3,4);if(zerotemp==0){TransferData(' ',1);TransferData(' ',1);} Lcd_Set_Post(3,5);TransferData(shi+48,1);TransferData(ge+48,1);TransferData('.',1);TransferData(templ+48,1);TransferData(0xa1,1);TransferData(0xe6,1);Lcd_Set_Post(4,0);festival(time_buf[2],time_buf[3],time_buf[4]);//农历}}if(num==3)//----------主菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(mainmenu);}if(num==4)//----------设置菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(setmenu);}if(num==5)//----------时间设置{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("时间设置");Lcd_Set_Post(2,1);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);LCD_WRITE_CHAR("年");TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);LCD_WRITE_CHAR("月");TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);LCD_WRITE_CHAR("日");TransferData(time_buf1[7]+48,1);//---------------星期Lcd_Set_Post(3,2);TransferData(shishi+48,1);//--------------------时TransferData(geshi+48,1);LCD_WRITE_CHAR("时");TransferData(shifen+48,1);//---------------------分TransferData(gefen+48,1);LCD_WRITE_CHAR("分");TransferData(shimiao+48,1);//--------------------秒TransferData(gemiao+48,1);}if(num==6)//----------秒表{uchar shi1,shi2,shi3,ge1,ge2,ge3;Lcd_Set_Post(1,3);//--------设置显示位置LCD_WRITE_CHAR("秒表");Lcd_Set_Post(3,2);shi1=fen/10;ge1=fen%10;TransferData(shi1+48,1);TransferData(ge1+48,1);TransferData(':',1);shi2=miao/10;ge2=miao%10;TransferData(shi2+48,1);TransferData(ge2+48,1);TransferData(':',1);shi3=xiaomiao/10;ge3=xiaomiao%10;TransferData(shi3+48,1);TransferData(ge3+48,1);}if(num==8){Lcd_Set_Post(1,2);//--------农历查询LCD_WRITE_CHAR("温度查询");Lcd_Set_Post(3,0);//--------农历查询LCD_WRITE_CHAR("最高温度"); TransferData(':',1);RdFromROM(Number,0,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(3,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); Lcd_Set_Post(4,0);//--------农历查询LCD_WRITE_CHAR("最低温度"); TransferData(':',1);RdFromROM(Number,4,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(4,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); }if(num==9)//----------界面菜单{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("界面选择");Lcd_Set_Post(2,0);TransferData(1+48,1);TransferData('.',1);LCD_WRITE_CHAR("多功能界面");Lcd_Set_Post(3,0);TransferData(2+48,1);TransferData('.',1);LCD_WRITE_CHAR("简洁界面");}。
基于51单片机的万年历设计单片机经过几十年的发展,已经广泛应用于生活中的各个领域。
单片机以其体积小、功能全、性价比高等诸多优点,在许多行业都得到了广泛应用。
在工业控制、家用电器、通信设备、信息处理、尖端武器等各种测控领域的应用中独占鳌头,单片机开发技术已成为电子信息、电气、通信、自动化、机电一体化等专业技术人员必须掌握的技术。
基于单片机的万年历作为设计的课题,因为它有很好的开放性和可发挥性,对作者的要求比较高,不仅考察了对单片机的掌握能力而且强调了对单片机扩展的应用。
另外液晶显示的万年历已经越来越流行,特别适合在家庭居室、办公室、大厅、会议室、车站和广场等地方使用,它具有显示清晰直观、走时准确、可以进行夜视等功能,并且还可以扩展出其它多种功能。
所以,电子万年历作为设计课题很有价值。
现在对于电子万年历的设计大多运用51单片机。
主要是因为51单片机种类齐全、结构体系完整、指令系统功能完善、性能优越、具有较高可靠性和高性价比等特点。
本篇论文主要介绍了运用单片机实现电子万年历的设计,万年历系统拟用STC89C51单片机控制,以DS1302时钟芯片计时、1602液晶屏显示。
系统主要由单片机控制电路,显示电路以及校正电路三个模块组成。
本文阐述了系统的硬件工作原理,所应用的各个接口模块的功能以及其工作过程,论证了设计方案理论的可行性。
目录第一章绪论 (1)1.1本课题主要的研究工作 (1)第二章系统的硬件设计与实现 (2)2.1电路设计框图 (2)2.2系统硬件概述 (2)2.3主要单元电路的设计 (2)2.3.1 单片机主控制模块的设计 (2)2.3.2时钟电路模块的设计 (3)2.3.3独立式键盘设计 (4)2.3.4显示模块的设计 (4)第三章系统的软件设计 (6)3.1程序流程图 (6)3.1.1 系统总流程图 (6)3.1.2 DS1302时钟程序流程图 (7)3.1.3 LCD显示程序流程图 (8)3.2程序的设计 (9)3.2.1 DS1302读写程序 (9)3.2.2 液晶显示程序 (11)第四章仿真与调试 (13)4.1K EIL软件调试流程 (13)4.2P ROTEUS软件运行流程 (13)4.3万年历的功能仿真 (13)致谢 (15)参考文献 (16)附录:主程序 (17)第一章绪论1.1 本课题主要的研究工作本项目是一种基于AT89C51片机的万年历设计,本方案以AT89C51片机作为主控核心,与时钟芯片DS1302、按键、LCD1602液晶显示器组成硬件系统。
课程设计说明书课程名称:《单片机技术》设计题目:基于单片机的万年历设计院(部):电子信息与电气工程学院学生:学号:专业班级:电子信息工程10-1指导教师:2013年 05 月 17 日课程设计任务书万年历设计摘要:以AT89S52为主控芯片设计了一个带温度显示的万年历电路系统,该电路具有年、月、日、星期、时、分、秒、闹钟显示和调整,并且还能显示温度和按键提示音、整点鸣叫、定时闹钟鸣叫等功能。
本设计由数据显示模块、温度采集模块、时间处理模块和调整设置模块四个模块组成。
温度采集选用DS18B20芯片,数据显示采用1602A液晶显示模块,主芯片利用定时中断产生时间,控制着液晶的显示更新、温度的实时变化以及按键的读取处理,而对于闹钟,实际上就是时间里的一个嵌套程序。
时间和闹钟的值由按键调整设置,采用通用的二十四小时制。
关键词:单片机;液晶显示屏;温度传感器;时钟芯片目录1. 设计背景 (1)1.1 概述 (1)1.2 万年历设计目的 (1)2.设计方案 (2)2.1 按键控制模块设计与论证 (2)2.2 时钟模块设计与论证 (2)2.3 显示模块模块设计与论证 (3)3. 方案实施 (4)3.1系统整体框图 (4)3.2原理图设计 (4)3.2.1 单片机最小系统模块 (4)3.2.2 电源模块 (5)3.2.3 时钟芯片DS1302模块 (6)3.2.4温度采集DS18B20模块 (6)3.2.5 闹钟模块 (7)3.2.6 LCD1602显示模块 (8)3.2.7 按键模块 (9)3.3 软件设计 (9)3.4 系统仿真 (10)3.5系统制作 (11)4. 结果与结论 (12)4.1 结果 (12)4.2 结论 (12)5. 收获与致 (13)6. 参考文献 (14)7. 附件 (15)7.1 原理图 (15)系统电路图如图7.1所示: (15)7.2 元器件清单 (15)7.3 实物图 (16)7.3.1 正常工作 (16)7.3.2 调试状态 (17)7.3.3 闹钟设置状态 (18)1. 设计背景1.1 概述如今万年历已经在人们生活中广泛的使用,它不仅是记录日期和时间的工具,而且也成为了一种装饰品。
1. 综述本课题要求设计一个常用的万年历。
该电路是用于反应年、月、日、时、分、秒、星期的实时状态,液晶显示屏上显示第一排显示“湖南工学院”第二排显示“年、月、日”第三排显示“时、分、秒”第四排显示“星期”。
当接通时液晶屏上一次显示,并且可以通过矩阵键盘调节年、月、日、时、分、秒、星期的实时状态。
假设液晶显示屏显示的是2008年8月1日,要求是:通过矩阵键盘的调节可以实时时间。
经过以上所述的设计内容及要求的分析,可以将电路分为以下几部分:首先,通过晶振电路产生频率为32.768KH z的脉冲信号,该脉冲信号用于提供给DS1302的时钟脉冲信号。
接通电源时,液晶屏上显示“湖南工学院”“电气与信息工程系”“电信0901”“蒋赞荣”。
当按下第一个按键时进入“欢迎进入万年历”界面。
按下第二个按键时进入显示经典万年历界面。
理论部分已用protues软件进行仿真,并且达到设计要求。
实际部分在电子实验室和同组的成员在老师的指导下一进行模拟,能够达到理论设计要求。
在设计的过程中应该本着元件通用化,成品化,程序的精简化,以满足大规模生产的要求,以便在日后产品的更新维护能够更好的方便的进行。
同时也要尽量减少设计过程中掉电现象和不稳定现象。
使产品在使用过程中能够稳定的运行,达到良好的无故障率。
二者必须达到一定的标准,才能在工厂进行量产。
2. 方案设计与分析方案通过DS1302时钟芯片产生时钟数据信息,通过读写该芯片内的时钟信号通过单片机的控制将其显示在液晶屏幕上。
该芯片的三总线SCLK、I/O、CE分别接在单片机的P3^2、P3^3、P3^4三端效果是最好的,因为P3^0、P3^1位接在液晶屏的RS、RW,P3^5接在液晶屏的E端,其它的三态数据线接在P0口,矩阵键盘可以通过跳线接P1口或P2口,在使程序设计起来比较简单,可以很好的利用者一点,设计的复杂程度适中,而且达到了预期的设计目的。
在此电路中由于P0口用于液晶电路的三态八根数据线了,而P3口也用作了特殊作用,所以矩阵键盘的跳线只能是在P1口或者是P2口作为键盘的输入信号。
单片机课程实训SCM PRACTICAL TRAINING目录第一部分课程设计任务书 (1)一、课程设计题目 (1)二、课程设计时间 (1)三、实训提交方式 (1)四、设计要求 (1)第二部分课程设计报告 (2)一、单片机发展概况 (2)二、MCS-51单片机系统简介 (2)三、设计思想 (3)四、硬件电路设计 (3)1. 总体设计 (3)2. 晶振电路 (4)3. 复位电路 (4)4. DS1302时钟电路 (5)5. 温度采集系统电路 (5)6. 按键调整电路 (6)7. 闹钟提示电路 (6)五、软件设计框图 (7)六、程序源代码 (8)1. 主程序 (8)2. 温度控制程序 (11)3. 日历设置程序 (13)4. 时钟控制程序 (18)5. 显示设置程序 (20)七、结束语 (23)八、课程设计小组分工 (23)九、参考文献 (23)第一部分课程设计任务书一、课程设计题目用中小规模集成芯片设计制作万年历。
二、课程设计时间五天三、实训提交方式提交实训设计报告电子版与纸质版四、设计要求(1)显示年、月、日、时、分、秒和星期,并有相应的农历显示。
(2)可通过键盘自动调整时间。
(3)具有闹钟功能。
(4)能够显示环境温度,误差小于±1℃(5)计时精度:月误差小于20秒。
第二部分课程设计报告一、单片机发展概况单片机诞生于20世纪70年代末,它的发展史大致可分为三个阶段:第一阶段(1976-1978):初级单片机微处理阶段。
该时期的单片机具有 8 位CPU,并行 I/O 端口、8 位时序同步计数器,寻址范围 4KB,但是没有串行口。
第二阶段(1978-1982):高性能单片机微机处理阶段,该时期的单片机具有I/O 串行端口,有多级中断处理系统,15 位时序同步技术器,RAM、ROM 容量加大,寻址范围可达 64KB。
第三阶段(1982-至今)位单片机微处理改良型及 16 位单片机微处理阶段民用电子产品、计算机系统中的部件控制器、智能仪器仪表、工业测控、网络与通信的职能接口、军工领域、办公自动化、集散控制系统、并行多机处理系统和局域网络系统。
毕业设计(论文)-基于MCS-51的万年历设计1 引言1.1 万年历的背景与意义万年历作为一种常见的时间计数工具,被广泛应用于日常生活和工业生产中。
随着电子技术的飞速发展,电子万年历以其准确、方便、易操作等特点逐渐取代了传统的机械万年历。
基于MCS-51单片机的万年历设计,不仅满足了人们对时间精确计量的需求,同时也为单片机技术在时间测量领域的应用提供了新的思路。
1.2 MCS-51单片机的介绍MCS-51单片机是美国Intel公司推出的一种高性能的8位单片机,具有较高的性价比、丰富的指令集和灵活的I/O端口。
由于其结构简单、易于编程和扩展,MCS-51单片机被广泛应用于工业控制、家用电器、智能仪表等领域。
1.3 论文结构及内容安排本文主要分为七个章节,首先介绍万年历的背景与意义以及MCS-51单片机的基本情况;其次,阐述万年历的原理与设计要求,并提出基于MCS-51单片机的万年历设计方案;接着,详细介绍MCS-51单片机的硬件设计和软件设计;然后,进行系统调试与性能测试;在此基础上,探讨万年历的实际应用与拓展;最后,总结全文并指出创新与不足之处,展望未来的研究方向。
2. 万年历的原理与设计2.1 万年历的基本原理万年历是一种可以显示公历日期、时间,并且可以自动调整闰年和平年的日历。
它的核心是通过算法处理时间的流逝,计算出当前的日期。
基本原理涉及以下几个核心概念:•时间单位:秒、分、时、日、月、年•时间算法:通过累计秒数,进行时、日、月、年的进位处理•闰年规则:四年一闰,百年不闰,四百年再闰2.2 万年历的设计要求在设计万年历时,需要遵循以下要求:•准确性:确保时间显示准确无误•可靠性:系统稳定运行,适应不同的环境条件•易用性:用户界面友好,操作简便•经济性:在满足功能要求的前提下,尽可能降低成本2.3 基于MCS-51单片机的万年历设计方案基于MCS-51单片机的万年历设计主要包括以下几个部分:2.3.1 时间计算模块利用单片机内部的定时器,以秒为单位递增计数,通过编写中断服务程序来处理时间进位,实现时、分、秒的计算。
基于51单片机的万年历中文摘要本设计万年历以AT89C51为控制中心,与温度传感器DS18B20,时钟芯片DS1302综合应用为一体,不仅能够准确显示时间、日期,闹钟设置,环境温度测量及温度高低温报警等功能。
单片机是一种集CPU、RAM、ROM、I/O接口和中断系统等于一体的器件,只需要外加电源和晶振就可实现对数字信息的处理和控制。
单片机与数字万年历相结合,用于时间显示,温度测试等不仅具有控制方便、组态简单和灵活性大等优点,而且可以大幅度提高被检测数值的技术指标,从而能够大大提高产品的质量和数量。
关键词:单片机,温度传感器,C语言,液晶显示ABSTRACTThis design USES AT89C51 as calendar control center, and the temperature sensor DS18B20, the clock DS1302 chip integrated application as a whole, and not only be able to accurately display the time, date, alarm, the environment temperature measurement and high temperature, low temperature alarm functions.SCM is a collection of CPU, RAM, ROM, I/O interface and interrupt system is one of the devices, only require additional power can be used for vibration and grain is the process of digital information and control. Single-chip microcomputer and digital calendar, combining for time to show, temperature testing has not only control convenient, simple and flexible configuration advantages, and which could increase the technical index of the tested value, which can greatly improve the quality of the products and quantity.Key words:Single-chip microcomputer, Temperature Sensor,C language,Liquid crystal displ目录第一章前言 (4)1.1系统开发背景及现状 (4)1.2 系统开发的目的 (4)第二章总体设计 (5)2.1 本设计实现的功能和要求 (5)2.2 设计的选择方案和论证 (5)2.2.1单片机芯片的选择方案和论证 (5)2.2.2显示模块选择方案和论证 (5)2.2.3 时钟芯片的选择方案和论证 (6)2.3.4 温度传感器的选择方案与论证 (6)2.3总体设计框图 (6)第三章硬件设计 (8)3.1 主要元器件介绍 (8)3.1.1 单片机简介 (8)3.1.2 传感器DS18B20介绍 (9)3.1.3 LCD1602液晶显示介绍 (10)3.2 各模块设计 (11)3.2.1 主控制电路 (11)3.2.2 LCD1602显示模块设计 (12)3.2.3 DS18B20温度传感器模块 (13)3.2.4 键盘输入模块设计 (13)3.2.5 蜂鸣器模块设计 (13)3.2.6 DS1302时钟电路模块 (14)第四章软件设计 (16)第五章安装与调试 (18)5.1 安装制作 (18)5.2 硬件调试 (18)5.2.1布线的原则与焊接 (18)5.2.2 硬件调试与测试 (19)5.3 软件调试 (19)5.3.1 软件测试仪器 (19)5.3.2 软件调试与测试 (19)5.4 联调 (20)5.5测试结果分析与结论 (21)第六章总结 (22)参考文献 (23)附录A (24)附录B (26)致谢 (28)第一章前言1.1系统开发背景及现状当今世界,知识更新的速度越来越快。
课程设计说明书课程名称:《单片机技术》设计题目:基于单片机的万年历设计院(部):电子信息与电气工程学院学生:学号:专业班级:电子信息工程10-1指导教师:2013年 05 月 17 日课程设计任务书万年历设计摘要:以AT89S52为主控芯片设计了一个带温度显示的万年历电路系统,该电路具有年、月、日、星期、时、分、秒、闹钟显示和调整,并且还能显示温度和按键提示音、整点鸣叫、定时闹钟鸣叫等功能。
本设计由数据显示模块、温度采集模块、时间处理模块和调整设置模块四个模块组成。
温度采集选用DS18B20芯片,数据显示采用1602A液晶显示模块,主芯片利用定时中断产生时间,控制着液晶的显示更新、温度的实时变化以及按键的读取处理,而对于闹钟,实际上就是时间里的一个嵌套程序。
时间和闹钟的值由按键调整设置,采用通用的二十四小时制。
关键词:单片机;液晶显示屏;温度传感器;时钟芯片目录1. 设计背景 (1)1.1 概述 (1)1.2 万年历设计目的 (1)2.设计方案 (2)2.1 按键控制模块设计与论证 (2)2.2 时钟模块设计与论证 (2)2.3 显示模块模块设计与论证 (3)3. 方案实施 (4)3.1系统整体框图 (4)3.2原理图设计 (4)3.2.1 单片机最小系统模块 (4)3.2.2 电源模块 (5)3.2.3 时钟芯片DS1302模块 (6)3.2.4温度采集DS18B20模块 (6)3.2.5 闹钟模块 (7)3.2.6 LCD1602显示模块 (8)3.2.7 按键模块 (9)3.3 软件设计 (9)3.4 系统仿真 (10)3.5系统制作 (11)4. 结果与结论 (12)4.1 结果 (12)4.2 结论 (12)5. 收获与致 (13)6. 参考文献 (14)7. 附件 (15)7.1 原理图 (15)系统电路图如图7.1所示: (15)7.2 元器件清单 (15)7.3 实物图 (16)7.3.1 正常工作 (16)7.3.2 调试状态 (17)7.3.3 闹钟设置状态 (18)1. 设计背景1.1 概述如今万年历已经在人们生活中广泛的使用,它不仅是记录日期和时间的工具,而且也成为了一种装饰品。
基于51单片机的电子万年历系统的设计人们在观测时间的时候,常常想知道当时的湿度、温度、日期、星期等与日常生活密切的信息。
采用51单片机设计了一种计时准确、功能全面、成本低廉的万年历。
该电子万年历通过定时中断和按键同时显示各种需要的信息,具有电路简单,显示直观、读取方便、功能多样的优点。
标签:电子万年历;单片机;定时中断;温湿度引言电子万年历是一种应用非常廣泛的日常计时工具,适合各类场合使用。
LCD 数字显示的日历钟显示清晰直观、走时准确、可以进行夜视,并且还可以扩展出多种功能。
功能也越来越齐全,除了公历年月日、时分秒、还有星期、温湿度显示及闹铃。
1 总体设计要求1.1 实现的功能此万年历主要功能是显示:时、分、秒、年、月、日、星期、湿度、温度、闹钟功能、整点报时、农历、平闰年。
数字式温湿度计测温范围-40~80℃,湿度误差范围±3%RH用LCD液晶显示。
1.2 系统基本方案选择KeilC51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
KeilC51软件目标代码生成效率很高,大多数情况下生成的汇编语言代码都比较容易理解[1]。
1.3 硬件设计选定本设计主控制系统采用AT89S52,独立按键控制;时钟电路由ds1302时钟电路提供;温湿度由DHT21数字式温湿度传感器采集;LCD1602液晶屏动态扫描作为显示。
如图1所示。
2 系统的硬件设计与实现2.1 单片机主控制模块的设计主控制系统采用AT89S52,这是一种高性能、低功耗微控制器,具有8K的系统可编程Flash存储器。
与工业80C51产品指令和引脚完全兼容。
单片机的最小系统由单片机芯片、时钟电路、复位电路组成[2]。
2.2 计时芯片计时芯片采用DS1302,这是一种高性能实时时钟电路[3],DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
如果采用单片机,还需要计数器,同时需要设置中断、查询等,消耗单片机资源,而采用DS1302时钟芯片,就不存在这些问题。
C51单片机模块化编程万年历设计程序如下:main.h#ifndef __MAIN_H__#define __MAIN_H__#include<regx52.h>#include<intrins.h>#include<absacc.h>#define uchar unsigned char #define uint unsigned int#define DQ P3_7#endifds18b20.h#include "main.h"uint sec;uint min=41;uint hour=18;uint day=20;uint month=4;uint yearl=11;uint yearh=20;uint tcnt;uint cursor=0;uchar a=0xff;uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint t){uint i;while(t--){for (i=0;i<125;i++);}}void Tdelay(unsigned int i){while(i--);}void Kdelay(unsigned int z){uchar i,j;for(i=0;i<z;i++)for(j=248;j>0;j--);}Init_DS18B20(void){unsigned char x = 0;DQ = 1;Tdelay(200);DQ=0;Tdelay(80);DQ=1;Tdelay(200);Tdelay(200);}//读一个字节ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0;dat>>=1;DQ = 1;if(DQ)dat|=0x80;Tdelay(4);}return(dat);}//写一个字节WriteOneChar(unsigned char dat) {unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;Tdelay(5);DQ = 1;dat>>=1;}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0x44);Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0xBE);a=ReadOneChar();b=ReadOneChar();t=b;t<<=8;t=t|a;tt=t*0.0625;t= tt*10+0.5;return(t);}void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16) {P2=0x7F;P0=L1;delay(1); //yearhP2=0xBF;P0=L2;delay(1); //yearhif(cursor==6){P2=0xDF;P0=L3;delay(1);}else{P2=0xDF;P0=L3;delay(1);} //yearl if(cursor==6){P2=0xEF;P0=L4;delay(1);}else{P2=0xEF;P0=L4;delay(1);} //yearl if(cursor==5){P2=0xF7;P0=L5;delay(1);}else{P2=0xF7;P0=L5;delay(1);} //month if(cursor==5){P2=0xFB;P0=L6;delay(1);}else{P2=0xFB;P0=L6;delay(1);} //month if(cursor==4){P2=0xFD;P0=L7;delay(1);}else{P2=0xFD;P0=L7;delay(1);} //dayif(cursor==4){P2=0xFE;P0=L8;delay(1);}else{P2=0xFE;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3){P1=0x7F;P0=L9;delay(1);}else{P1=0x7F;P0=L9;delay(1);} //hourif(cursor==3){P1=0xBF;P0=L10;delay(1);}else{P1=0xBF;P0=L10;delay(1);} //hour if(cursor==2){P1=0xDF;P0=L11;delay(1);}else{P1=0xDF;P0=L11;delay(1);} //minif(cursor==2){P1=0xEF;P0=L12;delay(1);}else{P1=0xEF;P0=L12;delay(1);} //minif(cursor==1){P1=0xF7;P0=L13;delay(1);}else{P1=0xF7;P0=L13;delay(1);} //secif(cursor==1){P1=0xFB;P0=L14;delay(1);}else{P1=0xFB;P0=L14;delay(1);} //secP1=0xFD;P0=L15;delay(1); //tempP1=0xFE;P0=L16;delay(1); //tempP1=0xFF;}main.c#include "main.h"#include "ds18B20.h"void delay(uint t);void Tdelay(unsigned int i);void Kdelay(unsigned int z);Init_DS18B20(void);ReadOneChar(void);WriteOneChar(unsigned char dat);ReadTemperature(void);void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16); main(){uint i;TMOD=0x02; //设置模式为定时器T0的模式2 (8位自动重装计数初值的计数TH0=0x06; //设置计数器初值,靠TH0存储重装的计数值X0=256-250=6 TL0=0x06;TR0=1; //启动T0ET0=1; //开启定时器T0中断允许EA=1; //开启中断总控制while(1){if(P3_0==0){Kdelay(200);if(P3_0==0){cursor++;if(cursor>=7){cursor=0;}}}if(P3_1==0){Kdelay(200);if(P3_1==0){if(cursor==1){sec++;if(sec==60)sec=0;}if(cursor==2){min++;if(min==60)min=0;}if(cursor==3){hour++;if(hour==24)hour=0;}if(cursor==4){day++;if(day==31)day=0;}if(cursor==5){month++;if(month==12)month=0;}if(cursor==6){yearl++;if(yearl==100)yearl=0;}if(cursor==7){yearh++;if(yearh==30)yearh=20;}}}if(P3_2==0){Kdelay(200);if(P3_2==0){if(cursor==1){sec--;}if(cursor==2){min--;}if(cursor==3){hour--;}if(cursor==4){day--;}if(cursor==5){month--;}if(cursor==6){yearl--;}if(cursor==7){yearh--;}}i=ReadTemperature();display(Seg[yearh/10],Seg[yearh],Seg[yearl/10],Seg[yearl],Seg[month/10],Seg [month],Seg[day/10],Seg[day],Seg[hour/10],Seg[hour],Seg[min/10],Seg[min],Seg[sec/10 ],Seg[sec],Seg[i/100],Seg[i/10]);}}void t0(void)interrupt 1 using 0 //t0的中断程序{tcnt++;if(tcnt==4000)//定时器的定时计数,4000次250us为1秒{tcnt=0;P3_3=~P3_3;a=~a;sec++;if(sec==60){sec=0;min++;if(min==60){min=0;hour++;if(hour==24){hour=0;day++;if(month==2&&((yearl==0&&yearh%4==0)||(yearl!=0&&yearl%4==0))&& day==30)day=1;else if(month==2&&day==29)day=1;elseif((month==4||month==6||month==9||month==11)&&day==31)day=1;else if(day==32)day=1;if(day==1){month++;if(month==13){month=1;yearl++;if(yearl==100){yearl=0;yearh++;if(yearh==100) {yearh=20; }}}}}}}}}。
单片机课程设计--基于51单片机的万年历单片机课程设计基于 51 单片机的万年历一、引言在现代生活中,时间的准确记录和显示对于我们的日常生活和工作具有重要意义。
万年历作为一种能够同时显示年、月、日、星期、时、分、秒等信息的设备,给人们带来了极大的便利。
本次课程设计旨在利用 51 单片机实现一个简单实用的万年历系统。
二、系统设计方案(一)硬件设计1、单片机选型选择经典的 51 单片机,如 STC89C52 单片机,其具有性能稳定、价格低廉、资源丰富等优点,能够满足本设计的需求。
2、显示模块采用液晶显示屏(LCD1602)作为显示设备,能够清晰地显示数字和字符信息。
3、时钟芯片选用DS1302 时钟芯片,它可以提供精确的实时时钟数据,包括年、月、日、星期、时、分、秒等。
4、按键模块设置三个按键,分别用于调整时间、选择调整项(年、月、日、时、分、秒等)以及切换显示模式(正常显示和设置模式)。
(二)软件设计1、主程序流程系统初始化后,首先读取 DS1302 中的时间数据,并将其显示在LCD1602 上。
然后进入循环,不断检测按键状态,根据按键操作进行相应的时间调整和显示模式切换。
2、时间读取与显示程序通过与 DS1302 进行通信,读取实时时间数据,并将其转换为适合LCD1602 显示的格式进行显示。
3、按键处理程序检测按键的按下状态,根据不同的按键执行相应的操作,如调整时间、切换显示模式等。
三、硬件电路设计(一)单片机最小系统单片机最小系统包括单片机芯片、晶振电路和复位电路。
晶振电路为单片机提供时钟信号,复位电路用于系统初始化时将单片机的状态恢复到初始值。
(二)显示电路LCD1602 显示屏通过数据总线和控制总线与单片机相连。
数据总线用于传输要显示的数据,控制总线用于控制显示屏的读写操作和显示模式。
(三)时钟电路DS1302 时钟芯片通过串行通信接口与单片机进行通信。
单片机通过发送特定的指令和数据,对 DS1302 进行读写操作,获取或设置时间信息。
单片机课程设计报告万年历的设计基于51单片机的万年历摘要:电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
万年历的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89C52单片机,LCD显示电路,以及调时按键电路等组成。
在单片机的选择上本人使用了AT89C52单片机,该单片机适合于许多较为复杂控制应用场合。
显示器使用了1602液晶显示,并且使用蜂鸣器实现了整点报警的功能,温度测试的功能实现使用了DS18B20,并实现了温度过高或过低时的温度报警。
软件方面主要包括日历程序、时间调整程序,显示程序等。
程序采用C语言编写。
所有程序编写完成后,在KeilC51软件中进行调试,确定没有问题后,在Proteus软件中嵌入单片机内进行仿真,并最终实现基本要求。
综上所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
一、设计要求基本要求:1,8 个数码管上显示,显示时间的格式为(假如当前时间是19:32:20)“19-32-20”;2,具有日历功能;③时间可以通过按键调整。
发挥部分:④具有闹钟功能(可以设定多个)。
二:总体设计电路设计框图系统硬件概述本电路是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;时钟电路由单片机定时功能提供;温度的采集由DS18B20构成,它具有独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯,使用时不需要额外的外围电路。
原创性声明本人呈交的毕业论文,是在导师的指导下,独立进行研究工作所取得的成果,所有数据、图片资料真实可靠。
尽我所知,除文中已经注明引用的内容外,本毕业论文的研究成果不包含他人享有著作权的内容。
对本论文所涉及的研究工作做出贡献的其他个人和集体,均已在文中以明确的方式标明。
本毕业论文的知识产权归属于培养单位。
本人签名:日期:摘要随着社会的发展,信息量的不断提升以前对信息交换的要求提高,电子万年历的发展以及投入市场变得非常有必要。
本设计是基于51单片机并模拟日常所用的日历,而51系列单片机是各单片机中最为典型和最有代表性的一种。
通过本次设计,学习和巩固了单片机指令编程的相关知识,熟悉单片机各部件的组成及其功能。
本设计将制作一种基于单片机控制的带实时温度显示、具有定时功能的电子万年历。
传统的电子日历大都体积大,功耗大,显示不准确等特点。
为了缩小体积,减小功耗,使其变得小巧灵敏,本设计加入了时钟芯片DS1302,可对时间进行准确记时,同时可设置定时时间,实现定时功能。
另外本设计具有显示实时温度的功能。
传统的温度传感器系统大都采用放大、调理、A/D转换,转换后的数字信号送入计算机处理,处理电路复杂、可靠性相对较差,占用计算机的资源比较多。
本设计将采用DS18B20一线制数字温度传感器,可将温度信号直接转换成数字信号送给微处理器,电路简单,成本低,实现了时间温度同时显示的效果。
最后,温度和时间都将通过12864液晶显示器进行显示。
测试表明系统达到了设计要求的各项功能,各部分工作正常。
关键词:时钟温度检测单片机温度ABSTRACTWith the development of the society, the amount of information is improving the requirements of the information exchange. the development of the electronic calendar and the investment market become very necessary. This design is based on 51 single-chip microcomputer and simulation used in the daily calendar, and 51 series microcontroller is the MCU in the most typical and most representative one. Through this design, learning and consolidate the single chip microcomputer instruction programming knowledge, be familiar with composition and function of the microcontroller parts.This design creates an electronic calendar with real-time temperature display and timing function based on single chip control. Most of traditional calendars are characterized by large size, high power consumption and inaccurate display. In order to reduce volume and power consumption and make calendars become small and exquisite, the design adds a clock chip DS1302, which can accurately record the time and set a regular time to achieve timing function. In addition, this design displays real-time temperature function. Traditional temperature sensor system is mostly amplified, recuperated and A / D converted. The converted digital signal is input the computer to be processed, but the processing circuit is complicated with relatively poor reliability and occupies more resources of the computer. This design uses the DS18B20 first-line system digital temperature sensor to directly convert the temperature signal into digital signal and send it the microprocessor, whose circuit is simple and low cost, achieving the displayed effect of time and temperature simultaneously. Finally, the temperature and time will be displayed through the 12864 liquid crystal display. The test indicates that the system has reached various functions of the design requirements and each part operates smoothly.Keywords: clock temperature-detection SCM temperature目录1 绪论 (1)2 系统基本方案选择和论证 (1)2.1单片机芯片的选择方案和论证 (1)2.2显示模块的选择方案和论证 (1)2.3时钟芯片的选择方案和论证 (2)2.4温度传感器的选择方案和论证 (3)2.5电路设计最终方案确定 (4)3 系统硬件电路设计 (1)3.1系统功能模块划分 (1)3.2各单元模块功能分析及模块电路设计 (2)3.2.1时钟模块 (2)3.2.2温度模块 (2)3.2.3显示模块 (5)3.2.4独立键盘模块 (5)3.2.5蜂鸣器模块 (6)3.2.6单片机模块 (7)3.2.7温度信息的采集 (8)3.3电路原理图的绘制和电路的焊接 (1)3.3.1原理图绘制软件PROTEL (1)3.3.2PCB制作 (1)3.3.3元器件的焊接 (3)4 系统软件设计 (1)4.1万年历软件系统的流程图 (1)4.3温度的读取 (5)下面是温度读取的子程序: (6)4.4键盘模块 (6)4.5蜂鸣器模块 (6)结束语 (1)致谢 (1)参考文献 (1)附录 (1)1 绪论二十一世纪是数字化技术高速发展的时代,而单片机在数字化高速发的时代扮演着极为重要的角色。
第十届学生科技节-----单片机设计大赛作品名称:万年历专业:物联网班级:1****:***组长:邓清兰学号:3112113111组员:黄孟秋学号:3112113101目录一、绪论 0二、系统功能 0三、硬件电路 03.1. 电路设计框图 03.2. 系统硬件概述 (1)四、各模块功能及工作原理 (1)4.1. 单片机主控制模块的设计 (1)4.2. LCD1602显示模块 (2)4.3. 键盘模块 (5)五、实现结果 (8)六、系统的实用性及创新性 (9)七、调节中遇到的问题及心得体会 (9)八、程序设计 (10)8.1. 流程图 (10)8.2. 源代码 (11)九、总结及感谢 (23)一、绪论众所周知单片机是一种集成在电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的计算机系统。
本设计要制作的就是单片机于生活中最为常见的几种应用——万年历。
本设计以AT89S52单片机作为核心,可以显示当前的日历和时间,时间也可以人为设定,显示格式为年(四位),月(两位),日(两位),时(两位),分(两位),秒(两位)。
设置时间的位切换、设定数值、启动定时器、切换日历通过外部中断来实现。
万年历显示电路由LCD1602组成,制作该装置的材料需要有软硬件的支持,硬件方面AT89C51单片机,晶振,电源,液晶屏LCD1602。
蜡變黲癟報伥铉锚鈰赘。
二、系统功能本次设计的是万年历,采用LCD1602显示,实现的功能如下:1.显示当前时间,显示格式为年(四位),月(两位),日(两位),时(两位),分(两位),秒(两位);2.时钟计时,自动进行时间的位切换;3.键盘设置,能通过键盘设定当前时间和计时,并通过键盘人为设定时间。
三、硬件电路3.1.电路设计框图3.2.系统硬件概述本电路是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作,本系统选用12MHZ的晶振,使得单片机有合理的运行速度;利用液晶屏LCD1602显示时间信息,通过对AT89S52单片机的编程控制液晶屏LCD1602的显示。
显示时间在LCD1602,通过按键切换选择。
外部按键可及时设定或调整时间信息。
買鲷鴯譖昙膚遙闫撷凄。
四、各模块功能及工作原理4.1.单片机主控制模块的设计AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash 存储器。
AT89S52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3, MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出。
第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路,20引脚为接地端,40引脚为电源端。
引脚图如图图4.1:图4.1 AT89S52 引脚结构图4.2.1 LCD1602 引脚结构4.2.LCD1602显示模块4.2.1LCD1602引脚介绍LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,引脚图第1脚:VSS为地电源。
第2脚:VDD接5V正电源。
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
猫虿驢绘燈鮒诛髅貺庑。
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。
当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W 为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
锹籁饗迳琐筆襖鸥娅薔。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:D0~D7为8位双向数据线。
第15脚:背光源正极。
第16脚:背光源负极。
4.2.2LCD1602指令1602液晶模块内部的控制器共有11条控制指令,如表4.2.31602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
(说明:1为高电平、0为低电平)構氽頑黉碩饨荠龈话骛。
指令1:清显示,指令码01H,光标复位到地址00H位置。
指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置I/D:光标移动方向,高电平右移,低电平左移S:屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效。
輒峄陽檉簖疖網儂號泶。
指令4:显示开关控制。
D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:控制光标的开与关,高电平表示有光标,低电平表示无光标B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
尧侧閆繭絳闕绚勵蜆贅。
指令5:光标或显示移位S/C:高电平时移动显示的文字,低电平时移动光标。
指令6:功能设置命令DL:高电平时为4位总线,低电平时为8位总线N:低电平时为单行显示,高电平时双行显示F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
识饒鎂錕缢灩筧嚌俨淒。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
凍鈹鋨劳臘锴痫婦胫籴。
指令10:写数据。
指令11:读数据。
4.2.3 LCD1602读/写操作LCD1602基本操作时序说明,如表4.2.44.2.4 LCD1602显示模块流程图4.3.键盘模块本设计采用4乘4键盘的反转法控制万年历的计时和时间设定,4乘4键盘电路图如图图4.3.1图4.3.24.3.1键盘功能图0 1 2 34 8 + 59-6 7<!>@YY N Y NYN YN N4.4计时模块 4.4.1计数器工作原理计数器:是单片机应用中的重要部件,工作方式灵活,可以对外部事件计数和检测等;实现计数功能。
其核心是特殊功能寄存器中能进行加1计数的寄存器。
实现原理:对T0或T1引脚输入的外部脉冲计数,如下图:4.4.2N YY N N YNY五、实现结果六、系统的实用性及创新性基本功能:能显示当前时间和计时,实现基本时钟功能。
创新性:界面友好,能实现计时和键盘数字的时间设定和自增、自减的时间设定。
七、调节中遇到的问题及心得体会问题一LCD1602的初始化不规范,导致无法正确在LCD1602上显示相应的字符,时间等。
解决在网上及课本上查找有关LCD1602初始化的程序,找出错误的地方并及时改正,最终解决了LCD1602的初始化问题。
问题二在对秒、分、时、日、月、年等的大小判断时,采用逐位判断,导致程序冗长,不利于程序的优化。
解决通过老师的指导及其他相关程序的借鉴,对时间大小的判断进行优化,将秒的十位和各位合为一个整体进行判断,分、时、日、月、年类似。
问题三在计时模块中,因为细节问题,找不到导致不能正常计时的原因。
解决通过老师的精心指导,找到不能正常计时的原因,将中断次数的判断if(count>100)改为if(count>=100)即可。
问题四在键盘设计模块中,对空数组的定义无效。
解决通过查找相关资料,了解到空数组的定义要放在data中,不能放在code 中。
将空数组定义为uchar a[14]使其默认放在data中就解决了该问题。
八、程序设计8.1.流程图8.2.源代码#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code Buffer[4]={0xfe,0xfd,0xfb,0xf7};uchar code table[]={'0','1','2','3','4','5','6','7','8','9','<','>','+','-','!','@'};uchar code w[14]={0x83,0x84,0x85,0x86,0x88,0x89,0x8b,0x8c,0xc4,0xc5,0xc7,0xc8,0xca,0xcb}; uchar a[14];sbit E=P2^7; //1602使能引脚sbit RW=P2^6; //1602读写引脚sbit RS=P2^5; //1602数据/命令选择引脚void Delay(uint xms); //延时void Time0_Init(); //中断请求void timer1_int(void); //中断void charge(); //判断秒分时日月等是否大于额外值,若大于向上一位加一void ftime(); //初始时间void timeon(); //计时void add(); //自加void sub(); //自减void wcmd(uchar del); //1602写指令void write(uchar del); //1602写数据void L1602_init(void); //1602初始化void second(); //秒显示void minute(); //分显示void hours(); //时显示void days(); //日显示void month(); //月显示void years(); //年显示void other(); //符号显示void number(); //键盘输入数字uint count,t; //中断执行次数,光标位置参数uchar sec=0; //初始秒uchar min=0; //初始分uchar hour=0; //初始时uchar day=0; //初始日uchar mon=0; //初始月uchar yearh=0; //初始年前两位uchar yearl=0; //初始年后两位//1602命令函数void wcmd(uchar del){P0 = del;RS = 0;RW = 0;E = 1;Delay(1);E = 0;Delay(1);}// 1602写数据函数void write(uchar del){P0 = del;RS = 1;RW = 0;E = 1;Delay(1);E = 0;Delay(1);}// 1602初始化void L1602_init(void) {wcmd(0x38);wcmd(0x38);wcmd(0x38);wcmd(0x0e);wcmd(0x06);wcmd(0x01);}//显示秒void second(){uchar i,j;i=sec/10;j=sec%10;wcmd(0xca);write(table[i]);write(table[j]); }//显示分void minute(){uchar i,j;i=min/10;j=min%10;wcmd(0xc7);write(table[i]);write(table[j]); }//显示时void hours(){uchar i,j;i=hour/10;j=hour%10;wcmd(0xc4);write(table[i]);write(table[j]); }//显示日void days(){uchar i,j;i=day/10;j=day%10;wcmd(0x8b);write(table[i]);write(table[j]); }//显示月void month(){uchar i,j;i=mon/10;j=mon%10;wcmd(0x88);write(table[i]);write(table[j]); }//显示年void years(){uchar i,j,m,n;i=yearh/10;j=yearh%10;m=yearl/10;n=yearl%10;wcmd(0x83);write(table[i]);write(table[j]);write(table[m]);write(table[n]);}//符号显示void other(){wcmd(0xc9);write(':');wcmd(0xc6);write(':');wcmd(0x87);write('-');wcmd(0x8a);write('-');}//延时void Delay(uint xms){uint i,j;for(i=0;i<xms;i++)for(j=0;j<110;j++);}//计时void timeon(){if(count>=100){ count=0;charge();}ftime(); //显示初始时间}//时间初值void ftime(){second();Delay(5);minute();Delay(5);hours();Delay(5);days();Delay(5);month();Delay(5);years();Delay(5);other();Delay(5);}//各个按键返回值uint Keyvalue(){ uint i,j;uchar temp;uint Key_value;while(1){P1=0xf0;if(P1!=0xf0){Delay(100);if(P1!=0xf0)for(j=0;j<4;j++){P1=Buffer[j];temp=0x10;for(i=0;i<4;i++){if(!(P1&temp)){Key_value=i+j*4;}temp<<=1;}}return Key_value;}}}//字符串显示void L1602_string(uchar hang,uchar lie,uchar *p) {uchar a,b=0;if(hang == 1) a = 0x80;if(hang == 2) a = 0xc0;a = a + lie - 1;while(1){wcmd(a++);b++;if((*p == '\0')||(b==16)) break;write(*p);Delay(500);p++;}}//自增void add(){wcmd(w[t]); //光标置位if(t==1) //光标在第二个位置时{if(yearh<99) //判断年前两位是否小于99,是,年前两位加1,并显示{yearh++;years();}}else if(t==3) //光标在第四个位置时{if(yearl<99) //判断年后两位是否小于99,是,年后两位加1,并显示{yearl++;years();}}else if(t==5) //光标在第六个位置时{if(mon<12) //判断月是否小于12,是,月加1,并显示{mon++;month();}}else if(t==7) //光标在第八个位置时{if(day<30) //判断日是否小于30,是,日加1,并显示{day++;days();}}else if(t==9) //当光标在第十个位置时{if(hour<12) //判断时是否小于12,是,时加1,并显示{hour++;hours();}}else if(t==11) //光标在第十二个位置时{if(min<59) //判断分是否小于59,是,分加1,并显示{min++;minute();}}else if(t==13) //光标在第十四个位置时{if(sec<59) //判断秒是否小于59,是,秒加1,并显示{sec++;second();}}}//自减void sub(){wcmd(w[t]); //光标置位if(t==1) //光标在第二个位置时,判断年前两位是否大于0,是,年前两位减1,并显示{if(yearh>0){yearh--;years();}}else if(t==3) //光标在第四个位置时,判断年后两位是否大于0,是,年后两位减1,并显示{if(yearl>1){yearl--;years();}}else if(t==5) //光标在第六个位置时,判断月是否大于1,是,月减1,并显示{if(mon>1){mon--;month();}}else if(t==7) //光标在第八个位置时,判断日是否大于1,是,日减1,并显示{if(day>1){day--;days();}}else if(t==9) //光标在第十个位置时,判断时是否大于0,是,时减1,并显示{if(hour>0){hour--;hours();}}else if(t==11) //光标在第十二个位置时,判断分是否大于0,是,分减1,并显示{if(min>0){min--;minute();}}else if(t==13) //光标在第十四个位置时,判断秒是否大于0,是,秒减1,并显示{if(sec>0){sec--;second();}}}//主函数void main(){ uchar keys;uint i,key; //数组a的参数i=0;t=0; //位置参数L1602_init(); //1602初始化L1602_string(1,5,"Showtime"); //初始界面显示L1602_string(2,5,"Welcome!"); //初始界面显示while(1){key=Keyvalue(); //将键值赋值给keykeys=table[key];if(keys=='@') //判断键值是否为@,是,执行计时{Time0_Init();while(1)timeon();}else if(keys=='!') //判断键值是否为!,是,显示初始时间,光标在第一个位置{ftime();wcmd(0x83);}else if(keys=='-'||keys=='+') //判断键值是否为+或-{if(keys=='+') //键值为+,执行自加函数{add();}else //键值为-,执行自减函数{sub();}}//判断键值是否为<,是,光标不在最左边时,光标左移一位else if(keys=='<'){if(t>=1){i--;t=t-1;wcmd(w[t]);}}else if(keys=='>') //判断键值是否为>,是,光标不在最右边时,光标右移一位{if(t<13){i++;t=t+1;wcmd(w[t]);}}else //键值为数字键时,将键值放入a数组中,在调用函数,显示当前设置的时间{ number();i=i%14;a[i]=key;i++;t++;number();}}}//输入数字void number(){yearh=a[0]*10+a[1];yearl=a[2]*10+a[3];mon=a[4]*10+a[5];day=a[6]*10+a[7];hour=a[8]*10+a[9];min=a[10]*10+a[11];sec=a[12]*10+a[13];ftime();}//中断请求void Time0_Init(){TMOD=0X10;TH1=(65536-10000)/256;TL1=(65536-10000)%256;EA=1;ET1=1;TR1=1;}//中断void timer1_int(void) interrupt 3{count++;TH1=(65536-10000)/256;TL1=(65536-10000)%256;}//判断年月日是否超过额外值void charge(){sec++; //秒加1if(sec==60) //秒等于60时,分加1,秒置0{ sec=0;min++; }if(min==60) //分等于60时,时加1 ,分置0{ m in=0;hour++; }if(hour==24) //时等于24时,日加1,时置0{ hour=0;day++; }if(day==31) //日等于30时,月加1,日置1{ day=1;mon++; }if(mon==13) //月等于613时,年后两位加1,月置1{ mon=1;yearl++; }if(yearl==99) //年后两位等于99时,年前两位加1,年后两位置0{yearh=0;yearh++;if(yearh==99) //年前两位等于99时,年前两位置0yearh=0;}}九、总结及感谢在用单片机实现万年历的设计中使用到了AT89S52、LCD1602及其4*4键盘的使用。