带温度显示的万年历_数码管显示(附电路图和源代码)

合集下载

数码管显示万年历时钟

数码管显示万年历时钟

数码管显示万年历时钟数码管显示万年历时钟功能介绍一、功能说明:1.整体功能达到了市售电子日历效果,显示内容包括年、月、日、星期、时、分、秒、室温;2.实时时钟芯片采用了两种:DS12C887+和DS1302。

可供学习和使用过程中进行选择;3.数码管控制采用了MAX7219专用扫描驱动芯片,可通过PS/2键盘对数码管的显示亮度进行15级调节;4.电路板上留有PS/2键盘接口,用于调节当前时间、数码管显示亮度、闹铃时间。

这一点和变通电子日历用明显区别,以达到一个有点专业的电子钟的要求;5.电路板上安装有继电器,可作为简单的时间控制(定时控制)或温度控制装置;二、待改进之处:1.可在板上合适的位置增加几个独立按键,日常使用调节更方便些;2.显示内容可增加农历和湿度;3.可以用光敏电阻配合串行A/D转换芯片实现显示亮度的自动调节,以适应环境光线的变化,这样子就更加具有专业性了。

三、PS/2键盘调整说明:1.使用PS2键盘F1进入运行时间设定、F2进入数码管显示亮度设定、F3进入闹铃时间设定、F4启动闹铃、F5关闭闹铃2.按下F1然后依次设定年、月、日、星期、时、分、秒时间信息,中途可以按小键盘区的ENTER键,退出设定状态3.按下F2然后选择小键盘区0-9和字符A-F可设定16级显示亮度,按下选择参数自动恢复走时状态4.按下F3然后依次设定时、分、秒三个闹铃时间参数,设定好任一参数可按小键盘区的ENTER键退出设定状态5.按下F4开启闹铃,继电器吸合其下方工作指示LED点亮,按下F5关闭闹铃,继电器释放同时LED熄灭,如蜂鸣器已经开始闹铃,可按F6或复位键6.按下F1或F2或F3但不想设定任何参数,都可按ESC退出相应的设定状态。

具有温度指示的数字万年历设计方案

具有温度指示的数字万年历设计方案

具有温度指示的数字万年历设计方案1 绪论随着电子技术的迅速发展,特别是随大规模集成电路出现,给人类生活带来了根本性的改变。

由其是单片机技术的应用产品已经走进了千家万户。

其中电子万年历就是一个典型的例子。

而且在万年历的基础上还可以扩展其它的实用功能,比如温度计。

万年历是采用数字电路实现对.时,分,秒.数字显示的计时装置,广泛用于个人家庭,车站,码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。

诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,但是所有这些,都是以钟表数字化为基础的。

因此,研究万年历及扩大其应用,有着非常现实的意义。

市场上有许多电子钟的专用芯片如:LM8363 、LM8365 等,但它们功能单一,电路连接复杂,不便于调试制作。

但是考虑到用单片机配合时钟芯片,可制成功能任意的电子钟,而且可以做到硬件简单、成本低廉。

所以本系统采用了以广泛使用的单片机AT89S52 技术为核心,配合时钟芯片DS1302 。

软硬件结合,使硬件部分大为简化,提高了系统稳定性,并采用LCD 显示电路、键盘电路,使人机交互简便易行,此外结合音乐闹铃电路、看门狗和供电电路。

本方案设计出的数字钟可以显示时间、设置闹铃功能之外。

本文首先描述系统硬件工作原理,并附以系统结构框图加以说明,着重介绍了本系统所应用的各硬件接口技术和各个接口模块的功能及工作过程, 其次,详细阐述了程序的各个模块和实现过程。

本设计以数字集成电路技术为基础,单片机技术为核心。

本文编写的主导思想是软硬件相结合,以硬件为基础,来进行各功能模块的编写。

本设计中我重点研究实现了单片机+ 时钟芯片这种模式的万年历,从原理上对单片机和时钟芯片有了深一步的认识,这些基本功能完成后,在软件基础上实现时间显示。

带温度计的万年历

带温度计的万年历

设计课题题目: 带温度计的万年历一、设计任务与要求1. 显示准确的北京时间(时、分、秒)及公历日期显示功能(年、月、日);2. 可通过按键切换年、月、日及时、分、秒的显示状态;3. 可随时可以调校年、月、日或时、分、秒;4. 可每次增减一进行时间调节,也可快速增减进行时间调节;5.可显示环境温度。

二、系统设计方案方案一、用主芯片为AT89C51的单片机控制实现,使用单片机内部的定时计数器实现时间的设定,使用按键进行时间的调整和定时,按键有蜂鸣器提示,温度传感器使用DALLAS 公司生产的单总线式数字温度传感器,它具有微型化、低功耗、高性能、抗干扰能力强、易配处理器等优点。

显示时间和温度使用数码管显示。

方案二、用主芯片为STC89C52的单片机控制实现,为了满足单片机系统的实时控制的需求,采用实时钟芯片DS1302,使用按键进行时间的调整和定时,温度传感器使用 DS18B20。

