《2022年电子综合方案单片机多功能数字时钟 2》由会员分享,可在线阅读,更多相关《2022年电子综合方案单片机多功能数字时钟 2(11页珍藏版)》请在金锄头文库上搜索。
1、个人资料整理仅限学习使用课题: 基于 51 单片机的多功能数字时钟系统设计一、 概述、设计思路该设计方案是以MC51单片机为核心,采用LCD液晶屏幕显示系统,辅以闹钟模块,温度采集模块、日期提醒、键盘时间调整预设置等模块,所构建的数字时钟系统,能动态显示实时时钟的时、分、秒,数据显示( 误差限制在30每天 ,对闹铃方式与温度调节模块进行了重点设计实现SB0 、 SB1 、SB2、SB3 四个键实现时钟正常显示,调时,及闹钟时间设置。本系统设计大部分功能有软件来实现,使电路简单明了,系统稳定性也得大大提高。二、系统组成与工作原理1、工作原理:本设计采用STC89C51单片机作为本次课程设计的控制
2、模块。单片机可把由DS18B20 、DS1302 、AT24C02中的数据利用软件来进行处理,从而把数据传输到显示模块,实现温度、日历和闹铃的显示。以LCD液晶显示器为显示模块,把单片机传来的的数据显示出来,并且显示多样化,在显示电路中,主要靠按键来实现各种显示要求的选择与切换。2、总是设计框架图:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 1 页,共 11 页个人资料整理仅限学习使用图二:系统总体电路图三、单元电路的设计与分析整个电子时钟系统电路可分为六大部分:中央处理单元CPU )、复位电路部分、显示部分、键盘输入部分、温度采集部分。1、M
3、CS-51 单片机89S51各引脚功能介绍:VCC :89S51 电源正端输入,接+5V。VSS:电源地端。XTAL1 :单芯片系统时钟的反相放大器输入端。XTAL2 :系统时钟的反相放大器输出端,一般在设计上只要在XTAL1 和XTAL2 上接上一只石英振荡晶体系统就可以动作了,此外可以在两引脚与地之间加入一 20PF 的小电容,可以使系统更稳定,避免噪声干扰而死机。RESET:89S51的重置引脚,高电平动作,当要对晶片重置时,只要对此引脚电平提升至高电平并保持两个机器周期以上的时间,AT89S51便能完成系统重置的各项动作,使得内部特殊功能寄存器之内容均被设成已知状态,并且至地址0000
4、H处开始读入程序代码而执行程序。EA/Vpp :EA 为英文 External Access的缩写,表示存取外部程序代码之意,低电平动作,也就是说当此引脚接低电平后,系统会取用外部的程序代码存于外部 EPROM中)来执行程序。因此在8031及8032中, EA引脚必须接低电平,因为其内部无程序存储器空间。如果是使用8751 内部程序空间时,此引脚要接成高电平。此外,在将程序代码烧录至8751内部 EPROM时,可以利用此引脚来输入 21V的烧录高压 Vpp )。AT89S51 精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 2 页,共 11 页个人
5、资料整理仅限学习使用ALE/PROG :端口 3的管脚设置:P3.0:RXD ,串行通信输入。P3.1:TXD ,串行通信输出。P3.2:INT0 ,外部中断 0输入。P3.3:INT1 ,外部中断 1输入。P3.4:T0,计时计数器0输入。P3.5:T1,计时计数器1输入。P3.6:WR :外部数据存储器的写入信号。P3.7:RD,外部数据存储器的读取信号。2、复位电路MCS-51 单片机的复位是由外部的复位电路来实现的。复位引脚RST 通过一个斯密特触发器与复位电路相连,斯密特触发器用来抑制噪声,在每个机器周期的S5P2,斯密特触发器的输出电平由复位电路采样一次,然后才能得到内部复位操作所
6、需要的信号。上电复位:上电复位电路是种简单的复位电路,只要在RST复位引脚接一个电容到VCC ,接一个电阻到地就可以了。上电复位是指在给系统上电时,复位电路通过电容加到RST 复位引脚一个短暂的高电平信号,这个复位信号随着VCC对电容的充电过程而回落,所以RST引脚复位的高电平维持时间取决于电容的充电时间。为了保证系统安全可靠的复位,RST引脚的高电平信号必须维持足够长的时间。电路图如下:上电自动复位是通过外部复位电路的电容充电来实现的。只要Vcc 的上升时间不超过1ms ,就可以实现自动上电复位。3、时钟电路时钟是单片机的心脏,单片机各功能部件的运行都是以时钟频率为基准,有条不紊的一拍一拍地
7、工作。因此,时钟频率直接影响单片机的速度,时钟电路的质量也直接影响单片机系统的稳定性。常用的时钟电路有两种方式:一种是内部时钟方式,另一种为外部时钟方式。本文用的是内部时钟方式。电路图如下:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 3 页,共 11 页个人资料整理仅限学习使用MCS-51 单片机内部有一个用于构成振荡器的高增益反相放大器,该高增益反向放大器的输入端为芯片引脚XTAL1,输出端为引脚XTAL2。这两个引脚跨接石英晶体振荡器和微调电容,就构成一个稳定的自激振荡器。4、显示电路采用 LCD 显示, LCD 显示具有丰富多样性,灵活性
8、,电路简单、易于控制而且功耗小,对于信息量多的系统,是比较适合的,LCD 液晶显示模块采用LCD1602 型号,具有很低的功耗,正常工作室电流仅2.0mA/5.0V。通过编程实现总动关闭屏幕能够更有效地降低功耗。LCD1602 分两行显示,每行可现实多达16个字符,其内部的字符发生器已经存储了160个不同的点阵字符图形,通过内部指令可实现对其显示多样的控制。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 4 页,共 11 页个人资料整理仅限学习使用5、 按键电路按键的开关状态通过一定的电路转换为高、低电平状态。按键闭合过程在相应的I/O 端口形成一
9、个负脉冲。闭合和释放过程都要经过一定的过程才能达到稳定,这一过程是处于高、低电平之间的一种不稳定状态,称为抖动。抖动持续时间的常长短与开关的机械特性有关,一般在5-10ms 之间。为了避免CPU多次处理按键的一次闭合,应采用措施消除抖动。本文采用的是独立式按键,直接用I/O 口线构成单个按键电路,每个按键占用一条I/O 口线,每个按键的工作状态不会产生互相影响。电路图如下: P1.0口表示功能移位键,按键选择要调整的时十位、时个位、分十位或分个位。 P1.1口表示数字“ +“键,按一下则对应的数字加1。 P1.2口表示数字“ - ”键,按一下则对应的数字减1。 P1.3口表示时间表的切换,程序
10、默认为日常时间表,当按下该开关,使输入为低电平时,表示当前执行的是考试时间表,并有绿发光二极管显示。再按键,使键抬起,输入维高电平时,表示当前执行的是日常作息时间表,用红发光二级管显示。6、温度采集部分此部分选用 DS18B20 传感器,主要由四部分组成:64 位ROM 、温度传感器、非挥发的温度报警触发器TH 和TL、配置寄存器。有三个管脚:DQ 为数字信号输入/ 输出端; GND 为电源地; VDD 为外接供电电源输入端。电源有两种接法:1)远端因入;2)寄生电源方式。它是支持“一线总线”接口的温度传感器,测量温度范围为 - 55C+125 C,在 - 10+85C范围内,可编程为9 位
11、12 位A/D 转换精度,工作电压在3V5V 之间。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。#软件设计:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 5 页,共 11 页个人资料整理仅限学习使用#include #include /#include LCD1602.h /#include DS1302.h #define uint unsigned int #define uchar unsigned char sbit DS1302_CLK = P17 。 /实时时钟时钟线引脚sbit DS1302_IO = P16
12、 。 /实时时钟数据线引脚sbit DS1302_RST = P15。 /实时时钟复位线引脚sbit wireless_1 = P30。sbit wireless_2 = P31。sbit wireless_3 = P32。sbit wireless_4 = P33。sbit ACC0 = ACC0 。sbit ACC7 = ACC7 。char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year。 /秒,分,时到日 ,月,年位闪的计数sbit Set = P20。 /模式切换键sbit Up = P21。 /
13、加法按钮sbit Down = P22 。 /减法按钮sbit out = P23。 /立刻跳出调整模式按钮sbit DQ = P10 。 /温度传送数据 IO口char done,count,temp,flag,up_flag,down_flag 。uchar temp_value。 /温度值uchar TempBuffer5,week_value2 。void show_time( 。 /液晶显示程序/*1602液晶显示部分子程序*/ /Port Definitions*sbit LcdRs = P25。sbit LcdRw = P26。sbit LcdEn = P27。sfr DBPor
14、t = 0x80。/P0=0x80,P1=0x90,P2=0xA0,P3=0xB0. 数据端口/内部等待函数 *unsigned char LCD_Wait(void LcdRs=0。LcdRw=1 。_nop_(。LcdEn=1。_nop_(。LcdEn=0。return DBPort。 /向LCD 写入命令或数据 *#define LCD_COMMAND 0 / Command #define LCD_DATA 1 / Data #define LCD_CLEAR_SCREEN 0x01 / 清屏#define LCD_HOMING 0x02 / 光标返回原点void LCD_Write(
15、bit style, unsigned char input LcdEn=0。LcdRs=style。LcdRw=0 。_nop_(。DBPort=input 。_nop_(。/注意顺序LcdEn=1。_nop_(。/注意顺序LcdEn=0。_nop_(。LCD_Wait( 。 /设置显示模式 *#define LCD_SHOW 0x04 /显示开#define LCD_HIDE 0x00 /显示关#define LCD_CURSOR 0x02 /显示光标#define LCD_NO_CURSOR 0x00 /无光标#define LCD_FLASH 0x01 /光标闪动#define LCD
16、_NO_FLASH 0x00 /光标不闪动void LCD_SetDisplay(unsigned char DisplayMode LCD_Write(LCD_COMMAND, 0x08|DisplayMode。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 6 页,共 11 页个人资料整理仅限学习使用 /设置输入模式 *#define LCD_AC_UP 0x02 #define LCD_AC_DOWN 0x00 / default #define LCD_MOVE 0x01 / 画面可平移#define LCD_NO_MOVE 0x00 /d
17、efault void LCD_SetInput(unsigned char InputMode LCD_Write(LCD_COMMAND, 0x04|InputMode。 /初始化 LCD*void LCD_Initial( LcdEn=0。LCD_Write(LCD_COMMAND,0x38。 /8位数据端口 ,2行显示 ,5*7点阵LCD_Write(LCD_COMMAND,0x38。LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR。 /开启显示 , 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN。 /清屏LCD_SetIn
18、put(LCD_AC_UP|LCD_NO_MOVE。 /AC递增 , 画面不动 /液晶字符输入的位置* void GotoXY(unsigned char x, unsigned char y if(y=0 LCD_Write(LCD_COMMAND,0x80|x。if(y=1 LCD_Write(LCD_COMMAND,0x80|(x-0x40。 /将字符输出到液晶显示void Print(unsigned char *str while(*str!=0 LCD_Write(LCD_DATA,*str。str+。 /*DS1302时钟部分子程序*/ typedef struct _SYSTE
19、MTIME_ unsigned char Second 。unsigned char Minute。unsigned char Hour。unsigned char Week。unsigned char Day。unsigned char Month。unsigned char Year。unsigned char DateString11。unsigned char TimeString9 。SYSTEMTIME 。 /定义的时间类型SYSTEMTIME CurrentTime 。#define AM(X X #define PM(X (X+12 / 转成 24小时制#define DS13
20、02_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 精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 7 页,共 11 页个人资料整理仅限学习使用void DS1302InputByte(unsigned char d /实时时钟写入一字节(
21、内部函数 unsigned char i。 ACC = d。 for(i=8 。 i0。 i- DS1302_IO = ACC0 。/相当于汇编中的 RRC DS1302_CLK = 1 。 DS1302_CLK = 0 。 ACC = ACC 1 。 unsigned char DS1302OutputByte(void /实时时钟读取一字节(内部函数 unsigned char i。 for(i=8 。 i0。 i- ACC = ACC 1 。/相当于汇编中的 RRC ACC7 = DS1302_IO 。 DS1302_CLK = 1 。 DS1302_CLK = 0 。 return(A
22、CC 。 void Write1302(unsigned char ucAddr, unsigned char ucDa /ucAddr: DS1302 地址 , ucData: 要写的数据 DS1302_RST = 0。/ Write1302(0x8e,0x00 。 DS1302_CLK = 0 。 DS1302_RST = 1。 DS1302InputByte(ucAddr 。/ 地址,命令 DS1302InputByte(ucDa 。/ 写1Byte数据 DS1302_CLK = 1 。 DS1302_RST = 0。 unsigned char Read1302(unsigned ch
23、ar 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_GetTime(SYSTEMTIME *Time /获取时钟芯片的时钟数据到自定义的结构型数组 unsigned char Re
24、adValue。ReadValue = Read1302(DS1302_SECOND。Time-Second = (ReadValue&0x704*10 + (ReadValue&0x0F。 /高三位取出读出乘ReadValue = Read1302(DS1302_MINUTE 。Time-Minute = (ReadValue&0x704*10 + (ReadValue&0x0F。ReadValue = Read1302(DS1302_HOUR。Time-Hour = (ReadValue&0x704*10 + (ReadValue&0x0F。ReadValue = Read1302(DS1
25、302_DAY。Time-Day = (ReadValue&0x704*10 + (ReadValue&0x0F。ReadValue = Read1302(DS1302_WEEK。Time-Week = (ReadValue&0x704*10 + (ReadValue&0x0F。ReadValue = Read1302(DS1302_MONTH 。Time-Month = (ReadValue&0x704*10 + (ReadValue&0x0F。ReadValue = Read1302(DS1302_YEAR。Time-Year = (ReadValue&0x704*10 + (ReadVa
26、lue&0x0F。 void DateToStr(SYSTEMTIME *Time /将时间年 ,月,日,星期数据转换成液晶显示字符串,放到数组里 DateString 精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 8 页,共 11 页个人资料整理仅限学习使用if(hide_year / 这里的 if,else语句都是判断位闪烁,2就不显示 ,输出字符串为 2007/07/22 Time-DateString0 = 2 。 Time-DateString1 = 0 。 Time-DateString2 = Time-Year/10 + 0 。 T
27、ime-DateString3 = Time-Year%10 + 0 。 else Time-DateString0 = 。 Time-DateString1 = 。 Time-DateString2 = 。 Time-DateString3 = 。 Time-DateString4 = / 。if(hide_month Time-DateString5 = Time-Month/10 + 0。 Time-DateString6 = Time-Month%10 + 0。 else Time-DateString5 = 。 Time-DateString6 = 。 Time-DateString
28、7 = / 。if(hide_day Time-DateString8 = Time-Day/10 + 0 。 Time-DateString9 = Time-Day%10 + 0 。 else Time-DateString8 = 。 Time-DateString9 = 。 if(hide_week week_value0 = Time-Week%10 + 0。/星期的数据另外放到week_value数组里 ,跟年 ,月,日的分开存放 ,因为等一下要在最后显示 else week_value0 = 。 week_value1 = 0 。精选学习资料 - - - - - - - - - 名师
29、归纳总结 - - - - - - -第 9 页,共 11 页个人资料整理仅限学习使用Time-DateString10 = 0 。 /字符串末尾加 0 ,判断结束字符 void TimeToStr(SYSTEMTIME *Time /将时 ,分,秒数据转换成液晶显示字符放到数组 TimeString 。 if(hide_hour Time-TimeString0 = Time-Hour/10 + 0。 Time-TimeString1 = Time-Hour%10 + 0。 else Time-TimeString0 = 。 Time-TimeString1 = 。 Time-TimeStri
30、ng2 = : 。 if(hide_min Time-TimeString3 = Time-Minute/10 + 0。 Time-TimeString4 = Time-Minute%10 + 0。 else Time-TimeString3 = 。 Time-TimeString4 = 。 Time-TimeString5 = : 。 if(hide_sec Time-TimeString6 = Time-Second/10 + 0 。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 10 页,共 11 页个人资料整理仅限学习使用 Time-Tim
31、eString7 = Time-Second%10 + 0 。 else Time-TimeString6 = 。 Time-TimeString7 = 。 Time-DateString8 = 0 。 void Initial_DS1302(void / 时钟芯片初始化 unsigned char Second=Read1302(DS1302_SECOND。if(Second&0x80 /判断时钟芯片是否关闭 Write1302(0x8e,0x00 。 /写入允许Write1302(0x8c,0x07 。 /以下写入初始化时间日期 :07/07/25.星期 : 3. 时间 : 23:59:5
32、5Write1302(0x88,0x07 。Write1302(0x86,0x25 。Write1302(0x8a,0x07 。Write1302(0x84,0x23 。Write1302(0x82,0x59 。Write1302(0x80,0x55 。Write1302(0x8e,0x80 。 /禁止写入 /-/*ds18b20子程序 */ /*ds18b20延迟子函数 while(i- 。 /*ds18b20初始化函数 */ void Init_DS18B20(void unsigned char x=0。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 11 页,共 11 页