万年历数字钟及可调时钟系统
数字时钟知识讲解

数字时钟知识讲解目录一、数字时钟概述 (2)1. 数字时钟定义与特点 (3)2. 数字时钟发展历史 (4)二、数字时钟基本原理 (5)1. 数字时钟计时原理 (6)1.1 时间计数方式 (7)1.2 计时准确度与频率 (8)2. 数字时钟电路构成 (9)2.1 振荡器电路 (10)2.2 分频器电路 (11)2.3 显示驱动电路 (12)三、数字时钟显示技术 (13)1. LED显示技术 (14)1.1 LED数码管显示原理 (15)1.2 LED时钟显示效果 (17)2. LCD显示技术 (18)2.1 LCD显示器原理 (19)2.2 LCD时钟显示效果 (20)四、数字时钟功能与应用领域介绍 (21)一、数字时钟概述数字时钟是一种现代化的时间显示设备,与传统的机械时钟相比,具有更高的准确性和精度。
数字时钟采用电子技术和数字化显示方式,能够精确地显示当前的小时、分钟、甚至秒数。
它们广泛应用于家庭、办公室、公共场所,甚至是个人手持设备中,已成为日常生活中不可或缺的一部分。
数字时钟的基本原理是依靠晶体振荡器来计时,通过电子线路驱动显示器显示时间。
与传统的机械时钟相比,数字时钟具有许多优势。
它们精度高,不受环境温度和机械振动的影响。
数字时钟易于阅读,特别是对于视力较弱的人群来说,数字显示比传统指针显示更为清晰易辨。
现代数字时钟还具备多种附加功能,如闹钟、定时器、日历等,为用户提供了极大的便利。
数字时钟的发展离不开电子技术的进步,随着科技的不断发展,数字时钟不仅在功能和应用领域得到了扩展,其设计和制造技术也不断提升。
数字时钟已不再是简单的计时工具,更是时尚和科技的代表。
它们在造型设计、显示色彩、界面控制等方面不断创新,为用户带来全新的视觉体验和使用感受。
数字时钟已经成为现代社会不可或缺的一部分,它们以其高精度、易用性和多功能性为人们提供了更加便捷和准确的时间服务。
1. 数字时钟定义与特点数字时钟是一种采用数字技术来显示时间的电子设备,与传统的模拟时钟相比,数字时钟具有许多优点和特点。
具有温度显示的电子实时时钟万年日历系统的设计与制作

毕业设计(论文)《具有温度显示的电子实时时钟/万年日历系统的设计与制作》专业(系)电气工程系铁道通讯信号方向班级铁道通讯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研究背景当今社会逐渐步入信息化时代,快节奏、高效率成为当今时代的主题。
数字系统课程设计-万年历时钟 VHDL语言