显示时间和温度使用LCD1602显示。

方案一片内定时器会导致计时节拍的时间误差,当进行年、月、日的日历计时,定时中断误差扥积累就会很大。

使用片内定时器进行计时的时候,单片机始终要处于工作状态。

才能维持计时时间,一旦停机或进入待机状态,开机后,计时时间就需要重新设定。

为了满足单片机系统的实时钟需求,本设计采用的是方案二,系统框图如图2-1所示。

图2-1三、单元电路分析与设计1. 原理分析 1.1主控制器单片机STC89C52 具有低电压供电和体积小等特点,如图3-1所示。

1.2晶振电路AT89S52引脚XTAL1和XTAL2与晶体振荡器及电容C1、C2按图3-2所示方式连接。

晶振、电容C1/C2及片内与非门(作为反馈、放大元件)构成了电容三点式振荡器,振荡信号频率与晶振频率及电容C1、C2的容量有关,但主要由晶振频率决定,范围在0~33MHz 之间,电容C1、C2取值范围在5~30pF 之间。

根据实际情况,本设计晶振选择频率为12MHZ ,电容选择30pF 如图3-2。

基于单片机的具有温度指示的数字万年历设计

基于单片机的具有温度指示的数字万年历设计

目录1 绪论 (1)2 总体设计方案 (2)2.1设计思路 (2)2.2设计方案 (2)2.3方案比较论证 (2)2.4总体设计方框图 (3)3 设计原理与分析 (4)3.1硬件电路主要芯片的功能介绍 (4)3.1.1单片机主控制器 (4)3.1.2 温度传感器芯片 (5)3.1.3 时钟芯片DS1302 (9)3.1.4 16*2LCD液晶显示1602 (12)4 硬件电路 (15)4.1单片机主控制模块的设计 (15)4.2时钟电路模块的设计 (15)4.3温度采集模块设计 (16)4.4功能按钮设计 (16)4.516*2LCD1602液晶显示电路设计 (17)4.6总体电路图 (17)5 系统软件设计 (18)5.1系统模块的功能分划分 (18)5.2总体程序流程框图 (18)5.3时钟调整时间的流程图 (20)5.4修改键“UP”的功能流程图 (21)5.5温度转换流程图 (22)6 系统仿真测试 (23)6.1KEIL的使用 (23)6.2P ROTUES软件仿真 (28)致谢 (31)参考文献 (32)附录一总体电路的PCB板图 (33)附录二设计电路的仿真电路图 (34)附录二万年历源程序 (35)1 绪论随着电子技术的迅速发展,特别是随大规模集成电路出现,给人类生活带来了根本性的改变。

由其是单片机技术的应用产品已经走进了千家万户。

其中电子万年历就是一个典型的例子。

而且在万年历的基础上还可以扩展其它的实用功能,比如温度计。

万年历是采用数字电路实现对.时,分,秒.数字显示的计时装置,广泛用于个人家庭,车站,码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。

诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,但是所有这些,都是以钟表数字化为基础的。

万年历程序+电路图

万年历程序+电路图

