电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能。本系统选用DALLAS公司生产的日历时钟芯片DS1302来作为实时时钟芯片,为本系统提供详细的年、月、日、星期和小时、分钟等时间信息。数字万年历采用直观数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有闹钟和时间校准等功能。该电路采用AT89C52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
本系统硬件部分由AT89C52单片机、DS1302时钟芯片、1062液晶显示器、DS18B20温度测量、键盘、蜂鸣器系统等部分构成。软件部分在keil环境下用C51语言编写,包括时间设置、时间显示、定时设置、定时闹钟、温度显示。
没有良好的基础知识和实践经验会受到很大限制,每项功能实现时需要那种硬件,程序该如何编写,算法如何实现等,没有一定的基础就不可能很好的实现。在编写程序过程中发现以现有的相关知识要独自完成编写任务困难重重,在老师和同学的帮助下才完成了程序部分的编写。
在现实我们生活中每个人都可能有自己的时钟,光阴在永不停息的流逝,有了时钟人们就能随着时间有计划的过着每一天。然而现在绝大部分的时钟有的需要不断地跟换电池,有些时钟需要外接电源,如果一旦电池没电或者外接电源无法供电,时钟就会停止计时了。而美国DALLAS 公司的新型时钟日历芯片DS1302就能解决这一问题。该器件能提供实时时钟(RTC)/日历、定时闹钟。少于31天的月份,月末日期可自动调整,其中包括闰年补偿。该器件还可以工作于24小时货代/PM指示的12小时格式。一个精密的温度补偿电路用来监视Vcc的状态。
本时钟还具有环保、走时无噪音、低功耗等非实时时钟不具有的功能。该实时时钟不但可以作为家用,而且更可以在公共场合使用,如车站、码头、商场等场所。
§1.2论文主要研究内容
本文是以实时时钟芯片DS1302和AT89C52单片机为主要研究对象,着重进行51单片机控制系统的设计研究和如何读取DS1302内部时钟信息的研究。以及运用18B20进行实时温度检测。主要内容包括:
- 实时温度显示;
- 年月日星期时分秒显示;
- 年月日星期时分秒调整;
- 闹钟定时小时分钟和秒;
采用AT89C52作为主控单片机,时钟模块选用DS1302作为时钟芯片,温度模块选用DS18B20作为温度传感器,显示模块选用LCD1602,设置部分选用按键电路。
AT89C52与MCS-51单片机产品兼容 、8K字节在系统可编程Flash存储器、 1000次擦写周期、 全静态操作:0Hz~33Hz 、 三级加密程序存储器 、 32个可编程I/O口线 、三个16位定时器/计数器 八个中断源 、全双工UART串行通道、 低功耗空闲和掉电模式 、掉电后中断可唤醒 、看门狗定时器 、双数据指针 、掉电标识符 。
DS1302 实时时钟芯片功能丰富,可以用来直接代替IBM PC 上的时钟日历芯片DS12887,同时,它的管脚也和MC146818B、DS12887 相兼容。由于DS1302 能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部又增加了世纪寄存器,从而利用硬件电路解决子“千年”问题;DS1302 中自带有锂电池,外部掉电时,其内部时间信息还能够保持10 年之久;对于一天内的时间记录,有12 小时制和24 小时制两种模式。用户还可对DS1302 进行编程以实现多种方波输出,并可对其内部的三路中断通过软件进行屏蔽。
DS18B20可组网数字温度传感器芯片封装而成,具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。可编程的分辨率为9~12位 温度转换为12位数字格式最大值为750毫秒 用户可定义的非易失性温度报警设置。DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。采用一线通信接口。
该系统的系统框图如图1.1示:
图1-1系统框图
第二章 硬件电路设计
§2.1单片机最小系统
本系统以AT89C52单片机为核心,本系统选用11.0592MHZ的晶振,,使得单片机有合理的运行速度。起振电容30pF对振荡器的频率高低、振荡器的稳定性和起振的快速性影响较合适,复位电路为按键高电平复位。
AT89C52单片机最小系统电路设计如图2.1所示。
图2-1 单片机最小系统
§2.2时钟芯片电路
- 时钟芯片DS1302,其引脚分布图如下所示
图2-2时钟引脚分布
MOT (1脚) :总线时序模式选择脚。接高电平,选择MOTOROLA总线时;序;接低电平或悬空,择选择INTEL总线时序。
NC (2,3,16,20,21,22脚):悬空脚。
AD0~AD7(4~11脚):地址/地址数据复用总线引脚。
CS(13脚):片选脚,低电平有效。
AS(14脚):地址锁存输入脚。下降沿时,地址被锁存,紧接着的上升沿来时地址被清除。
R/W(15脚):读/写输入脚。在选择MOTOROLA总线时序模式时,此引脚用于指示当前的读写周期,高电平指示当前为读周期,低电平指示当前为写周期;选择INTEL中线时序模式时,此引脚为低电平有效的输入脚,相当于通用RAM的写使能信号(/WE)
DS(17脚):选择MOTOROLA总线时序模式时,此引脚为数据锁存脚;选择INTEL总线时序模式时,此引脚为读输入脚,低电平有效,相当于典型的内存的输出使能信号(/OE)
RESET(18脚):复位脚,低电平有效,复位不会影响到时钟、日历和RAM。
IRQ(19脚):中断申请输出脚,低电平有效,可作为微处理器的中断输入。
SQW(23脚):方波信号输出脚。可通过设置寄存器位SQWE关断此信号输出,此信号的输出频率也可通过对芯片内部的寄存器编程予以改变。
VCC(24脚):+5v电源端。
图2-3 时钟、日历和闹钟数据模式——BCD模式(DM=0)
图2-4 时钟、日历和闹钟数据模式——二进制模式(DM=1)
2.2.3 4个控制寄存器介绍
DS1302有4个控制寄存器,在任何时间都可以进行访问,即使处于更新周期。
寄存器A字节的内容如下。
MSB LSB
UIP | DV2 | DV1 | DV0 | RS3 | RS2 | RS1 | RS0 |
UIP: 更新标志位。为只读位且不受复位操作的影响,为1时,表示即将发生的数据更新;为0时,表示至少244US不会更新数据。当UIP为0时,可以获得所有时钟、日历、闹钟信息。将寄存器B中的SET位置1可以限制任何数据更新操作,并且清除UIP位。
DV2、DV1、DV0:此3位为010时将打开晶振,并开始计时。RES3、RES2、RES1、RES0:用于设置周期性中断产生的时间周期和输出方波的频率。
寄存器B字节的内容如下。
MSB LSB
SET | PIE | AIE | UIE | SQWE | DM | 24/12 | DSE |
SET:设置位,可读写,不受复位操作影响。为0时,不处于设置状态,芯片进行正常时间数据更新;为1时,抑制数据更新,可以通过程序设定时间和日历信息。
PIE:周期性中断使能位,可读写,复位时清除此位。为1时,允许寄存器C中的周期中断标志位PF,驱动/IRQ引脚为低产生中断信号输出,中断信号产生的周期由RS3~RE0决定。
AIE:闹钟中断使能位,可读写。为1时,允许寄存器C中的闹钟中断标志位AF、闹钟发生时就会通过/IRQ引脚产生中断输出。
UIE:数据更新结束中断使能位,可读写。复位或者SET位为1时清除此位。为1时允许寄存器C中的更新结束标志UF,更新结束时就会通过/IRQ引脚产生中断输出。
SQWE:方波使能位,可读写,复位时清除此位。为0时,SQW引脚保持低电平;为1时,SQW引脚输出方波信号,其频率由RS3~RS0决定。
DM:数据模式位,可读写,不受复位操作影响。为0时,设置时间、日历信息为二进制数据;为1时,设置为BCD码数据。
24/12:时间模式设置为,可读写,不受复位操作影响。为0时,设置为12小时模式;为1时,设置为24小时模式。
DSE:为1时,会引起两次特殊的时间更新;4月的第一个星期日凌晨1:59:59会直接更新到3:00:00,10月的最后一个星期日凌晨1:59:59会直接更新到1:00:00;为0时,时间信息正常更新,此位可读写,不受复位操作影响。
寄存器C字节内容如下。
MSB LSB
IRQF | PF | AF | UF | 0 | 0 | 0 | 0 |
IQRF:中断申请标志位。为1时,/IRQ引脚为低,产生中断申请。当PF、PIE为1时或者AF、ATE为1或者UF、UIE为1时,此位为1,否则置0.
PF:中期中断标志位。为1时,它是只读位,和PIE位状态无关,由复位操作或者寄存器C操作清除。
AF:闹钟中断标志位。为1时,表示当前时间和闹钟设定时间一至,由复位操作或读寄存器C操作清除。
UF:数据更新结束中断标志位。每个更新周期后此位都会置1,当UIE位位置1时,UF若为1就会引起IRQF置1,将驱动/IRQ引脚为低电平,申请中断。此位由复位操作或读寄存器C操作清除。
寄存器D字节的内容如下。
MSB LSB
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
VRT;RAM和时间有效位。用于指示和VBAT引脚连接的电池状态。此位不可写,也不受操作为影响,正常情况下读取时总去为1,如果出现读取为0的情况,则表示电池耗尽,时间数据和RAM中的数据就会出现问题。
芯片DS12CR887的113字节普通RAM空间为非易失性RAM空间,他不专门用于某些特别功能,而是可以在未处理器程序中作为非易失性内存空间使用。
§2.4温度采集电路设计
适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电。
②独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。
③DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温④DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内。
⑤温范围-55℃~+125℃,在-10~+85℃时精度为0.5℃。
⑥可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温。
⑦在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快。
⑧测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力。
⑨负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
DS1820的操作指令分为ROM操作命令和存储器操作命令。
(1)、ROM操作命令及其含义
Read ROM指令代码(33h):如果只有一片DS1820,可用此命令读出其序列号,若在线DS1820多于一个,将发生冲突。
Match ROM指令代码(55h):多个DS1820在线时,可用此命令匹配一个给定序列号的DS1820,此后的命令就针对该DS1820。
Skip ROM指令代码(CCh):此命令执行后的存储器操作将针对在线的所有DS1820。
Search ROM指令代码(F0h):用以读出在线的DS1820的序列号。
Alarm Search指令代码(ECh):当温度值高于TH或低于TL中的数值时,此命令可以读出报警的DS1820。
(2)、存储器操作指令代码及其含义
Write Scratchpad指令代码(4Eh):写两个字节的数据到温度寄存器。
Read Scratchpad指令代码(BEh):读取温度寄存器的温度值。
Copy Scratchpad指令代码(48h):将温度寄存器的数值拷贝到EERAM中,保证温度值不丢失。
Convert T指令代码(44h):启动在线DS1280做温度A/D转换。
Recall E2指令代码(B8h):将EERAM中的数值拷贝到温度寄存器中。
Read Power Supply指令代码(B4h):在本命令送到DS1280之后的每一个读数据间隙,指出电源模式:“0”为寄生电源;“1”为外部电源。
(1).Read ROM(33 h),每次对DS1820进行操作之前都要对它进行初始化,主要目的在于确定传感器已经连接到单总线上。
(2).Search ROM(F0h),这条指令使处理器用排除的方法去辨别总线上的DS1820。
(3).Match ROM(55h),只有准确的符合64位ROM序列的DS1820才能响应其后的指令,当然,单点测温时可以使用Skip ROM(CCh)指令来跳过这一步。
(4).Convert T(44h),发完指令后应查询总线上的电平,当电平位高时温度转换完成。
(5).Read Scratchpad(BEh),将读指令发出后,就可从总线上读得表示温度的2字节二进制数。
由于采用单总线数据传输方式,DS18B20的数据I/O均由同一条线完成,因此,对读写的操作时序要求严格。它的各种时序如图2-5所示
图2-5 DS18B20的操作时序
为了保证DS18B20的严格I/O时序。需要做较精确的延时。在DS18B20操作中,用到的延时有15μS,90μS,270μS,540μS等。因这些延时均为15μS的整倍,因此在程序中可以编写一个以15μS为基准的延时函数。
图2-6温度采集电路
§2.5 1602LCD液晶显示屏
字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,本设计采用16列*2行的字符型LCD1602带背光的液晶显示屏。
1602LCD主要技术参数:
- 显示容量:16×2个字符
- 芯片工作电压:4.5—5.5V
- 工作电流:2.0mA(5.0V)
- 模块最佳工作电压:5.0V
- 字符尺寸:2.95×4.35(W×H)mm
各引脚接口说明如表所示:
表2-1
编号 | 符号 | 引脚说明 | 编号 | 符号 | 引脚说明 |
1 | VSS | 电源地 | 9 | D2 | 数据 |
2 | VDD | 电源正极 | 10 | D3 | 数据 |
3 | VL | 液晶显示偏压 | 11 | D4 | 数据 |
4 | RS | 数据/命令选择 | 12 | D5 | 数据 |
5 | R/W | 读/写选择 | 13 | D6 | 数据 |
6 | E | 使能信号 | 14 | D7 | 数据 |
7 | D0 | 数据 | 15 | BLA | 背光源正极 |
8 | D1 | 数据 | 16 | BLK | 背光源负极 |
表2-1:引脚接口说明:
第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脚:背光源负极。
1602液晶模块内部的控制器共有11条控制指令,如表2-2所示:
表2-2
序号 | 指令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
1 | 清显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 光标返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * |
3 | 置输入模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S |
4 | 显示开/关控制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
5 | 光标或字符移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * |
6 | 置功能 | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * |
7 | 置字符发生存贮器地址 | 0 | 0 | 0 | 1 | 字符发生存贮器地址 | |||||
8 | 置数据存贮器地址 | 0 | 0 | 1 | 显示数据存贮器地址 | ||||||
9 | 读忙标志或地址 | 0 | 1 | BF | 计数器地址 | ||||||
10 | 写数到CGRAM或DDRAM) | 1 | 0 | 要写的数据内容 | |||||||
11 | 从CGRAM或DDRAM读数 | 1 | 1 | 读出的数据内容 |
表2-2字符控制命令说明:
1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明: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:读数据。
芯片时序表如下:
读状态 | 输入 | RS=L,R/W=H,E=H | 输出 | D0—D7=状态字 |
写指令 | 输入 | RS=L,R/W=L,D0—D7=指令码,E=高脉冲 | 输出 | 无 |
读数据 | 输入 | RS=H,R/W=H,E=H | 输出 | D0—D7=数据 |
写数据 | 输入 | RS=H,R/W=L,D0—D7=数据,E=高脉冲 | 输出 | 无 |
表2-3
基本操作时序表
读写操作时序如图2-7和2-8所示:
图2-7读操作时序
图2-8 写操作时序
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图2-9是1602的内部显示地址。
图2-9液晶内部显示地址
例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图10-58所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
图2-10 字符代码与图形对应图
- 延时15mS
- 写指令38H(不检测忙信号)
- 延时5mS
- 写指令38H(不检测忙信号)
- 延时5mS
- 写指令38H(不检测忙信号)以后每次写指令、读/写数据操作均需要检测忙信号
- 写指令38H:显示模式设置
- 写指令08H:显示关闭
- 写指令01H:显示清屏
- 写指令06H:显示光标移动设置
- 写指令0CH:显示开及光标设置
液晶5端为读/写选择端,因为我们不从液晶中读取数据,只向其写入命令和显示数据,因此此端始终选择为写状态,即低电平接地。液晶6端为使能信号,是操作时必须的信号。其电路如图2-11所示:
图2-11 1602的电路连接
§2.6 蜂鸣器闹铃电路
当单片机给蜂鸣器一个低电平时,三极管导通驱动蜂鸣器发出声音作为定时闹铃,其电路图如图2-12所示:
图2-12 蜂鸣器连接电路
§2.7 按键调整电路
系统四个独立键盘均采用查询方式,S2用于设置年、月、日、时、分、秒、星期的数值加,以及闹钟开,S3用于设置年、月、日、时、分、秒、星期的数值减以及闹钟关,s1用于具体设置时钟位的切换,s4键用于设置闹钟。其电路图如2-13所示:
图2-13 按键电路连接
电子钟的电源为5伏直流电源,本设计中我使用的是5V的充电模块,电源模块的原理图如图2-15所示:
图2-14电源模块
第三章 软件部分设计
本系统主要包括五个模块编程:
- 蜂鸣器闹铃响编程
- 时钟芯片12C887的编
- 液晶显示屏1602的编程
- 按键编程
- DS18B20温度采集编程
§3.1 主程序流程
主程序开始初始化,并打开中断,然后执行扫描闹钟、键盘及读取18B20值。当有S1键按下时,执行时钟设置,当有S4键按下时,则进入闹钟设置,无论是时钟还是闹钟,设置完后退出,温度、时钟恢复实时显示。主程序流程图如图3-1所示:
初始化开中断 |
读18b20 |
S1或S2是否按下 |
扫描闹钟 |
显示温度 |
设置闹钟 |
显示温度 |
设置时间 |
图3-1主程序流程图
§3.2 时间设置子程序流程
通过单片机判断S1按下的次数来设置,由s1num标志位来记录次数,用if语句判断执行命令。系统程序不断扫面键盘,当s1键按下后产生一个低电平,即s1num加一。在调节时间之前首先进行各个变量初始化,及设置起始时间,同时为读取数据作准备。当s1=1时进入秒的设置,地址指针指向miao显示位置处,通过两个if语句分别循环控制显示秒数的加和减。当s1=2时,地址指针指向fen显示位置处,变量最大值为59。当s1=3时,地址指针指向shi显示位置处,变量最大值设为23。当s1=4时,地址指针指向week显示位置处,最大值设为7,1至7分别用MON、TUE、WED、THU 、FRI、SAT、SUN字符串显示。随着s2、s3值的的变化显示不同的字符串。当s1=5时,地址指针指向day显示位置,变量最大值为31。当s1=6时,地址指针指向month显示位置,变量最大值为12。
当s1=7时,地址指针指向year显示位置,最大值为99。
S1=1秒 |
S1=2分 |
S1=7月 |
S1=8退出 |
S2调加秒 |
S3调减秒 |
S3调减年 |
S2调加年 |
S1=1秒 |
S1=2分 |
S1=7月 |
S1=8退出 |
S2调加秒 |
S3调减秒 |
S3调减年 |
S2调加年 |
S1=1秒 |
S1=2分 |
S1=7月 |
S1=8退出 |
S2调加秒 |
S3调减秒 |
S3调减年 |
S2调加年 |
S1=1秒 |
S1=2分 |
S1=7月 |
S1=8退出 |
S2调加秒 |
S3调减秒 |
S3调减年 |
S2调加年 |
图3-2时间设置流程图
§3.3 闹钟设置子程序流程
时间设置程序流程图如图3-3所示。在开始时间设置之前程序会关闭全局中断,直至设置结束,中断又会重新开启,进入计时状态。
闹钟的设置时通过S1键的按下次数来判断的。当单片机检测到S4键按下一次时则进入闹钟设置界面,光标并自动跳到秒设置位置,可以对秒进行设置,当S1键依次按下1、2、3次时,则分别进入闹钟的秒、分、时关的设置。:
S4=1设置闹钟 |
S4=2退出设置 |
S1=1调节秒 |
S1=2调节分 |
S1=3调节时 |
S1=4退出 |
S4=1设置闹钟 |
S4=2退出设置 |
S1=1调节秒 |
S1=2调节分 |
S1=3调节时 |
S1=4退出 |
图3-3 闹钟设置流程图
§3.4 程序设计问题
按键在按下时因为机械原因会产生抖动,抖动的后果就是当按下一次按键时因为抖动的原因让系统读取到多次的按键按下的次数,由此导致设置时出现错误。解决的方法如下:当按键按下时读取按键键值,若5ms后键值和按下是相等,则确认为有效按键,以此消除按键抖动带来的问题。
蜂鸣器报警时,设置响100毫秒,停100毫秒,循环响应,产生滴滴的声音。
初始化设置
显示模式设置
写入指令码write_com(0x38),设置功能16*2显示,5*7点阵,8位数据接口
显示/开关及光标设置
- 写入指令码write_com(0x0c),设置开显示,不显示光标,光标不闪烁。
- 写入指令码write_com(0x06),设置当读或写一个字符后地址指针加一,且光标加一。当写一个字符,整屏显示不移动。
显示清屏,写入指令码write_com(0x01)。
写入指令码函数write_com()写指令过程 :输入:rs=0,D0-D7=指令码,E=高脉冲
写入数据函数 write_date() 写指令过程: 输入:rs=1,D0-D7=数据,E=高脉冲
写入指令和数据时rw端已经接地。
数据指针设置 指令码80H+地址码(0-27H)显示第一行的字符
指令码80H+地址码(40H-67H)显示的第二行字符
EA=1;//打开总中断
EX1=1;//打开外部中断
IT1=1;//设置负跳变沿触发中断
当闹钟到点时响应外部中1 时间到时IRQ端从高阻态转为低电平,此时读一次c寄存器清除IRQ端的输出,等待下一次定时。
void exter() interrupt 2 //外部中断1服务程序
{
uchar c;//进入中断表示闹钟时间到
flag_ri=1; //设置标志位,用以大程序中报警
c=read_ds(0x0c);//读取12c887c寄存器表示响应了中端
}
首次上电初始化时间函数:
void set_time()
{//首次上电初始化时间函数
write_ds(0,0);//初始化秒
write_ds(1,0);//初始化秒闹钟
write_ds(2,0);// 初始化分
write_ds(3,0);//初始化分闹钟
write_ds(4,0);//初始化时
write_ds(5,0);// 初始化时闹钟
write_ds(6,0);//初始化星期
write_ds(7,0);// 初始化日
write_ds(8,0);//初始化月
write_ds(9,0);// 初始化年
}
写12C887函数:
void write_ds(uchar add,uchar date)
{ //写12C887函数
dscs=0; 打开片选信号
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0; //下降沿锁存地址
dsrw=0;
P0=date;
dsrw=1;//上升沿锁存数据
dsas=1;//上升沿清除地址
dscs=1; //关掉片选信号
}
图3-5 写时序图
读12C887函数:
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;打开片选信号
P0=add;
dsas=0; //下降沿锁存地址
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1; //下降沿锁存地址
dsas=1;//上升沿清除地址
dscs=1;//关掉片选信号
return ds_date;
}
图3-6 读时序图