process(clk,stop,rst)
variable ll:std_logic_vector(3 downto 0):="0000"; variable hh:std_logic_vector(3 downto 0):="0000"; begin if(rst='0')then ll:="0000";hh:="0000"; else if stop='0' then
是
个位 加一
进位 赋零
否
值为13?
是
判断 大小月 并赋 值输出
个十 位清零 进位 赋一
否 个位为10?
是
个位 清零十 位 加一
结束
图 10 月计数器算法流程图
图 11 月计数器 RTL 图 2.6 年计数器模块
年计数器模块为 1000 进制计数器,但其无进位输出。此外,该模块还负责 判断判断闰年还是平年,并将结果输出。其有两个输入和三个输出,其中 rst 起 复位作用,clk 为月计数器的进位,l 为个位输出,h 为十位输出,c 为进位输出,
6月14日6月22日项目设计开发环境使用25分设计任务功能理解与方案设计15分功能模块设计模块划分及编程设计30分功能仿真与调试10分设计报告及答辩20分合计100分得分1设计要求11设计任务设计制作一个基于lcd1602显示带有时间调整的万年历电子时钟
万年历电子时钟
--------------- 数字系统课程设计
port(rst,clk:in std_logic; l,h:out std_logic_vector(3 downto 0);
智能时钟万年历(详细电路图)

《嵌入式课程设计》讲义项目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消抖时间如何度过?”。
单片机课程设计—万年历[1]
![单片机课程设计—万年历[1]](https://img.taocdn.com/s3/m/f8634cde87c24028905fc3ce.png)
郑州轻工业学院软件学院单片机与接口技术课程设计总结报告设计题目:电子万年历学生:系别:专业:班级:学号:指导教师:2021年12月16日设计题目:电子万年历设计任务与要求:1、显示年月日时分秒及星期信息2、具有可调整日期和时间功能3、增加闰年计算功能方案比拟:方案一:系统分为主控制器模块、显示模块、按键开关模块,主控制模块采用AT89C52单片机为控制中心,显示模块采用普通的共阴LED数码管,键输入采用中断实现功能调整,计时使用AT89C52单片机自带的定时器功能,实现对时间、日期的操作,通过按键盘开关实现对时间、日期的调整。
方案二:系统分为主控模块、时钟电路模块、按键扫描模块,LCD显示模块,电源电路、复位电路、晶振电路等模块。
主控模块采用AT89C52单片机,按键模块用四个按键,用于调整时间,显示模块采用LCD1602,时钟电路模块采用DS1302时钟芯片实现对时间、日期的操作。
两个方案工作原理大致相同,只有显示模块和时钟电路不同。
LED数码管价格适中,对于数字显示效果较好,而且使用单片机的端口也较少; LCD1602液晶显示屏,显示功能强大,可以显示大量文字、图形,显示多样性,清晰可见,价格相对LED数码管来说要昂贵些,但是基于本设计显示的东西较多,假设采用LED数码管的话,所需数码管较多,而且不利于控制,因此选择LCD1602作为显示模块。
DS1302是一款高性能的实时时钟芯片,以计时准确、接口简单、使用方便、工作电压范围宽和低功耗等优点,得到广泛的应用,实时时钟有秒、分、时、星期、日、月和年,月小于31天时可以自动调整,并具有闰年补偿功能,而且在掉电时能够在外部纽扣电池的供电下继续工作。
单片机有定时器的功能,但时间误差较大,且需要编写时钟程序,因此采用DS1302作为时钟电路。
比照以上方案,结合设计技术指标与要求我们选择了方案二进行设计。
逻辑总框图:该电子万年历的总体设计框图如图(1)所示。
电子万年历

摘要本设计是电子万年历。
具备三个功能:能显示年月日时分秒及星期信息,并具有可调整日期和时间功能。
我选用的是单片机8052来实现电子万年历的功能。
该电子万年历能够成功实现时钟运行,调整,显示年月日时分秒及星期,温度等信息。
该电子万年历使用12MHZ晶振与单片机8052相连接,通过软件编程的方法实现了以24小时为一个周期同时显示小时,分钟和秒的要求。
利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。
同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。
电子万年历设计与制作可采用数字电路实现,也可以采用单片机来完成。
若用数字电路完成,所设计的电路相当复杂,大概需要十几片数字集成块,其功能也主要依赖于数字电路的各功能模块的组合来实现,焊接的过程比较复杂,成本也非常高。
若用单片机来设计制作完成,由于其功能的实现主要通过软件编程来完成,么就降低了硬件电路的复杂性,而且其成本也有所降低,更适合我们大学生自主研发。
所以在该设计与制作中我选用了单片机8052,它是低功耗、高性能的CMOS型8位单片机。
片内带有4KB的Flash存储器,且允许在系统内改写或用编程器编程。
另外, 单片机8052的指令系统和引脚与8051完全兼容,片内有128B 的RAM、32条I/O口线、2个16位定时计数器、5个中断源、一个全双工串行口等。
因此,采用单片机8052原理制作的电子万年历,不仅仅在原理上能够成功实现计时等功能,也更经济,更适用,更符合我们实际生活的需要,对我们大学生来说也更加有用。
目录1 概述 (3)1.1单片机原理及应用简介 (3)1.2系统硬件设计 (4)1.3结构原理与比较 (6)2 系统总体方案及硬件设计 (8)2.1系统总体方案 (8)2.2硬件电路的总体框图设计 (10)2.3硬件电路原理图设计 (11)3 软件设计 (12)3.1主程序流程图 (12)3.2显示模块流程图 (12)4 Proteus软件仿真 (14)4.1Proteus ISIS简介 (14)4.2仿真过程 (15)4.3仿真结果 (15)5 课程设计体会 (17)参考文献 (18)附1:源程序代码 (29)附2:系统原理图 (26)1 概述1.1单片机原理及应用简介随着国内超大规模集成电路的出现,微处理器及其外围芯片有了迅速的发展。
用DS1302与LCD1602设计可调数字万年历课程设计

数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:年月日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
51单片机万年历课程设计报告

一、设计任务:1、设计任务:设计并制作一个数字钟。
2、设计要求:●显示年月日时分秒及星期信息●具有可调整日期和时间功能●增加闰年计算功能●显示部分由LCD1602完成二、方案论证:1.显示部分:显示部分是本次设计的重要部分,一般有以下两种方案:方案一:采用LED显示,分静态显示和动态显示。
对于静态显示方式,所需的译码驱动装置很多,引线多而复杂,且可靠性也较低。
而对于动态显示方式,虽可以避免静态显示的问题,但设计上如果处理不当,易造成亮度低,有闪烁等问题。
方案二:采用LCD显示。
LCD液晶显示具有丰富多样性、灵活性、电路简单、易于控制而且功耗小等优点,对于信息量多的系统,是比较适合的。
鉴于上述原因,我们采用方案二。
2.数字时钟:数字时钟是本设计的核心的部分。
根据需要可采用以下两种方案实现:方案一:方案完全用软件实现数字时钟。
原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。
利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将时字节清零。
该方案具有硬件电路简单的特点,但当单片机不上电,程序将不执行。
而且由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。
方案二:方案采用Dallas公司的专用时钟芯片DS1302。
该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。
为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。
当电网电压不足或突然掉电时,可使系统自动转换到内部锂电池供电系统。
而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。
基于时钟芯片的上述优点,本设计采用方案二完成数字时钟的功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
万年历数字钟及可调时钟系统一、引言万年历数字钟是一种用万年历时钟芯片实现年、月、日、时、分、秒计时,并通过单片机处理后送给显示芯片显示的装置,与机械式时钟相比具有更高的准确性和直观性,且具有更长的使用寿命。
本系统还可以扩展为可调的自动开关,对家电对用电设备进行控制,笔者在随后改制成为可调时的自动断电的供电系统.二、原理图设计1.单片机及其外围电路设计复位采用X25045芯片,复位电路如图1所示。
图1 复位电路设计单片机采用贴片封装的AT89S51,晶振为11.0592MHz。
其中P1.5~P1.7为下载程序使用,电路如图2所示。
图2 单片机89S51外围电路设计2.时钟芯片电路设计时钟芯片采用PCF8563,晶振采用32.768K,电容使用15pf。
PCF8563 是PHILIPS 公司推出的一款工业级内含I2C 总线接口功能的具有极低功耗的多功能时钟日历芯片。
内部时钟电路、内部振荡电路、内部低电压检测电路(1.0V)以及两线制I2C 总线通讯方式,不但使外围电路及其简洁,而且也增加了芯片的可靠性。
同时每次读写数据后,内嵌的字地址寄存器会自动产生增量。
电路如图3所示。
图3 时钟芯片电路设计3.显示芯片电路设计显示芯片采用ZLG7289,晶振为12MHz。
ZLG7289A 是广州周立功单片机发展有限公司自行设计的,具有SPI 串行接口功能的可同时驱动8 位共阴式数码管(或64 只独立LED )的智能显示驱动芯片,该芯片同时还可连接多达64 键的键盘矩阵,单片即可完成LED 显示﹑键盘接口的全部功能。
电路如图4所示。
图4 显示芯片电路设计4.双电源电路设计系统采用双电源,平时使用V1=10V的外接电源,停电时使用电池,由V2输入。
电池有6节,其电压为9V。
当电池电压低于6V时,LED亮,说明电池电量不足。
电路如图5所示。
图5 双电源电路设计三、程序设计程序开始时先对系统初始化,并设置好各种中断。
下步操作主要是对时钟芯片进行操作,首先要给时钟芯片设置初值,时钟芯片便自行计数。
此时检测是否有按键按下,按键是为了调整时钟。
有按键按下则执行按键中断程序,没有按键按下则执行下一步的操作,即取时钟芯片中的时钟值,然后送显示。
程序流程图如下。
图6 总体流程图四、源程序#include <reg51._date;void RESWDI(void);void WREN(void);void WRDI(void);void WRSR(void);unsigned char RSDR(void);void WIPCHK(void);void OUTByte(unsigned char Byte);unsigned char INPUTByte(void);unsigned char ReadByte(unsigned char ADD);void WriteByte(unsigned char Byte,ADD);#define _Nop() _nop_()sbit zlg7289_cs =P1^1;sbit zlg7289_clk =P2^6;sbit zlg7289_dio =P2^7;sbit zlg7289_key =P3^2;sbit p07=P0^7;sbit p06=P0^6;sbit CS=P2^4;sbit SCK=P2^2;sbit SO=P2^5;sbit SI=P2^3;sbit p10=P1^0;sbit SDA=P1^2; *模拟I2C数据传送位*sbit SCL=P1^3; *模拟I2C时钟控制位*uchar buf[9]={0x00,0x00,0x30,0x23,0x15,0x1,0x05,0x04,0x05}; uchar bufdata,bb,date;uchar SLA=0xA2,SUBA=0x00;uchar *p;uchar keychange=0;uchar key=0; *键盘值*bit keyint=0; *按键中断标志*bit keyok=1; *数据是否修改好*uchar num=0; *移位键移到哪个LED*void delay(uchar i){while(i--);}******************** TIMER1 interrupt process *************************** timer0 (void) interrupt 1 using 1{TH0=0x3c;TL0=0xb0;RESWDI();}void RESWDI(void) 复位看门狗(喂狗){zlg7289_cs=1;CS =1;CS =0;CS =1;zlg7289_cs=1;}void WREN(void) 写使能复位使用)?{zlg7289_cs=1;SCK=0;CS=0;OUTByte(0x06); 发送06H写使能命令字SCK=0;CS=1;zlg7289_cs=1;}void WRDI(void) 写使能复位(禁止写{{zlg7289_cs=1;SCK=0;CS=0;OUTByte(0x04); 发送04H写禁止命令字SCK=0; CS=1;zlg7289_cs=1;}void WRSR(void) 写状态寄存器{WREN();zlg7289_cs=1;SCK=0;CS=0;OUTByte(0x01); 发送01H写寄存器命令字OUTByte(0x00); 发送寄存器值BL0,BL1为0没写保护,WD0=0 W01=1 WD1=0WD1=0看门狗复位时间1.4SSCK=0;CS=1;zlg7289_cs=1;WIPCHK(); 判断是否写入}unsigned char RSDR(void) 读状态寄存器{unsigned char Temp;zlg7289_cs=1;SCK=0;CS=0;OUTByte(0x05); 发送05H读状态寄存器命令字Temp =INPUTByte(); 读状态寄存器值SCK=0;CS=1;return Temp;;这一个调试时没有执行,Temp的值总是0xFF;??????????? zlg7289_cs=1;}void WIPCHK(void) 检查WIP位,判断是否写入完成{unsigned char Temp,TempCyc;for(TempCyc=0;TempCyc<50;TempCyc++){Temp =RSDR(); 读状态寄存器if (Temp&0x01==0)TempCyc =50;}}单字节指令或数据写入X25045在SI线上输入的数据在SCK的上升沿被锁存。
void OUTByte(unsigned char Byte) 输出一个定节{unsigned char TempCyc;zlg7289_cs=1;for(TempCyc=0;TempCyc<8;TempCyc++){SCK =0;if(Byte&0x80)SI =1;elseSI =0;SCK =1;Byte =Byte<<1; 右移}SI=0; 使SI处于确定的状态zlg7289_cs=1;}单字节数据从X25045读到单片机数据由SCK的下降沿输出到SO线上。
unsigned char INPUTByte(void) 输入一个字节{unsigned char Temp=0, TempCyc;zlg7289_cs=1;for(TempCyc=0;TempCyc<8;TempCyc++){Temp =Temp<<1; 右移SCK =1;SCK=0;if (SO)Temp =Temp|0x01; SO为1,则最低位为1elseTemp&=0xFE;}return Temp;;这一个调试时没有执行,Temp的值总是0zlg7289_cs=1;}unsigned char ReadByte(unsigned char ADD) 读地址中的数据这里不做先导字处理,只能读00-FFH{unsigned char Temp;zlg7289_cs=1;SCK=0;CS=0;SO=1;SI=1;OUTByte(0x3); 发送读指令03H 如要支持000-FFF则要把高位地址左移3位再为03H相或OUTByte(ADD); 发送低位地址Temp =INPUTByte();SCK=0;CS=1;return Temp;这一个调试时没有执行,Temp的zlg7289_cs=1;}void WriteByte(unsigned char Byte,ADD) 向地址写入数据这里同样不做先导字处理,只能写00-FFH{WREN();zlg7289_cs=1;SCK=0;CS=0;SO=1;SI=1;OUTByte(0x2); 发送写指令02H 如要支持000-FFF则要把高位地址左移2位再为02H相或OUTByte(ADD); 发送低位地址OUTByte(Byte); 发送数据SCK=0;CS=1;WIPCHK();zlg7289_cs=1;}******************************************************************** ***************模拟I2C总线传输程序*********************************** ******************************************************************** bit ack; *应答标志位********************************************************************起动总线函数******************************************************************** void Start_I2c(){SDA=1; *发送起始条件的数据信号*_Nop();SCL=1;_Nop(); *起始条件建立时间大于4.7us,延时*_Nop();_Nop();_Nop();_Nop();SDA=0; *发送起始信号*_Nop(); * 起始条件锁定时间大于4μs*_Nop();_Nop();_Nop();_Nop();SCL=0; *钳住I2C总线,准备发送或接收数据*_Nop();_Nop();}*******************************************************************结束总线函数******************************************************************** void Stop_I2c(){SDA=0; *发送结束条件的数据信号*_Nop(); *发送结束条件的时钟信号*SCL=1; *结束条件建立时间大于4μs*_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1; *发送I2C总线结束信号*_Nop();_Nop();_Nop();_Nop();}*******************************************************************字节数据传送函数******************************************************************** void SendByte(uchar c){uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) *要传送的数据长度为8位*{if((c<<BitCnt)&0x80)SDA=1;else SDA=0;_Nop();SCL=1; *置时钟线为高,通知被控器开始接收数据位* _Nop();_Nop(); *保证时钟高电平周期大于4μs*_Nop();_Nop();_Nop();SCL=0;}_Nop();_Nop();SDA=1; *8位发送完后释放数据线,准备接收应答位* _Nop();_Nop();SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;else ack=1; *判断是否接收到应答信号*SCL=0;_Nop();_Nop();}*******************************************************************字节数据接收函数******************************************************************** uchar RcvByte(){uchar retc;uchar BitCnt;retc=0;SDA=1; *置数据线为输入方式*for(BitCnt=0;BitCnt<8;BitCnt++){_Nop();SCL=0; *置时钟线为低,准备接收数据位*_Nop();_Nop(); *时钟低电平周期大于4.7s*_Nop();_Nop();_Nop();SCL=1; *置时钟线为高使数据线上数据有效*_Nop();_Nop();retc=retc<<1;if(SDA==1)retc=retc+1; *读数据位,接收的数据位放入retc中 * _Nop();_Nop();}SCL=0;_Nop();_Nop();return(retc);}********************************************************************应答子函数******************************************************************** void Ack_I2c(bit a){if(a==0)SDA=0; *在此发出应答或非应答信号*else SDA=1;_Nop();_Nop();_Nop();SCL=1;_Nop();_Nop(); *时钟低电平周期大于4μs*_Nop();_Nop();_Nop();SCL=0; *清时钟线,钳住I2C总线以便继续接收*_Nop();_Nop();}*******************************************************************向有子地址器件发送多字节数据函数******************************************************************** bit ISendStr(uchar sla,uchar suba,uchar *s){uchar i;Start_I2c(); *启动总线*SendByte(sla); *发送器件地址*if(ack==0)return(0);SendByte(suba); *发送器件子地址*if(ack==0)return(0);for(i=0;i<9;i++){SendByte(*s); *发送数据*if(ack==0)return(0);s++;}Stop_I2c(); *结束总线*return(1);}*******************************************************************向有子地址器件读取多字节数据函数******************************************************************** bit IRcvStr(uchar sla,uchar suba,uchar *s){uchar i;Start_I2c(); *启动总线*SendByte(sla); *发送器件地址*if(ack==0)return(0);SendByte(suba); *发送器件子地址*if(ack==0)return(0);Start_I2c();SendByte(sla+1);if(ack==0)return(0);for(i=0;i<8;i++){*s=RcvByte(); *发送数据*Ack_I2c(0); *发送就答位*s++;}*s=RcvByte();Ack_I2c(1); *发送非应位*Stop_I2c();return(1);}**********模拟I2C程序结束***************************void display(uint dis){uchar j;zlg7289_clk=0;delay(20);zlg7289_cs=0;for(j=0;j<16;j++){if((dis&0x8000)==0x8000) zlg7289_dio=1; else zlg7289_dio=0;delay(20);zlg7289_clk=1;delay(10);zlg7289_clk=0;delay(10);dis=dis<<1;}zlg7289_cs=1;delay(20);}void dis_play(uchar aa){uchar i;for(i=0;i<8;i++){if(_crol_(aa,i)&0x80)zlg7289_dio =1; elsezlg7289_dio =0; zlg7289_clk =1;delay(10); zlg7289_clk =0;}}void displaymonth(){bufdata=buf[5]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xc8);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);bufdata=buf[5]&0x30;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xc9);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);bufdata=buf[7]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xca);delay(10);dis_play(bufdata); zlg7289_cs=1;bufdata=buf[7]&0x10;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcf);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);}void displaytime(){bufdata=buf[3]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xce);delay(10);dis_play(bufdata); zlg7289_cs=1;bufdata=buf[3]&0x70;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcd);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);bufdata=buf[4]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcc);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);bufdata=buf[4]&0x30;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcb);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);}void display_x5045(){date=ReadByte(0x40);close_date=date;bufdata=date&0x0f;zlg7289_cs=0;delay(10);dis_play(0xce);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);bufdata=date&0x70;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcd);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);date=ReadByte(0x42);bufdata=date&0x0f;zlg7289_cs=0;open_date=ReadByte(0x42);delay(10);dis_play(0xcc);delay(10);dis_play(bufdata); zlg7289_cs=1;delay(70);bufdata=date&0x30;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcb);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);}****************按键处理程序********************* key=47: 闪烁移位键(shift)key=39: +key=39: -key=31: 确认键(ok)void key_int() interrupt 0{keyint=1;}void keyexe(){uchar i;uchar temp=0;uchar aa;p06=1;EX0=1;zlg7289_cs =0;delay(10);dis_play(0x15); *写入读键盘数据指令* delay(10);for(i=0;i<8;i++){temp=temp<<1;aa=zlg7289_dio; 按位或if(aa==1) 读数据位,接收的数据位放入retc中 temp=temp+1;zlg7289_clk=1;delay(10); 延时zlg7289_clk=0;}zlg7289_cs=1;key=temp;if(key==47) 闪烁移位键{key=0;keyok=0;EX0=0;if(num==8){num=1;}elsenum++;switch(num){ case 1: {display(0x88fe);}break; case 2: {display(0x88fd);}break; case 3: {display(0x88fb);}break; case 4: {display(0x88f7);}break; case 5: {display(0x88ef);}break; case 6: {display(0x88df);}break; case 7: {display(0x88bf);}break;case 8: {display(0x887f);}break;default: ;}EX0=1;}else if(key==39) +{EX0=0;key=0;RESWDI();if(num!=0){keyok=0;keychange=1;RESWDI();}if(num==7) 在分个位上{if((buf[3]&0x0f)==0x09) buf[3]&=0xf0; else ++buf[3];EX0=1;bufdata=buf[3]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xce);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);RESWDI();}else if(num==6) 在分十位上{if((buf[3]&0xf0)==0x50) buf[3]&=0x0f; else buf[3]+=0x10;EX0=1;bufdata=buf[3]&0x70;bufdata=bufdata>>4;bufdata=bufdata&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcd);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);RESWDI();}else if(num==5) 在小时个位上{if((buf[4]&0xf0)==0x20){if((buf[4]&0x0f)>0x02) buf[4]&=0xf0;else ++buf[4];}else if((buf[4]&0x0f)==0x09) buf[4]&=0xf0; else ++buf[4];EX0=1;bufdata=buf[4]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcc);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);RESWDI();}else if(num==4) 在小时十位上{if((buf[4]&0x0f)>0x03){if((buf[4]&0xf0)>0x00) buf[4]&=0x0f;else buf[4]+=0x10;}else if((buf[4]&0xf0)==0x20) buf[4]&=0x0f; else buf[4]+=0x10;EX0=1;bufdata=buf[4]&0x30;bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;RESWDI();delay(10);dis_play(0xcb);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);RESWDI();}else if(num==1) 在日的个位上{if((buf[5]&0xf0)==0x30){if((buf[5]&0x0f)>0x00) buf[5]&=0xf0;else ++buf[5];}else if((buf[5]&0x0f)==0x09) buf[5]&=0xf0; else ++buf[5];EX0=1;bufdata=buf[5]&0x0f;RESWDI();zlg7289_cs=0;delay(10);dis_play(0xc8);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);RESWDI();}else if(num==2) 在日的十位上{if((buf[5]&0x0f)>0x01){if((buf[5]&0xf0)>0x10) buf[5]&=0x0f;else buf[5]+=0x10;}else if((buf[5]&0xf0)==0x30) buf[5]&=0x0f; else buf[5]+=0x10;EX0=1;bufdata=buf[5]&0x30;RESWDI();bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;delay(10);dis_play(0xc9);delay(10);dis_play(bufdata);delay(70);RESWDI();}else if(num==4) 在月个位上{if((buf[7]&0xf0)==0x10){if((buf[7]&0x0f)>0x01) buf[7]&=0x0f;else ++buf[7];}else if((buf[7]&0x0f)==0x09) buf[7]&=0xf0; else ++buf[7];EX0=1;bufdata=buf[7]&0x0f;RESWDI();zlg7289_cs=0;delay(10);dis_play(0xca);delay(10);dis_play(bufdata);delay(70);RESWDI();}else if(num==8) 在月十位上{if((buf[7]&0x0f)>0x02){buf[7]&=0x0f;}else if((buf[7]&0xf0)==0x10) buf[7]&=0x0f; else buf[7]+=0x10;EX0=1;bufdata=buf[7]&0x10;bufdata=bufdata>>4;bufdata&=0x0f;RESWDI();zlg7289_cs=0;delay(10);dis_play(0xcf);delay(10);dis_play(bufdata); *显示月十位*delay(70);RESWDI();}else ;}else if(key==15) 存放断电时间,数据存放于5045中,每按键数据减少一 {display_x5045();EX0=1;key=0;if(num!=0){keyok=0;keychange=1;}if(num==7) 在分个位上{date=ReadByte(0x40);if((date&0x0f)==0x00) date|=0x09;EX0=1;bufdata=date&0x0f;zlg7289_cs=0;delay(10);dis_play(0xce);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);WriteByte(date,0x40);}else if(num==6) 在分十位上{date=ReadByte(0x40);if((date&0xf0)==0x00) date|=0x50; else date-=0x10;EX0=1;bufdata=date&0x70;bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;dis_play(0xcd);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);WriteByte(date,0x40);}else if(num==5) 在小时个位上{date=ReadByte(0x42);if((date&0xf0)==0x20){if(((date&0x0f)==0x00)||((date&0x0f)>0x03)) date|=0x03;else --date;}else if((date&0x0f)==0x00) date|=0x09;else --date;EX0=1;bufdata=date&0x0f;zlg7289_cs=0;delay(10);dis_play(0xcc);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);WriteByte(date,0x42);}else if(num==4) 在小时十位上{date=ReadByte(0x42);if((date&0x0f)>0x03){if((date&0xf0)==0x00) date|=0x10; else date-=0x10;}else if((date&0xf0)==0x00) date|=0x20; else date-=0x10;EX0=1;bufdata=date&0x30;bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;delay(10);dis_play(0xcb);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);WriteByte(date,0x42);}else if(num==1) 在日的个位上{if((buf[5]&0xf0)==0x30){if(((buf[5]&0x0f)==0x00)||((buf[5]&0x0f)>0x01)) buf[5]|=0x01;else --buf[5];}else if((buf[5]&0x0f)==0x00) buf[5]|=0x09;else --buf[5];bufdata=buf[5]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xc8);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);}else if(num==2) 在日的十位上{if((buf[5]&0x0f)>0x01){if((buf[5]&0xf0)==0x00) buf[5]|=0x20; else buf[5]-=0x10;}else if((buf[5]&0xf0)==0x00) buf[5]|=0x30; else buf[5]-=0x10;bufdata=buf[5]&0x30;bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;delay(10);dis_play(0xc9);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);}else if(num==3) 在月个位上{if((buf[7]&0xf0)==0x10){if(((buf[7]&0x0f)==0x00)||((buf[7]&0x0f)>0x01)) buf[7]|=0x01;else --buf[7];}else if((buf[7]&0x0f)==0x00) buf[7]|=0x09;else --buf[7];bufdata=buf[7]&0x0f;zlg7289_cs=0;delay(10);dis_play(0xca);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);}else if(num==8) 在月十位上{if((buf[7]&0x0f)>0x02) buf[7]&=0x0f;else if((buf[7]&0xf0)==0x00) buf[7]|=0x10; else buf[7]-=0x10;bufdata=buf[7]&0x10;bufdata=bufdata>>4;bufdata&=0x0f;zlg7289_cs=0;delay(10);dis_play(0xcf);delay(10);dis_play(bufdata);zlg7289_cs=1;delay(70);EX0=1;}else ;}else if(key==31) ok{EX0=0;key=0;keyok=1;num=0;if(keychange==1){keychange=0;p=buf;SUBA=0x00;buf[0]=0x00;buf[1]=0x00;buf[2]=0x00;ISendStr(SLA,SUBA,p);for (i=0;i<250;i++)delay(250);}else ;zlg7289_cs=0;delay(10);dis_play(0x88);delay(10);dis_play(0xff); *清LED闪烁* zlg7289_cs=1;delay(70);}EX0=1;}************************************************************ *******主函数************************************************ void main(){unsigned char i,j,word2;*程序的初始化**************************TMOD=0x09;TH0=0x3c;TL0=0xb0;TR0=1;ET0=1;IP=0x02; 中断优先级敲定IT0=1;EX0=1;IE0=1;EA=1; *打开全部中断*p10=1;p06=1;p07=1;WREN();WRSR();WRDI();WriteByte(0x07,0x40);在0x20中写入0x10,( 为了验证)WriteByte(0x0a,0x42);WRDI();word2=ReadByte(0x22);*初始化结束*********************************清LED显示**************************************** zlg7289_cs=0;delay(10);dis_play(0xA4); 复位zlg7289_cs=1;delay(70);*给时钟芯片附初值******************************** Stop_I2c();。