基于单片机的万年历系统设计(一)顶层文件万年历.C#include<reg51.h>#include "LCD1602.h"#include "DS1302.h"#define uchar unsigned char#define uint unsigned intsbit speaker=P2^4;bit key_flag1=0,key_flag2=0;SYSTEMTIME adjusted;uchar sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0;uchar data_alarm[7]={0};/************键盘控制******************************/int key_scan() //扫描是否有键按下{ int i=0;uint temp;P1=0xf0;temp=P1;if(temp!=0xf0)i=1;elsei=0;return i;}uchar key_value() //确定按键的值{uint m=0,n=0,temp;uchar value;uchar v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'} ;P1=0xfe; temp=P1; if(temp!=0xfe)m=0;P1=0xfd;temp=P1 ;if(temp!=0xfd)m=1;P1=0xfb;temp=P1 ;if(temp!=0xfb)m=2;P1=0xf7;temp=P1 ;if(temp!=0xf7)m=3;P1=0xef;temp=P1 ;if(temp!=0xef)n=0;P1=0xdf;temp=P1 ;if(temp!=0xdf)n=1;P1=0xbf;temp=P1 ;if(temp!=0xbf)n=2;value=v[m][n];return value;}/***************************设置闹铃函数*******************************/void naoling(void){uchar i=0,l=0,j;init1602();while(key_flag2&&i<12)if(key_scan()){j=key_value();write_data(j);if(i%2==0)data_alarm[l]=(j-'0')*10;else {data_alarm[l]+=(j-'0');l++;}i++;delay(600);}write_com(0x01);}uchar according(void){ uchar k;if(data_alarm[0]==adjusted.Year&&data_alarm[1]==adjusted.Month&&data_alarm[2]==adj usted.Day&&data_alarm[3]==adjusted.Hour&&data_alarm[4]==adjusted.Minute&&data_al arm[5]==adjusted.Second)k=1;else k=0;return k;}void speak(void){uint i=50;while(i){speaker=0;delay(1);speaker=1;delay(1);i--;}}void alarm(void){uint i=10;while(i){speak();delay(10);i--;}}/**************************修改时间操作********************************/ void reset(void){sec_add=0;min_add=0;hou_add=0;day_add=0;mon_add=0;yea_add=0 ;}void adjust(void){if(key_scan()&&key_flag1)switch(key_value()){case '0':sec_add++;break;case '1':min_add++;break;case '2':hou_add++;break;case '3':day_add++;break;case '4':mon_add++;break;case '5':yea_add++;break;case 'b':reset();break;default: break;}adjusted.Second+=sec_add;adjusted.Minute+=min_add;adjusted.Hour+=hou_add;adjusted.Day+=day_add;adjusted.Month+=mon_add;adjusted.Year+=yea_add;if(adjusted.Second>59) adjusted.Second=adjusted.Second%60;if(adjusted.Minute>59) adjusted.Minute=adjusted.Minute%60;if(adjusted.Hour>23) adjusted.Hour=adjusted.Hour%24;if(adjusted.Day>31) adjusted.Day=adjusted.Day%31;if(adjusted.Month>12) adjusted.Month=adjusted.Month%12;if(adjusted.Year>100) adjusted.Year=adjusted.Year%100;}/**************************中断处理函数*********************************/ void changing(void) interrupt 0 using 0 //需要修改时间和日期,或者停止修改{if(key_flag1)key_flag1=0;else key_flag1=1;}void alarming(void) interrupt 3 using 0 //需要设置闹铃或者停止设置{if(key_flag2)key_flag2=0;else key_flag2=1;}/********************************主函数***********************************/ main(){uint i;uchar *l;uchar p1[]="D:",p2[]="T:";SYSTEMTIME T;EA=1;EX0=1;IT0=1;EA=1;EX1=1;IT1=1;init1602();Initial_DS1302() ;while(1){ write_com(0x80);write_string(p1,2);write_com(0xc0);write_string(p2,2);DS1302_GetTime(&T) ;adjusted.Second=T.Second;adjusted.Minute=T.Minute;adjusted.Hour=T.Hour;adjusted.Week=T.Week;adjusted.Day=T.Day;adjusted.Month=T.Month;adjusted.Year=T.Year;for(i=0;i<9;i++){adjusted.DateString[i]=T.DateString[i];adjusted.TimeString[i]=T.TimeString[i];}adjust();if(key_flag2)naoling();if(according())alarm();DateToStr(&adjusted);TimeToStr(&adjusted);write_com(0x82);write_string(adjusted.DateString,8);write_com(0xc2);write_string(adjusted.TimeString,8);delay(10);}(二)头文件1 显示模块LCD1602.H#ifndef LCD_CHAR_1602_2009_5_9#define LCD_CHAR_1602_2009_5_9#define uchar unsigned char#define uint unsigned intsbit lcdrs = P2^0;sbit lcdrw = P2^1;sbit lcden = P2^2;void delay(uint z) // 延时{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com) // 写入指令数据到lcd {lcdrw=0;lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date) // 写入字符显示数据到lcd {lcdrw=0;lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init1602() // 初始化设定{lcdrw=0;lcden=0;write_com(0x3C);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);}void write_string(uchar *pp,uint n){int i;for(i=0;i<n;i++)write_data(pp[i]);}#endif(三)头文件2 时钟模块DS1302.H#ifndef _REAL_TIMER_DS1302_2009_5_20_#define _REAL_TIMER_DS1302_2003_5_20_sbit DS1302_CLK = P2^6; //实时时钟时钟线引脚sbit DS1302_IO = P2^7; //实时时钟数据线引脚sbit DS1302_RST = P2^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;typedef struct SYSTEM_TIME{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[9]; //用这两个字符串来放置读取的时间unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算DS1302_RAM 地址的宏/******内部指令**********/void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0;DS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1; //因为在前面已经定义了ACC0 = ACC^0;以便再次利用DS1302_IO = ACC0;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1;ACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}/********************************/void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)Write1302(0x8E,0x10);elseWrite1302(0x8E,0x00);}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);Write1302(Address, ((Value/10)<<4 | (Value%10))); //将十进制数转换为BCD码} //在DS1302中的与日历、时钟相关的寄存器存放的数据必须为BCD码形式void DS1302_GetTime(SYSTEMTIME *Time){unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将BCD码转换为十进制数ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); }unsigned char *DataToBCD(SYSTEMTIME *Time){unsigned char D[8];D[0]=Time->Second/10<<4+Time->Second%10;D[1]=Time->Minute/10<<4+Time->Minute%10;D[2]=Time->Hour/10<<4+Time->Hour%10;D[3]=Time->Day/10<<4+Time->Day%10;D[4]=Time->Month/10<<4+Time->Month%10;D[5]=Time->Week/10<<4+Time->Week%10;D[6]=Time->Year/10<<4+Time->Year%10;return D;}void DateToStr(SYSTEMTIME *Time){//将十进制数转换为液晶显示的ASCII值Time->DateString[0] = Time->Year/10 + '0';Time->DateString[1] = Time->Year%10 + '0';Time->DateString[2] = '-';Time->DateString[3] = Time->Month/10 + '0';Time->DateString[4] = Time->Month%10 + '0';Time->DateString[5] = '-';Time->DateString[6] = Time->Day/10 + '0';Time->DateString[7] = Time->Day%10 + '0';Time->DateString[8] = '\0';}void TimeToStr(SYSTEMTIME *Time){//将十进制数转换为液晶显示的ASCII值Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';Time->TimeString[2] = ':';Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';Time->TimeString[5] = ':';Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';Time->DateString[8] = '\0';}void Initial_DS1302(void){unsigned char Second;Second=Read1302(DS1302_SECOND);if(Second&0x80) //初始化时间DS1302_SetTime(DS1302_SECOND,0);}void DS1302_TimeStop(bit flag) // 是否将时钟停止{unsigned char Data;Data=Read1302(DS1302_SECOND);DS1302_SetProtect(0);if(flag)Write1302(DS1302_SECOND, Data|0x80);elseWrite1302(DS1302_SECOND, Data&0x7F);}#endif附录2 系统电路图10。

