




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PAGEII基于单片机的数字时钟的硬件结构及软件系统设计摘要电子日历是一种非常常见的日常计时工具,在当今社会中越来越重要。电子日历的硬件主要采用AT89C51作为主控核心,DS1302时钟芯片提供时钟和LCD1602液晶显示器。AT89C51单片机由STC公司生产,功耗低,电压可达4~6V;DS1302时钟芯片是美国达拉斯公司生产的低功耗实时时钟芯片,可实现年、月、日、周、时、分、秒计时,并具有闰年补偿等多项功能。此外,DS1302应用寿命长,误差小。它适用于数字电子日历取直观的数字显示,数字显示是取LCD1602液晶显示器来显示,可以同时显示年、月、日、周、时、分、秒等信息。此外,电子日历还具有时间校准功能。软件方面,主要包括日通程序、时间调整程序、显示程序等,所有程序编写完成后,在keil软件中进行调试。在没有问题之后,它们被烧录到MCU进行测试。本设计主要由时钟芯片DS1302和温度传感器DS18B20采集数据到单片机进行处理,然后通过LCD1602显示,本文主要讨论了液晶显示器LCD1602与时钟芯片DS1302、温度传感器DS18B20与单片机的硬件互联和通信,给出了几种硬件连接方案在日历计算的软件方面,对该方法进行了详细的比较。【关键词】AT89C51LCD1602DS18B20DS1302按键目录11486前言 121075第一章工作原理 2237061.1设计目标 2314251.1.1基本功能 28838第二章硬件设计与原理 3145852.1总设计框图 3202382.2硬件设计分析 3144542.2.1电源的设计 344682.2.2单片机最小系统 4159402.2.3显示系统 10271722.2.4LCD1602的指令说明及时序 126442.2.5LCD1602的RAM地址映射及标准字库表 1432202.2.6DS1302原理及说明 16161972.2.7DS18B20工作原理及说明 1954422.2.8按键电路 2026381第三章软件设计与分析 22236973.1软件设计的组成 22186313.2源程序 2613711第四章软件仿真 56214844.1PROTEUS简介 5681714.2仿真图 5818214.3原理图 59283274.4元件清单 6025374参考文献 64前言近年来,随着通道技术的飞速发展,单片机领域不断走向社会的每一个角落,也推动着传统的主控检测技术日新月异。在单片机实时操作和主动控制系统中,单片机是目前应用的核心部件。仅仅掌握单片机的知识是不够的。它还应根据其具体的硬件结构和软件组合,针对应用对象的具体特点加以完善。单片机原理与应用课程设计是电子类专业的一门基础课程。它是继汇编语言程序设计和接口技能课程之后的一门实践性课程。
第一章工作原理1.1设计目标1.1.1基本功能此万年历主要具有:年、月、日、星期、时、分、秒、温度显示。主要功能:1、万年历2、时间3、星期4、温度显示(以上四项内容同时显示)5、四键调时(设置键、上调键、下调键、关音按键)第二章硬件设计与原理以AT89C51单片机为核心,起着控制作用。系统包括LCD1602液晶显示电路、复位电路、时钟电路、按键电路、温度传感器电路、时钟芯片电路。设计思路分为七个模块:复位电路、晶振电路模块、AT89C51、LCD1602液晶显示电路、按键电路、温度传感器电路、时钟芯片电路这七个模块。2.1总设计框图2.2硬件设计分析2.2.1电源的设计系统电源使用直流5伏。由电脑USB接口提供电源。USB是通用串行总线(UniversalSerialBus)接口的简称。它是目前使用比较广泛的电脑接口之一,主要版本有1.0、1.1和最新的2.0三种版本。根据USB总线的工业标准,它可以提供额定功率为5V/500mA的电源供USB设备使用。2.2.2单片机最小系统51单片机是所有与intel8031指令系统兼容的单片机的总称。这一系列单片机的鼻祖是英特尔的8031单片机。后来,随着同一技术的发展,它成为应用广泛的8位单片机之一。MCU是一种大规模集成电路,它将CPU、ram、ROM、定时器/计数器、多功能I/O口等计算机所需的基本功能部件集成在一块芯片中,又称MCU。51系列单片机包括以下几个部分:一个8位CPU;片上振荡器和时钟电路4KBROM程序存储器128BRAM数据存储器控制电路寻址64KB外部数据存储器和64KB外部程序存储器空间32个可编程I/O端口两个16位定时器/计数器一个可编程全双工串行端口五个中止源和两个优先级嵌套中止结构As图2-2-1是AT89C51单片机的基本结构,其基本性能介绍如下:图2-2-1AT89C51单片机AT89C51包含40个引脚、32个外部双向输入/输出(I/O)端口、2个外部和中间端口、3个16位可编程定时计数器和2个全双工串行通信端口。AT89C51可以按常规方法编程,但不能在线编程。它将普通微处理器与flash存储器相结合,特别是可擦除flash存储器,可以有效地降低开发成本。AT89C51的主要特性如下表所示:兼容MCS—51指令系统32个可编程I/O线4k字节可编程闪烁存储器可编程UARL通道三个16位可编程定时/计数器中断时钟频率0-24MHz2个外部中断源,共8个中断源256×8bit内部RAM2个读写中断口线可直接驱动LED软件设置睡眠和唤醒功能低功耗空闲和掉电模式表2-2-1AT89C51主要功能描述AT89C51是一种8位通用微处理器,采用40针双列直插式封装。采用工业级C51核,内部功能和引脚布局与通用型8xc52相似。主要用于掌握收敛调整功能。主要功能包括会聚主芯片内部存储器、数据RAM和外部接口的初始化、会聚调整的掌握、会聚测试图的掌握、红外遥控信号的吸收和解码以及与主板CPU的通信。主要引脚有:xtal1(19引脚)和xtal2(18引脚)是振荡器的输入和输出端口,外置12Mhz晶体振荡器。Rst/VPD(9针)为复位输入端口,复位电路由外电阻和电容组成。VCC(40针)和VSS(20针)是电源端口,分别连接到+5V电源的正极和负极端子。在本设计中,端口P0(32-39针)被定义为N1功能主端口,与N1的相应功能针相连。引脚13被定义为IR输入端口,引脚10和引脚11被定义为I2C总线主端口,与N1的SDAs(18引脚)和SCLS(19引脚)端口相连。27引脚和28引脚被定义为握手信号功能端口,与主板CPU的相应功能端口相连,用于检测电流系统并掌握汇聚调整功能的端口P0:端口P0是一组8位开漏双向I/O端口,即地址/数据总线复用端口。当用作输出端口时,每个TTL逻辑门可以通过吸收电流来驱动。将“1”写入端口P0时,它可用作高阻抗输入。当访问外部数据存储器或程序存储器时,这组端口线分时地址转换(低8位)和数据总线复用在访问期间激活内部上拉电阻。在flash编程中,端口P0吸收指令字节,而在程序验证中,它输出指令字节。在验证中,它请求外部上拉电阻器P1端口:P1是一个带有内部上拉电阻器的8位双向I/O端口。P1的输出缓冲级可以驱动(吸收或输出电流)4个TTL逻辑门。将“1”写入端口,通过内部上拉电阻将端口拉至高电平,即可作为输入端口。当用作输入端口时,由于内部上拉电阻,引脚在被外部信号下拉时将输出电流(IIL)。与AT89C51不同,P1.0和P1.1还可用作定时器/计数器2的外部计数输入(P1.0/T2)和输入(P1.1/t2ex)。在闪存编程和程序验证期间,P1吸收低8位地址P2端口:P2是一个带内部上拉电阻器的8位双向I/O端口。P2的输出缓冲级可以驱动(吸收或输出电流)4个TTL逻辑门。将“1”写入端口P2,并通过内部上拉电阻将端口拉至高电平。此时,它可以用作输入端口。当它被用作输入端口时,由于内部上拉电阻,当它被外部信号拉低时,引脚将输出电流(IIL)。当访问具有16位地址的外部程序存储器或外部数据存储器时(例如,执行MOVX@dptr指令),P2端口发送高8位地址数据。当访问具有8位地址的外部数据存储器(例如执行MOVX@RI指令)时,P2端口输出P2锁存器的内容。在flash编程或验证过程中,P2还吸收高位地址和一些主信号&P3端口:P3端口是一组带有内部上拉电阻的8位双向I/O端口。P3端口的输出缓冲级可以驱动(吸收或输出电流)四个TTL逻辑门。当将“1”写入P3端口时,它们由内部上拉电阻器上拉,可用作输入端口。此时,外部下拉的P3端口将使用上拉电阻器输出电流(IIL)。除了作为一个通用的I/O端口外,P3端口的主要用途是它的第二个功能。P3端口还吸收一些主信号,用于闪存编程和程序验证Rst:复位输入。当振荡器工作时,rst引脚输出超过两个机器周期,并且高电平将重置MCUAle/prog:当访问外部程序存储器或数据存储器时,Ale(地址锁存许可)输出脉冲用于锁存地址的低8位。通常,ale仍以时钟振荡频率的1/6输出一个固定的脉冲信号,因此可以用来输出时钟或定时目标。应当注意,每当访问外部数据存储器时,Al脉冲将被跳过。该引脚还用于在闪存编程期间输入程序脉冲(PROG)。如有必要,可通过在SFR区域设置8eh装置的D0位置来停止ale操作。在此位之后,只有一条MOVX和MOVC指令可以激活ale。此外,销会稍微拉高。当MCU执行外部程序时,ale停止位应设置为无效PSEN:PSEN的输出是外部程序存储器的读出通信号。当AT89C51从外部程序存储器中获取指令(或数据)时,PSEN每机器周期有效两次,即输出两个脉冲。在此期间,当访问外部数据存储器时,PSEN信号将被跳过两次。EA/VPP:外部访问权限。为了使CPU只访问外部程序存储器(地址为0000hffffh),EA终端必须坚持低电平(接地)。应注意,如果加密位Lb1被编程,则在复位期间EAend状态将被内部锁定。如果EA端是高电平(连接到VCC端),CPU执行内部程序存储器中的指令。闪存编程时,引脚加上+12V编程许可电源VPP,当然这一定是12V编程电压VPP的应用器件。Xtal1:振荡器反相放大器和内部时钟发生器的输入。Xtal2:振荡器反相放大器输出。单片机最小原理图如图2-2-2所示。图2-2-2单片机最小系统单片机最小系统说明:时钟信号产生:MCS-51芯片中有一个高增益逆变放大器,输入为xtal1,输出为xtal2。在芯片外部,xtal1和xtal2与晶体振荡器和微调电容器连接,形成稳定的自激振荡器,它是单片机的时钟振荡电路,时钟电路的振荡脉冲经触发器分频后成为单片机的时钟脉冲信号,一般电容C2和C3约为30pf,晶体的振荡频率为1.2-12mhz。如果晶体振荡频率高,系统的时钟频率也高,单片机的运行速度也快,单片机复位使系统中的CPU等功能部件处于一定的初始状态,并从该状态开始工作。MCU复位条件:必须使9针加上连续两个机器周期(即24个振荡周期)的高电平。2.2.3显示系统LCD1602分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图2-2-3所示:图图2-2-3LCD1602尺寸图LCD1602重要技术参数:1,显示容量:16×2字符2,芯片工作电压:4.5-5.5v3,工作电流:2.0ma(5.0V4,模块最佳工作电压:5.0V5,字符大小:2.95×4.35(W×H)Mm引脚功能说明LCD1602采用14引脚(无背光)或16引脚(带背光)接口。各引脚接口说明如图2-2-4所示:编号符号引脚说明编号符号引脚说明1VSS电源地9D2数据2VDD电源正极10D3数据3VL液晶显示偏压11D4数据4RS数据/命令选择12D5数据5R/W读/写选择13D6数据6E使能信号14D7数据7D0数据15BLA背光源正极8D1数据16BLK背光源负极图图2-2-4引脚接口说明图2-2-4:引脚接口说明表引脚1:VSS是地面电源。引脚2:VDD连接到5V正极电源。第三个引脚:VL是LCD比较调整终端。接正电源时比较度最弱,接地时比较度最高。当它太高的时候,鬼魂就会出现。使用时,可通过10k电位器调节比较度。引脚4:RS是存储设备、高级数据存储设备和低级指令存储设备的选择。引脚5:R/W是读/写信号线,用于高电平的读操作和低电平的写操作。当RS和R/W都处于低电平时,它们可以写指令或显示地址;当RS处于低电平时,R/W处于高电平时,可以读出忙信号;当RS处于高电平时,R/W处于低电平时,它们可以写入数据。引脚6:e端子是启用端子。当e终端从高电平跳到低电平时,LCD模块执行命令。引脚7-14:d0-d7是8位双向数据线。引脚15:背光阴极。引脚16:背光阴极。2.2.4LCD1602的指令说明及时序1602液晶模块内部的控制器共有11条控制指令,如图2-2-5所示:序号指令RSR/WD7D6D5D4D3D2D1D01清显示00000000012光标返回000000001*3置输入模式00000001I/DS4显示开/关控制0000001DCB5光标或字符移位000001S/CR/L**6置功能00001DLNF**7置字符发生存贮器地址0001字符发生存贮器地址8置数据存贮器地址001显示数据存贮器地址9读忙标志或地址01BF计数器地址10写数到CGRAM或DDRAM)10要写的数据内容11从CGRAM或DDRAM读数11读出的数据内容图图2-2-5控制命令表通过指令编程完成1602液晶显示模块的读写操作、屏幕操作和光标操作。(说明:1为高电平,0为低电平)指令1:清除显示,指令代码01h,光标复位到地址00h位置命令2:复位光标并将光标返回到地址00h命令3:光标和显示模式设置I/D:光标移动方向,高电平向右移动,低电平向左移动s:是否所有文本在屏幕上向左或向右移动。高电平有效,低电平无效命令4:显示开关主控。D:掌握整体显示的开与关,高电平显示的开与关,低电平显示的关显示C:掌握光标的开与关,高电平显示有光标,低电平显示无光标B:掌握光标是否发光,高电平显示,无光标低位显示Command5:光标或显示移位s/C:高位移动显示文字,低位移动光标Command6:功能设置命令DL:高位4位总线,低位8位总线n:低位单行显示,高位双线显示F:低位5x7点阵字符,5x10高位点阵字符Instruction7:字符发生器RAM地址设置Instruction8:DDRAM地址设置Instruction9:读取忙信号和光标地址BF:忙标志位,高位表示忙,此时模块无法吸收命令或数据,如果是低位,则表示不忙Instruction10:写入数据说明11:读取数据。2.2.5LCD1602的RAM地址映射及标准字库表图2-2-6图2-2-6LCD1602内部显示地址例如,如果第二行第一个字符的地址是40H,您是否可以直接写入40H以将光标定位在第二行第一个字符上?这是不可能的,因为在写入显示地址时,请求的最高位D7总是高电平1,因此实际写入的数据应该是01000000B(40H)+10000000B(80h)=11000000B(C0H)。在初始化液晶显示模块时,首先要设置显示模式,液晶显示模块中显示的字符的时标主动向右移动,不需要人工干预。每次输入前确定LCD模块是否忙。1602液晶显示模块中的字符生成存储器(cgrom)存储了160种不同的点阵字符图形。这些字符包括阿拉伯数字、英文字母的大小写、常用符号和日语假名。每个字符都有一个固定的代码。例如,大写英文字母“a”的代码为01000001b(41h)。模块显示地址41当显示H中的点阵字符图时,我们可以看到字母“a”。图2-2-7液晶显示电路2.2.6DS1302原理及说明(1)时钟芯片DS1302的工作原理:每次读写程序前,必须对DS1302进行初始化。首先,将SCLK端设置为“0”,然后将rst端设置为“1”,最后给出SCLK脉冲。读/写顺序如下图2.2所示。图2.1显示了DS1302的主字。主字的第7位必须设置为1。如果为0,则无法向DS1302读取或写入数据。对于位6,如果ram=1表示程序读/写,CK=0表示时间读/写。位1到5表示操作单元的地址。位0是读/写操作位。当执行读取操作时,位为1;当位为0时,执行写操作。主字节总是从最低位输入/输出。表2.2显示了DS1302的日历和时间存储设备的内容:“ch”是时钟暂停标记位。位为1时,时钟振荡器停止,DS1302处于低功耗状态;位为0时,时钟开始运行。“WP”是写掩码位。在对时钟和ram进行任何写操作之前,WP必须为0。当“WP”为1时,写入掩码位防止写入任何寄存器。(2)DS1302的主字DS1302的主字如图2.1所示。主字节的高有效位(位7)必须是逻辑1。如果为0,则无法将数据写入DS1302。如果位6为0,则可以访问日历时钟数据。如果位1为1,则可以访问RAM数据。位5到1指示操作单元的地址。如果位0为0,则可以执行写操作。如果位1是1,则可以执行读取操作。主字节总是从最低位终端输出打开。图2-2-8DS1302的控制字(3)当指令字输入后的下一个SCLK时钟的上升沿被抓住时,数据被写入DS1302,并且数据输入从低位开始,即位0。类似地,在紧接8位主指令字之后的下一个SCLK脉冲的下边缘处读取DS1302的数据,并且从低位0到高位7读取数据。如图2-2-9所示:图2-2-9DS1302读与写的时序图(3)DS1302寄存器DS1302有12个寄存器,其中7个寄存器与日历和时钟有关。存储的数据位是BCD码。日历、时间寄存器及其主字见表2.2。表2.2DS1302的日历、时间寄存器此外,DS1302还具有年存储、主存储、充电存储、时钟突发存储和ram相关存储。时钟突发存储设备可以一次顺序地读写除充电存储设备之外的存储设备的所有内容。DS1302ram相关存储器可分为两种:一种是单个ram单元,共31个字节,每个单元配置为8位字节,其命令主字为C0H~FDH,奇数为读操作,偶数为写操作;另一种是突发方式下的ram存储器,它可以一次读写全部31字节的RAM,命令主字是FEH(写)和FFH(读)。图2-2-10DS1302电路2.2.7DS18B20工作原理及说明DS18B20的读写时序和测温原理与DS1820相同,只是温度值的位数因分辨率不同而不同,温度转换的延迟时间从2s缩短到750ms,DS18B20测温原理如所示图2-1-10。图中温度系数较低的晶体振荡器的振荡频率受温度影响不大。它用于产生一个固定频率的脉冲信号,并将其发送到计数器1。高温系数晶体振荡器的振荡速率随温度的变化而显著变化,产生的信号作为计数器2的脉冲输入。计数器1和温度存储预设为-55℃对应的基值。计数器1对低温系数晶体振荡器产生的脉冲信号进行减法计数。当计数器1的预置值减为0时,温度存储装置的值将增加1,计数器1的预置值将重新加载。计数器1再次开始对低温系数晶体振荡器产生的脉冲信号进行计数。此循环将停止温度存储装置值的累积,直到计数器2计数为0,此时,温度存储装置中的值为测量温度。图2-1-10中的斜率累加器用于补偿和修正温度测量过程中的非线性,其输出用于修正计数器1的预设值。
图2-2-11DS18B20测温原理框图图2-2-12DS18B20电路2.2.8按键电路按键是由一组按键或触摸开关组成的阵列,是一种常用的输入设备。键盘可分为编码键盘和非编码键盘1。编码键盘通过硬件电路产生按键的按键代码。该键盘程序简单,但硬件电路复杂,价格昂贵,单片机系统一般不采用。在非编码键盘中,一些键通常排列成行矩阵。硬件逻辑与密钥编码之间没有严格的对应关系,但由所用程序决定。非编码键盘的硬件接口简单,但占用CPU时间较长,因此通常采用可编程键盘管理芯片来克服这一缺陷。本设计采用两种按键,一种是按键式非编码键盘,另一种是触摸式非编码开关,由于接线中有四个插脚,因此需要用万用表测量连接,然后将两个插脚连接起来。原理图如下为了计算数据,必须先输入数据,还必须确认按键输入的值。这需要扫描键盘,以便确认到底按了哪个键。图2-2-13按键电路第三章软件设计与分析3.1软件设计的组成系统由延时子功能、LCD1602LCD写入命令子功能、LCD1602LCD写入数据子功能、DS18B20初始化子功能、DS18B20读取1位数据子功能、读取字节数据子功能、向DS18B20写入字节数据子功能、DS18B20启动取温转换子功能组成,获取温度子函数、初始化子函数、DS1302地址子函数、数据发送子函数发送子函数、DS1302数据读取子函数、DS1302初始化子函数、显示年、月、日、周子函数、按键扫描子函数、主函数和数据定义。图3-1-1DS1302读取日期和时间流程图图3-1-2DS18B20温度传感器流程图图3-1-3时间调整程序流程图图3-1-4整体流程图图3-1-5DS1302读写程序流程图3.2源程序#include<reg51.h>#include"DS18B20.h"uchara,b,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp,miao1,shi1=12,fen1=1,miao1=0,clock=0;//flag用于读取头文件中的温度值,和显示温度值#defineyh0x80//LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)#defineer0x80+0x40//LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)sbitrs=P2^0;sbiten=P2^2;sbitrw=P2^1;//如果硬件上rw接地,就不用写这句和后面的rw=0了sbitled=P2^6;//LCD背光开关//DS1302时钟芯片与C51之间的引脚连接定义sbitIO=P1^1;sbitSCLK=P1^0;sbitRST=P1^2;sbitCLO=P1^4;sbitACC0=ACC^0;sbitACC7=ACC^7;/************************************************************ACC累加器=AACC.0=E0HACC.0就是ACC的第0位。Acc可以位寻址。累加器ACC是一个8位的存储单元,是用来放数据的。但是,这个存储单元有其特殊的地位,是单片机中一个非常关键的单元,很多运算都要通过ACC来进行。以后在学习指令时,常用A来表示累加器。但有一些地方例外,比如在PUSH指令中,就必须用ACC这样的名字。一般的说法,A代表了累加器中的内容、而ACC代表的是累加器的地址。***************************************************************///校时按键与C51的引脚连接定义sbitkey1=P1^5;//设置键sbitkey2=P1^6;//加键sbitkey3=P1^7;//减键sbitbuzzer=P1^3;//蜂鸣器,通过三极管9012驱动,端口低电平响/**************************************************************/ucharcodetab1[]={"20--"};//年显示的固定字符ucharcodetab2[]={"::"};//时间显示的固定字符ucharcodetab3[]={"HELLOWELCOME"};//开机动画//延时函数,后面经常调用voiddelay(uintxms)//延时函数,有参函数{ uintx,y; for(x=xms;x>0;x--) for(y=110;y>0;y--);}/********液晶写入指令函数与写入数据函数,以后可调用**************//*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面*/voidwrite_1602com(ucharcom)//****液晶写入指令函数****{ rs=0;//数据/指令选择置为指令 rw=0;//读写选择置为写 P0=com;//送入数据 delay(1); en=1;//拉高使能端,为制造有效的下降沿做准备 delay(1); en=0;//en由高变低,产生下降沿,液晶执行命令}voidwrite_1602dat(uchardat)//***液晶写入数据函数****{ rs=1;//数据/指令选择置为数据 rw=0;//读写选择置为写 P0=dat;//送入数据 delay(1); en=1;//en置高电平,为制造下降沿做准备 delay(1); en=0;//en由高变低,产生下降沿,液晶执行命令}voidlcd_init()//***液晶初始化函数****{ ucharj;write_1602com(0x0f|0x08); for(a=0;a<17;a++) write_1602dat(tab3[a]); j=17; while(j--) { write_1602com(0x1c);//循环左移 delay(700); } write_1602com(0x01); delay(10); write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据 write_1602com(0x0c);//开显示不显示光标 write_1602com(0x06);//整屏不移动,光标自动右移 write_1602com(0x01);//清显示 /***开机动画显示hellowelcomedianzizhong****/ write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示 for(a=0;a<14;a++) { write_1602dat(tab1[a]);//向液晶屏写日历显示的固定符号部分 //delay(3); } write_1602com(er+2);//时间显示固定符号写入位置,从第2个位置后开始显示 for(a=0;a<8;a++) { write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号 //delay(3); } write_1602com(er+0); write_1602dat(0x24); write_1602com(er+1); write_1602dat(0x20);}/***************DS1302有关子函数********************/voidwrite_byte(uchardat)//写一个字节{ ACC=dat; RST=1; for(a=8;a>0;a--) { IO=ACC0; SCLK=0; SCLK=1; ACC=ACC>>1; }}ucharread_byte()//读一个字节{ RST=1; for(a=8;a>0;a--) { ACC7=IO; SCLK=1; SCLK=0; ACC=ACC>>1; } return(ACC);}//voidwrite_1302(ucharadd,uchardat)//向1302芯片写函数,指定写入地址,数据{ RST=0; SCLK=0; RST=1; write_byte(add); write_byte(dat); SCLK=1; RST=0;}ucharread_1302(ucharadd)//从1302读数据函数,指定读取数据来源地址{ uchartemp; RST=0; SCLK=0; RST=1; write_byte(add); temp=read_byte(); SCLK=1; RST=0; return(temp);}ucharBCD_Decimal(ucharbcd)//BCD码转十进制函数,输入BCD,返回十进制{ ucharDecimal; Decimal=bcd>>4; return(Decimal=Decimal*10+(bcd&=0x0F));}//voidds1302_init()//1302芯片初始化子函数(2010-01-07,12:00:00,week4){ RST=0; SCLK=0; write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x80,0x00);//向DS1302内写秒寄存器80H写入初始秒数据00 write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00 write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12 write_1302(0x8a,0x01);//向DS1302内写周寄存器8aH写入初始周数据4 write_1302(0x86,0x08);//向DS1302内写日期寄存器86H写入初始日期数据07 write_1302(0x88,0x07);//向DS1302内写月份寄存器88H写入初始月份数据01 write_1302(0x8c,0x10);//向DS1302内写年份寄存器8cH写入初始年份数据10 write_1302(0x8e,0x80);//打开写保护}////温度显示子函数voidwrite_temp(ucharadd,uchardat)//向LCD写温度数据,并指定显示位置{ uchargw,sw,bw; if(dat>=0&&dat<=128) { gw=dat%10;//取得个位数字 sw=dat%100/10;//取得十位数字 bw=dat/100 ;//取得百位数字 } else { dat=256-dat; gw=dat%10;//取得个位数字 sw=dat%100/10;//取得十位数字 bw=-3; //0x30-3表示为负号 } write_1602com(er+add);//er是头文件规定的值0x80+0x40 write_1602dat(0x30+bw);//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码write_1602dat(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码 write_1602dat(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码 }////时分秒显示子函数voidwrite_sfm(ucharadd,uchardat)//向LCD写时分秒,有显示位置加、现示数据,两个参数{ uchargw,sw; gw=dat%10;//取得个位数字 sw=dat/10;//取得十位数字 write_1602com(er+add);//er是头文件规定的值0x80+0x40 write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码 }////年月日显示子函数voidwrite_nyr(ucharadd,uchardat)//向LCD写年月日,有显示位置加数、显示数据,两个参数{ uchargw,sw; gw=dat%10;//取得个位数字 sw=dat/10;//取得十位数字 write_1602com(yh+add);//设定显示位置为第一个位置+add write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码 }//voidwrite_week(ucharweek)//写星期函数{ write_1602com(yh+0x0c);//星期字符的显示位置 switch(week) { case1: write_1602dat('M');//星期数为1时,显示 write_1602dat('O'); write_1602dat('N'); break; case2: write_1602dat('T');//星期数据为2时显示 write_1602dat('U'); write_1602dat('E'); break; case3: write_1602dat('W');//星期数据为3时显示 write_1602dat('E'); write_1602dat('D'); break; case4: write_1602dat('T');//星期数据为4是显示 write_1602dat('H'); write_1602dat('U'); break; case5: write_1602dat('F');//星期数据为5时显示 write_1602dat('R'); write_1602dat('I'); break; case6: write_1602dat('S');//星期数据为6时显示 write_1602dat('T'); write_1602dat('A'); break; case7: write_1602dat('S');//星期数据为7时显示 write_1602dat('U'); write_1602dat('N'); break; }}//****************键盘扫描有关函数**********************voidkeyscan(){ if(key1==0)//key1为功能键(设置键) { delay(9);//延时,用于消抖动 if(key1==0)//延时后再次确认按键按下 { buzzer=0;//蜂鸣器短响一次 delay(20); buzzer=1; while(!key1); key1n++; if(key1n==12) key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环 switch(key1n) { case1:TR0=0;//关闭定时器 //TR1=0; write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标 write_1602com(0x0f);//设置光标为闪烁 temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302 write_1302(0x8e,0x00); write_1302(0x80,0x80|temp);//miao write_1302(0x8e,0x80); break; case2:write_1602com(er+6);//按2次fen位置显示光标 //write_1602com(0x0f); break; case3:write_1602com(er+3);//按动3次,shi //write_1602com(0x0f); break; case4:write_1602com(yh+0x0e);//按动4次,week //write_1602com(0x0f); break; case5:write_1602com(yh+0x0a);//按动5次,ri //write_1602com(0x0f); break; case6:write_1602com(yh+0x07);//按动6次,yue //write_1602com(0x0f); break; case7:write_1602com(yh+0x04);//按动7次,nian //write_1602com(0x0f); break; case8:write_1602com(er+1); write_1602dat(0x4d); write_1602com(er+1); break; case9:write_1602com(er+1); write_1602dat(0x46); write_1602com(er+1); break; case10:write_1602com(er+1); write_1602dat(0x53); write_1602com(er+1); break; case11: write_1602com(er+1); write_1602dat(0x20); write_1602com(0x0c);//按动到第8次,设置光标不闪烁 TR0=1;//打开定时器 temp=(miao)/10*16+(miao)%10; write_1302(0x8e,0x00); write_1302(0x80,0x00|temp);//miao数据写入DS1302 write_1302(0x8e,0x80); break; } } } //加键key2 if(key1n!=0)//当key1按下以下。再按以下键才有效(按键次数不等于零) { if(key2==0)//上调键 { delay(10); if(key2==0) { buzzer=0;//蜂鸣器短响一次 delay(20); buzzer=1; while(!key2); switch(key1n) { case1: miao++;//设置键按动1次,调秒 if(miao==60) miao=0;//秒超过59,再加1,就归零 write_sfm(0x08,miao);//令LCD在正确位置显示"加"设定好的秒数 temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x80,temp);//向DS1302内写秒寄存器80H写入调整后的秒数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,光标自动右移,所以要指定返回 //write_1602com(0x0b); break; case2: fen++; if(fen==60) fen=0; write_sfm(0x05,fen);//令LCD在正确位置显示"加"设定好的分数据 temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case3: shi++; if(shi==24) shi=0; write_sfm(2,shi);//令LCD在正确的位置显示"加"设定好的小时数据 temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case4: week++; if(week==8) week=1; write_1602com(yh+0x0C);//指定'加'后的周数据显示位置 write_week(week);//指定周数据显示内容 temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case5: ri++; switch(yue) { case1: case3: case5: case7: case8: case10: case12: if(ri>31) ri=1; break; case2: if(nian%4==0||nian%400==0) { if(ri>29) ri=1; } else { if(ri>28) ri=1; } break; case4: case6: case9: case11: ri++; if(ri>30) ri=1; break; } write_nyr(9,ri);//令LCD在正确的位置显示"加"设定好的日期数据 temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case6: yue++; if(yue==13) yue=1; write_nyr(6,yue);//令LCD在正确的位置显示"加"设定好的月份数据 temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case7: nian++; if(nian==100) nian=0; write_nyr(3,nian);//令LCD在正确的位置显示"加"设定好的年份数据 temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case8: write_1602com(er+9);//设置闹钟的秒定时 miao1++; if(miao1==60) miao1=0; write_sfm(0x08,miao1);//令LCD在正确位置显示"加"设定好秒的数据 write_1602com(er+9);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case9: write_1602com(er+6);//设置闹钟的分钟定时 fen1++; if(fen1==60) fen1=0; write_sfm(0x05,fen1);//令LCD在正确位置显示"加"设定好的分数据 write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case10:write_1602com(er+3);//设置闹钟的小时定时 shi1++; if(shi1==24) shi1=0; write_sfm(0x02,shi1);//令LCD在正确的位置显示"加"设定好的小时数据 write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; } } } //减键key3,各句功能参照'加键'注释 if(key3==0) { delay(10);//调延时,消抖动 if(key3==0) { buzzer=0;//蜂鸣器短响一次 delay(20); buzzer=1; while(!key3); switch(key1n) { case1: miao--; if(miao==-1) miao=59;//秒数据减到-1时自动变成59 write_sfm(0x08,miao);//在LCD的正确位置显示改变后新的秒数 temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x80,temp);//向DS1302内写秒寄存器80H写入调整后的秒数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 //write_1602com(0x0b); break; case2: fen--; if(fen==-1) fen=59; write_sfm(5,fen); temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case3: shi--; if(shi==-1) shi=23; write_sfm(2,shi); temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case4: week--; if(week==0) week=7; write_1602com(yh+0x0C);//指定'加'后的周数据显示位置 write_week(week);//指定周数据显示内容 temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case5: ri--; switch(yue) { case1: case3: case5: case7: case8: case10: case12: if(ri==0) ri=31; break; case2:if(nian%4==0||nian%400==0) { if(ri==0) ri=29; } else { if(ri==0) ri=28; } break; case4: case6: case9: case11: if(ri==0) ri=30; break; } write_nyr(9,ri); temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case6: yue--; if(yue==0) yue=12; write_nyr(6,yue); temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case7: nian--; if(nian==-1) nian=99; write_nyr(3,nian); temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码 write_1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码 write_1302(0x8e,0x80);//打开写保护 write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; case8: write_1602com(er+9);//设置闹钟的秒定时 miao1--; if(miao1==-1) miao1=59; write_sfm(0x08,miao1);//令LCD在正确位置显示"加"设定好秒的数据 write_1602com(er+9);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case9: write_1602com(er+6);//设置闹钟的分钟定时 fen1--; if(fen1==-1) fen1=59; write_sfm(0x05,fen1);//令LCD在正确位置显示"加"设定好的分数据 write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break; case10:write_1602com(er+3);//设置闹钟的小时定时 shi1--; if(shi1==-1) shi1=23; write_sfm(0x02,shi1);//令LCD在正确的位置显示"加"设定好的小时数据 write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break; } } } }}//定时器0初始化程序voidinit()//定时器、计数器设置函数{ TMOD=0x11;//指定定时/计数器的工作方式为1 TH0=0;//定时器T0的高四位=0 TL0=0;//定时器T0的低四位=0 EA=1;//系统允许有开放的中断 ET0=1;//允许T0中断 TR0=1;//开启中断,启动定时器}//*******************主函数**************************//***************************************************voidmain(){ lcd_init();//调用液晶屏初始化子函数 ds1302_init();//调用DS1302时钟的初始化子函数 init();//调用定时计数器的设置子函数 led=0;//打开LCD的背光电源buzzer=0;//蜂鸣器长响一次delay(80);buzzer=1; while(1)//无限循环下面的语句: { keyscan();//调用键盘扫描子函数}}/*************通过定时中断实现定是独处并显示数据******************/voidt0()interrupt1//取得并显示日历和时间{ //Init_DS18B20();//温度传感器DS18b2初始化子函数,在头文件中 flag=ReadTemperature();//将18b2头文件运行返回的函数结果送到变量FLAG中,用于显示 //读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样): miao=BCD_Decimal(read_1302(0x81)); fen=BCD_Decimal(read_1302(0x83)); shi=BCD_Decimal(read_1302(0x85)); ri=BCD_Decimal(read_1302(0x87)); yue=BCD_Decimal(read_1302(0x89)); nian=BCD_Decimal(read_1302(0x8d)); week=BCD_Decimal(read_1302(0x8b)); //显示温度、秒、时、分数据: write_temp(12,flag);//显示温度,从第二行第12个字符后开始显示 write_sfm(8,miao);//秒,从第二行第8个字后开始显示(调用时分秒显示子函数) write_sfm(5,fen);//分,从第二行第5个字符后开始显示 write_sfm(2,shi);//小时,从第二行第2个字符后开始显示 //显示日、月、年数据: write_nyr(9,ri);//日期,从第二行第9个字符后开始显示 write_nyr(6,yue);//月份,从第二行第6个字符后开始显示 write_nyr(3,nian);//年,从第二行第3个字符后开始显示 write_week(week); /***********整点报时程序************/ if(fen==0&&miao==0) if(shi<22&&shi>6) { buzzer=0;//蜂鸣器短响一次 delay(20); buzzer=1; } /**************闹钟程序:将暂停键按下停止蜂鸣********************/ if(shi1==shi&&fen1==fen&&miao==0) { clock=1; } if(clock==1) { buzzer=0;//蜂鸣器短响一次 delay(20); buzzer=1; } if(CLO==0) /*按下p1.4停止蜂鸣*/ clock=0; }typedefunsignedcharuchar;typedefunsignedintuint;sbitDQ=P3^3;//定义DQ引脚为P3.3/*******************************延时函数*********************************功能:在11.059MHz的晶振条件下调用本函数需要24μs,然后每次计数需16μs**************************************************************************/voidDS18_delay(intuseconds){ ints; for(s=0;s<useconds;s++);}/*******************************复位函数********************************功能:完成单总线的复位操作。*复位时间为480μs,因此延时时间为(480-24)/16=28.5,取29μs。*经过70μs之后检测存在脉冲,因此延时时间为(70-24)/16=2.875,取3μs。**********************************************************************
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 版企业培训合作合同
- 运动自行车品牌代理合同
- 新疆沙雅县市级名校2025届初三下学期英语试题分类汇编含答案
- 五金制品锯类购销协议
- 小型企业劳动合同模板
- 土地使用权买卖合同模板范本
- 商场店铺租赁合同范本
- 冀教版小学数学六年级下册小升初毕业会考模拟卷(三) (含答案)
- 2025年云南省曲靖市沾益区民族中学中考历史一模试卷(含答案)
- 智能设备服务合同
- 2025山东省港口集团有限公司招聘183人笔试参考题库附带答案详解
- 2025青桐鸣高三4月大联考数学试题及答案
- 水利部珠江水利委员会所属事业单位招聘笔试真题2024
- 甘肃省2025年甘肃高三月考试卷(四4月)(甘肃二诊)(英语试题+答案)
- 2025年河南建筑职业技术学院高职单招语文2019-2024历年真题考点试卷含答案解析
- 企业交叉作业协议书
- 2025届湖北省武汉市高考数学一模试卷含解析
- 平凡之路歌词
- 教师资格证统计表
- 气柜施工方案
- 《膀胱结石的护理》PPT课件.ppt
评论
0/150
提交评论