课程设计___数字万年历(显示温度星期)

课程设计___数字万年历(显示温度星期)

信息与电子工程学院课程设计报告目录一、课程设计概述 (3)1、课程设计背景 (3)2、课程设计内容 (3)二、方案的选择及确定 (3)2.1设计思路 (3)2.2设计方案 (3)2.3 方案比较论证 (3)三、系统硬件设计 (4)3.1总体硬件设计 (4)3.2 单片机主控制模块的设计 (4)3.3 时钟电路模块的设计 (5)3.4 温度采集模块设计 (6)3.5 功能按钮设计 (6)3.6 16*2 LCD1602液晶显示电路设计 (7)3.7总体电路图 (7)四、系统软件设计 (8)4.1 系统模块的功能分划分 (8)4.2 总体程序流程框图 (9)4.3 时钟调整时间的流程图 (9)4.4 修改键“UP”的功能流程图 (10)4.5温度转换流程图 (11)五、系统调试过程 (13)六、遇到的问题及解决方法/总结 (13)七、参考文献 (13)八、附录 (13)1、仪器与设备 (13)2、元器件清单 (14)3、原理图 (14)4、PCB图 (15)5、实物图 (15)6、操作说明书 (16)一、课程设计概述1、课程设计背景随着计算机技术的和控制系统的广泛应用,以及设备向小型化、智能化发展,单片机作为高新技术之一,以其体积小、功能强、价格低、使用灵活等优势,显示出了很强的生命力。

进入21世纪以来,开发推出单片机的公司很多,各种高性能单片机芯片市场异常活跃,新技术的不断采用,更加使单片机的种类、性能以及应用领域不断扩大和提高。

因其功耗低、超高型、低成本、功能完整,在国内越来越受到用户的重视和广泛使用。

2、课程设计内容要求设计的单片机作息时间控制钟完成以下功能:①实时显示当前温度;②实时显示当前时间;③实时显示当前日期;④能修改当前时钟二、方案的选择及确定2.1设计思路用STC89C52RC处理产生内部时钟数据或者读取外部时钟数据和采集外部传感器的信息进行处理,并暂时寄存在其内部的储存器中,再通过单片机调用内部RAM 的数据并送到LCD或者LED数码管上显示出来。

智能时钟万年历(详细电路图)

智能时钟万年历(详细电路图)

《嵌入式课程设计》讲义项目1 智能数字万年历一.项目指标分析项目指标要求如下:1. 显示年、月、日、时、分、秒和星期。

2. 实时显示温度。

3. 可手动调整时间。

4. 采用LCD显示。

基于以上要求,核心控制芯片选用STC89C51;时钟芯片选用DS1302;温度传感器选用DS18B20;液晶屏选用LCD1602;设置按键,以便于调整时间。

二.电路原理系统电路功能图如图1所示:图1 智能数字万年历电路功能图由图1可知,P2口控制LCD的数据端;P3.5、P3.6和P3.7控制着LCD的片选、读/写和寄存器选择信号;可调电阻RP2用于调节屏的显示对比度。

P3.4是温度传感器DS18B20的1-wire接口,即片选、时钟和数据信号均由P3.4口控制。

P0.5、P0.6和P0.7是时钟芯片DS1302的SPI接口,为使信号控制更稳定,这三个接口上都上拉了10KΩ电阻;为获得精准的时钟信号,选用频率为32.768KHz的外部晶振对DS1302提供振荡信号。

P0.0-P0.3控制着四个按键,以便于调整时间。

三.程序设计基于这个项目,程序的设计可分成各芯片驱动程序设计和控制算法程序两部分。

1.各芯片的驱动程序设计在写驱动程序时,首先通读芯片手册,以掌握主要技术指标;然后可按照以下3个步骤进行:(1)分清楚各芯片的通信属于哪种接口方式,例如:时钟芯片DS1302按照SPI 接口进行通信;温度传感器DS18B20按照1-wire接口进行通信;液晶屏LCD1602采用常规的并行数据传输方式。

(2)仔细分析芯片时序图,弄清楚片选信号是高电平有效还是低电平有效;数据是在时钟信号的上升沿还是下降沿时打入;数据前还是时钟前等。

(3)将功能程序函数化、驱动程序模块化。

2.控制算法程序设计这里的算法主要集中在如何设置按键识别程序,即便于调整时间,又不影响液晶屏的显示。

这里,提供两种思想以便参考。

(1)循环扫描方式流程图图2 循环扫描方式流程图(2图3 状态机方式流程图将图2和图3比较起来看,两种方式的最大差别在于“10ms消抖时间如何度过?”。

具有温度显示的电子实时时钟万年日历系统的设计与制作

具有温度显示的电子实时时钟万年日历系统的设计与制作

毕业设计(论文)《具有温度显示的电子实时时钟/万年日历系统的设计与制作》专业(系)电气工程系铁道通讯信号方向班级铁道通讯091学生姓名陈志军指导老师赵巧妮完成日期2011.11.22摘要本设计以数字集成电路技术为基础,单片机技术为核心。

本文详细的介绍基于AT89S51单片机带有温度和闹钟的万年历控制系统。

利用单片机定时计数器提供秒信号,DS18B20数字式温度传感器进行温度数据传输,经软件处理,在动态扫描后,利用8个共阳数码管交替显示年月日、时分秒、环境温度值。

为了更好的调节和设置,设计了四个按键快速进行时间和闹钟的精准调整。

关键字:单片机;万年历;温度;闹钟;DS18B20AbstractThis design with digital integrated circuit technology as the foundation, microcontroller technology as the core. This paper is introduced in detail based on AT89S51 with temperature and the alarm clock calendar control system. Using single chip computer timing counter offer seconds signal, the temperature sensor DS18B20 digital temperature data transmission, the software processing, in dynamic scan, a total of 8 Yang digital tube alternate show dates, meticulous, environment when the temperature. In order to better regulate and settings, design the four keys of rapid time and alarm the accuracy of adjustment.Key words:Microcomputer; Calendar;Temperature; Alarm clock; DS18B20; Dynamic scanning目录摘要 (I)第1章引言 (1)1.1研究背景 (1)1.2论文研究目标和意义 (1)1.3论文章节安排 (1)第2章任务与要求 (2)2.1课题概述 (2)2.1.1 设计内容 (2)2.1.2 要求 (2)第3章方案论证与设计 (3)3.1 总体设计分析 (3)3.2 方案的选择与设计 (3)3.2.1 显示模块选择方案和论证: (3)3.2.2 时钟芯片的选择方案和论证: (3)3.2.3 温度传感器的选择方案与论证: (4)3.3 方案确定 (4)第4章硬件电路设计 (5)4.1 硬件电路设计框图 (5)4.1.1 系统硬件概述 (5)4.1.2 单片机主控制模块的设计 (5)4.1.3 振荡电路 (6)4.1.4 复位电路 (6)4.1.5 温度采集模块设计 (6)4.1.6 显示模块的设计 (7)4.1.7 蜂鸣器电路 (8)4.1.8 按键电路 (8)第5章系统的软件设计 (10)5.1编程环境及语言: (10)5.2程序流程框图 (10)第6章电路调试 (12)6.1调试的设备 (13)6.2调试步骤 (13)6.2.1 硬件调试 (13)6.2.2 软件调试 (13)第7章使用说明 (17)7.1 使用方法 (17)7.1.1 系统面板介绍 (17)7.1.2 调整方法 (17)7.1.3 调整框图 (18)7.1.3 注意事项 (19)7.2故障分析 (19)7.2.1 LED数码管显示不全、模糊、多出相对较暗的一位 (19)7.2.2 调整时按键过于灵敏 (19)心得体会 (20)参考文献 (21)附件 (22)附件一:总原理图 (22)附件二:PCB版图 (23)附件三:元件清单 (24)附录四:程序代码 (26)引言1.1研究背景当今社会逐渐步入信息化时代,快节奏、高效率成为当今时代的主题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

设计报告设计任务:设计一个智能化万年历时钟电路,LED数码管作为电路的显示部分,按钮开关作为调时部分,通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期、温度。

并能准确计算闰年闰月的显示。

设计要求:通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期等功能,并能准确计算闰年闰月的显示,三个个按钮连接P3.0、P3.1、P3.2可以精确调整每一个时间数值,通过对所设计的万年历时钟电路进行实验测试,达到了动态显示时间,随时调整时间等技术所连线路和单片机接口仿真图如图3所示:图3 仿真按键4)温度采集部分:DS18B20温度传感器,测温范围-55℃~+125℃,固有测温分辨率0.5℃。

独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。

DS18B20的采集数据通过DQ传入单片机,单片机读取数据后将数据输出!如图所示:程序如下:ReadOneChar(void){unsigned char i=0;// 定义i用于循环unsigned char dat = 0;// 读取的8位数据for (i=8;i>0;i--)//8次循环{DQ = 0;// 拉低DQ总线开始读时序dat>>=1;// dat左移一位DQ = 1; //释放DQ总线if(DQ)// 如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat 即为读取的数据)//DQ=0,就跳过dat|=0x80;Tdelay(4);// 延时以完成此次读时序,之后再读下一数据}return(dat); 返回读取的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);// 写指令,跳过ROM,WriteOneChar(0x44);// 启动温度转换Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0xBE);// 写指令,读暂存存储器a=ReadOneChar();//读低8位b=ReadOneChar();//读高8位t=b;//t<<=8;//t=t|a;//tt=t*0.0625;//t= tt*10+0.5;//return(t); //获得0.01°C 的精度并返回}LED数码管的选择LED数码管分为共阴和共阳两种,以利用STC89C51的P0口作为LED显示的数据部分,以P2口的七个口作为显示部分的位选,通过三八译码器和4-16译码器扩展为17位的位选分别接在一个四位数码管和13个数码管的位选部分。

详细电路图如图4-5所示:程序如下:P2=0xF0;P0=L1;delay(1); //yearh P2=0xF1;P0=L2;delay(1); //yearhif(cursor==8){P2=0x1F|a;P0=L17;delay(1);}else{P2=0x1F;P0=L17;delay(1);}//weekif(cursor==6){P2=0xF2|a;P0=L3;delay(1);}else{P2=0xF2;P0=L3;delay(1);} //yearlif(cursor==6) {P2=0xF3|a;P0=L4;delay(1);}else{P2=0xF3;P0=L4;delay(1);} //yearlif(cursor==5) {P2=0xF4|a;P0=L5;delay(1);}else{P2=0xF4;P0=L5;delay(1);} //monthif(cursor==5) {P2=0xF5|a;P0=L6;delay(1);}else{P2=0xF5;P0=L6;delay(1);} //monthif(cursor==4) {P2=0xF6|a;P0=L7;delay(1);}else{P2=0xF6;P0=L7;delay(1);} //dayif(cursor==4) {P2=0xF7|a;P0=L8;delay(1);}else{P2=0xF7;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3) {P2=0xF8|a;P0=L9;delay(1);}else{P2=0xF8;P0=L9;delay(1);} //hourif(cursor==3) {P2=0xF9|a;P0=L10;delay(1);else{P2=0xF9;P0=L10;delay(1);} //hourif(cursor==2) {P2=0xFA|a;P0=L11;delay(1);}else{P2=0xFA;P0=L11;delay(1);} //minif(cursor==2) {P2=0xFB|a;P0=L12;delay(1);}else{P2=0xFB;P0=L12;delay(1);} //minif(cursor==1) {P2=0xFC|a;P0=L13;delay(1);}else{P2=0xFC;P0=L13;delay(1);} //secif(cursor==1)P2=0xFD|a;P0=L14;delay(1);}else{P2=0xFD;P0=L14;delay(1);} //secP2=0xFE;P0=L15;delay(1); //tempP2=0x0F;P0=L16;delay(1); //tempP2=0xFF;}图5 日期显示仿真实验整个电路仿真图如下图6所示所示:图6 仿真电路图实物的制作与调试(1)原理图的绘制与PCB的制作(2)原理图的绘制(3)在Protel99se中先新建一个工程,把所需要的元件载入到文档里面。

(4)按照所设计的电路画原理图(5)通过电气检查是否有错,并修改完善。

原理图如图7所示:显示部分图7 原理图系统实现:1、方案设计、方案比较方案一:采用实时时钟芯片实时时钟芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据的更新每秒自动进行一次,不需程序干预。

计算机可通过中断或查询方式读取数据进行显示,因此计时功能的实现无需占用CPU的时间,程序简单。

此外,实时时钟芯片多数带有锂电池做后备电源,具备永不停止的计时功能;具有可编程方波输出功能,可用做实时测控系统的采样信号等;有的实时时钟芯片内部还带有非易失性RAM,可用来存放需长期保存但有时也需变更的数据。

由于功能完美,精度高,软件程序设计相对简单,且计时不占用CPU时间,因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。

方案二:软件控制利用单片机内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时,该方案节省硬件成本,且能使设计者对单片机的指令系统能有更深入的了解,从而掌握单片机应用技术MCS-51汇编语言程序设计方法,因此,本系统设计采用此种软件控制方法来实现时, STC89C51单片机是低功耗的具有4KB在线可编程FLASH存储器的单片机。

它与通用80C51系列单片机的指令第和引脚兼容。

片内的FLASH集成在一个芯片上,形成了功能强大、使用灵活和具有较高性能价格比的微控制器。

它的功能强大,而且也较容易购买。

总结:所要实现的功能通过单片机编程就可以达到,不需要额外的时钟芯片来增加成本,并使外围电路更加简单明了。

3、实验步骤(1)、给电路通上电源, LED显示是否通电;(2)、电路板上分别选择模式、+ 和 - 按键,可以对时间和日期进行任意的调整,数码管分别显示日期和时间;调整模式按键按下表示对时间开始进行调整,通过选位来确定所要调整的位置,分别可以加和减。

(3)、用一个四位数码管和13个数码管,可显示时间和日期。

实验实物图如图11-12所示:总结:经过测试,我所做的万年历相对稳定,并且能准确的计时以及调整时间,经过这次试验懂得了仿真与实物是有差别的,也学会了很多。

实验总结:1、这次我的设计的任务是万年历时钟的设计,通过C51芯片程序控制显示万年历。

本次实验是设计一个智能化万年历时钟电路,LED数码管作为电路的显示部分,按钮作为调整时间和日期部分,可任意的对时间进行所需的调整,通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期、温度等功能,并能准确计算闰年闰月的显示。

2、我采用的是12MHZ的晶振,再通过一系列的计算从而实现万年历时钟的基本功能。

在实验调试过程中,出现了很多的问题,仿真时不需要数码管驱动依然能够实现所需的功能,但实验时出现了数码管亮度达不到要求的情况。

我采用了以下方案来驱动数码管:1)74LS138和74HC154作为位选驱动;2)在P0口接的上拉电阻,在这个过程中又涉及了上拉电阻的大小,开始用10K的电阻,因为电阻过大,使电流不能达到要求,以至于不能增加数码管的亮度。

最后我们换用1K的上拉电阻,成功的实现了我们所要得到的结果,数码管的亮度达到了所需的要求。

3、在做板过程中出现的线断路问题;通过万用表的检测一一排除和焊接!4、本次实验让自己对单片机的应用有了进一步的了解,对程序也有了更深的体会!元件清单附录源程序如下所示:#define uchar unsigned char#define uint unsigned int#define DQ P3_7#include<AT89X51.H>uint sec; 初始化秒uint min=50;//初始化分钟uint hour=9;// 初始化时uint day=10;// 初始化天uint month=6;// 初始化月uint yearl=11;// 初始化年低位uint yearh=20;// 初始化年高位uint week=6;// 初始化星期uint tcnt; // 定义tcnt变量uint cursor=0;// 定义cursor变量uchar a=0xff;定义a变量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(){uchar i,j;//定义I J 变量for(i=100;i>0;i--)for(j=248;j>0;j--);}//延时Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位Tdelay(8); //稍做延时DQ = 0; //单片机将DQ拉低Tdelay(80); //精确延时,大于480usDQ = 1; //拉高总线Tdelay(14);Tdelay(20);//延时}//读一个字节ReadOneChar(void){unsigned char i=0;// 定义i用于循环unsigned char dat = 0;// 读取的8位数据for (i=8;i>0;i--)//8次循环{DQ = 0;// 拉低DQ总线开始读时序dat>>=1;// dat左移一位DQ = 1; //释放DQ总线if(DQ)// 如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat 即为读取的数据)//DQ=0,就跳过dat|=0x80;Tdelay(4);// 延时以完成此次读时序,之后再读下一数据}return(dat); 返回读取的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);// 写指令,跳过ROM,WriteOneChar(0x44);// 启动温度转换Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0xBE);// 写指令,读暂存存储器a=ReadOneChar();//读低8位b=ReadOneChar();//读高8位t=b;//t<<=8;//t=t|a;//tt=t*0.0625;//t= tt*10+0.5;//return(t); //获得0.01°C 的精度并返回}void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,uchar L8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16,uchar L17)/***********动态显示数码管的时间**************/{P2=0xF0;P0=L1;delay(1); //yearhP2=0xF1;P0=L2;delay(1); //yearhif(cursor==8){P2=0x1F|a;P0=L17;delay(1);}else{P2=0x1F;P0=L17;delay(1);}//weekif(cursor==6){P2=0xF2|a;P0=L3;delay(1);}else{P2=0xF2;P0=L3;delay(1);} //yearlif(cursor==6){P2=0xF3|a;P0=L4;delay(1);}else{P2=0xF3;P0=L4;delay(1);} //yearlif(cursor==5) {P2=0xF4|a;P0=L5;delay(1);}else{P2=0xF4;P0=L5;delay(1);} //monthif(cursor==5) {P2=0xF5|a;P0=L6;delay(1);}else{P2=0xF5;P0=L6;delay(1);} //monthif(cursor==4) {P2=0xF6|a;P0=L7;delay(1);}else{P2=0xF6;P0=L7;delay(1);} //dayif(cursor==4) {P2=0xF7|a;P0=L8;delay(1);}else{P2=0xF7;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3) {P2=0xF8|a;P0=L9;delay(1);}else{P2=0xF8;P0=L9;delay(1);} //hourif(cursor==3) {P2=0xF9|a;P0=L10;delay(1);}else{P2=0xF9;P0=L10;delay(1);} //hourif(cursor==2) {P2=0xFA|a;P0=L11;delay(1);}else{P2=0xFA;P0=L11;delay(1);} //minif(cursor==2) {P2=0xFB|a;P0=L12;delay(1);}else{P2=0xFB;P0=L12;delay(1);} //minif(cursor==1) {P2=0xFC|a;P0=L13;delay(1);}else{P2=0xFC;P0=L13;delay(1);} //secif(cursor==1) {P2=0xFD|a;P0=L14;delay(1);}else{P2=0xFD;P0=L14;delay(1);} //secP2=0xFE;P0=L15;delay(1); //tempP2=0x0F;P0=L16;delay(1); //tempP2=0xFF;}main(){uint i;TMOD=0x02; //设置模式为定时器T0的模式2 (8位自动重装计数初值的计数值)TH0=0x06; //设置计数器初值,靠TH0存储重装的计数值X0=256-250=6TL0=0x06;TR0=1; //启动T0ET0=1; //开启定时器T0中断允许EA=1; //开启中断总控制while(1){P3_0=1;if(P3_0==0){delay(10);if(P3_0==0)//如果按键被按下{Kdelay();if(P3_0==0)//确定按键按下{while(P3_0==0); // 等待按键放开cursor++;if(cursor>=9){cursor=0;}//如果cursor大于9则cursor=0if(P1_0==0){cursor=0;}} }}P3_1=1;if(P3_1==0){delay(10);if(P3_1==0) //如果按键被按下{Kdelay();if(P3_1==0) //确定按键按下{if(cursor==1){sec++;//如果cursor=1则按键按下秒数加一if(sec==60)sec=0;//如果秒数等于60秒则回到0开始}if(cursor==2){min++;//如果cursor=2则按键按下分数加一if(min==60)min=0; 如果分数等于60分则回到0开始}if(cursor==3){hour++;//如果cursor=3则按键按下时数加一if(hour==24)hour=0; //如果时数等于24时则回到0开始}if(cursor==4){day++;//如果cursor=4则按键按下天数加一if(day==31)day=0; //如果天数等于31天则回到0开始}if(cursor==5){month++;//如果cursor=5则按键按下月数加一if(month==13)month=0; //如果月数等于13月则回到0开始}if(cursor==6){yearl++;//如果cursor=6则按键按下年数低位加一if(yearl==100)yearl=0; //如果年数等于100则回到0开始}if(cursor==7){yearh++;//如果cursor=7则按键按下年数高位加一if(yearh==30)yearh=20; //如果年数大于30则回到0开始}{week++;//如果cursor=8则按键按下星期数加一if(week==8)week=1; //如果星期数等于8则回到0开始}}while(P3_1==0);}}P3_2=1; //写入时先写1if(P3_2==0){//按键按下delay(10);//延时10个毫秒if(P3_2==0)//确定按键按下{Kdelay();if(P3_2==0){if(cursor==1){sec--;//如果cursor=1则按键按下秒数减一if(sec==0)sec=59; //如果秒数小于0则回到59开始}if(cursor==2){min--;//如果cursor=2则按键按下分数减一if(min==0)min=59; //如果分数小于0则回到59开始}if(cursor==3){hour--;//如果cursor=3则按键按下时数减一if(hour==0)hour=23; //如果时数小于0则回到23开始}if(cursor==4){day--;//如果cursor=4则按键按下天数减一if(day==0)day=31; //如果天数小于0则回到31开始}if(cursor==5){month--;//如果cursor=5则按键按下月数减一month=12; //如果月数小于0则回到12开始}if(cursor==6){yearl--;//如果cursor=6则按键按下年的低位数减一if(yearl==0)yearl=99; //如果年数小于0则回到99开始}if(cursor==7){yearh--;//如果cursor=7则按键按下年的高位数减一if(yearh==20)yearh=30; //如果年数小于0则回到30开始}if(cursor==8){week--;//如果cursor=8则按键按下秒星期减一if(week==0)week=7; //如果星期数小于0则回到7开始}while(P3_2==0);}}}i=ReadTemperature();display(Seg[yearh/10],Seg[yearh%10],Seg[yearl/10],Seg[yearl%10],Seg[ month/10],Seg[month%10],Seg[day/10],Seg[day%10],Seg[hour/10],Seg[hou r%10],Seg[min/10],Seg[min%10],Seg[sec/10],Seg[sec%10],Seg[i/100],Seg [i/10%10],Seg[week%10]); // 数据显示}}void t0(void)interrupt 1 using 0 //t0的中断程序{tcnt++;if(tcnt==4000)//定时器的定时计数,4000次250us为1秒{tcnt=0;sec++;if(sec==60){sec=0; 秒计到60时清0min++;//分数加一if(min==60){min=0; //分数计到60时清0hour++; //时数加一if(hour==24){hour=0;时数计到24时回到0开始day++;week++;天数和星期加一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;//天计到32时清1if(day==1){month++;//月数加一if(month==13){month=1;// 月数计到1时清1yearl++;//年的低位加一if(yearl==100){yearl=0;//年低位数计到100时清0yearh++;//高位加一if(yearh==100)//如果高位年数计到100 {yearh=20;//高位年数回到20}}}}}}}}}。

相关文档
最新文档