电子万年历课程设计
烟 台 南 山 学 院
单片机课程设计
题目 电子万年历
姓 名:
所在学院: 烟台南山学院
所学专业: 自 动 化
班 级:
学 号:
指导教师:
完成时间:
摘 要
单片机作为当今领域应用广泛的电子器件,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。单片机体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、开发较为容易。由于具有上述优点,在我国,单片机已广泛地应用在工业自动化控制、自动检测、智能仪器仪表、家用电器、电力电子、机电一体化设备等各个方面,而51单片机是各单片机中最为典型和最有代表性的一种。以AT89C51芯片为核心,辅以必要的电路,设计了一个简易的电子时钟,它由5V 直流电源供电,通过数码管能够准确显示时间,日期,调整时间,日期,从而到达学习、设计、开发软、硬件的能力。
时钟电路在计算机系统中起着非常重要的作用,是保证系统正常工作的基础。在一个单片机应用系统中,时钟有两方面的含义:一是指为保障系统正常工作的基准振荡定时信号,主要由晶振和外围电路组成,晶振频率的大小决定了单片机系统工作的快慢;二是指系统的标准定时时钟,即定时时间,它通常有两种实现方法:一是用软件实现,即用单片机内部的可编程定时/计数器来实现,但误差很大,主要用在对时间精度要求不高的场合;二是用专门的时钟芯片实现,在对时间精度要求很高的情况下,通常采用这种方法,典型的时钟芯片有:DS1302,DS12887,X1203等都可以满足高精度的要求。本设计由单片机AT89C51芯片和LED 数码管为核心,运用DS1302时钟芯片,辅以必要的电路,构成了一个单片机电子时钟。
1 绪论 ...................................................................... 1
2 总体方案设计与论证 ........................................................ 2
2.1数字时钟方案 ......................................................... 2
2.2显示方案 ............................................................. 3
3 硬件系统的方案设计 ........................................................ 4
3.1 系统框图 ............................................................ 4
3.2 单片机的选择 ........................................................ 4
3.3 时钟电路DS1302 ...................................................... 7
3.4 时钟电路及复位电路 .................................................. 9
3.5 驱动电路 ............................................................ 9
3.6 显示电路 ........................................................... 10
3.7 按键接口 ........................................................... 11
4 软件系统设计 ............................................................. 12
4.1 时间信息获取程序 ................................................... 12
4.2 显示程序 ........................................................... 12
5 系统调试 ................................................................. 13
5.1 系统调试 .......................................................... 13
5.2 时钟显示 .......................................................... 13
5.3 DS1302的调试 ...................................................... 13
5.4 按键电路调试 ...................................................... 13
6 总结 ..................................................................... 14
参考文献 ................................................................... 15
附录:系统程序 ............................................................ 16
现代数字万年历是根据单片机制作而成的计时工具,是人们日常生活中必不可少的必需品,广泛用于个人家庭以及车站、办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。但随着时间的推移,科学技术的不断发展,生活节奏越来越快,竞争日益激烈,人们对时间计量的精度要求越来越高,应用越来越广。可以说时间的准确已成为各行业安全运行的基础,如果时间出现误差而不能及时校正,会造成一系列严重的后果和经济损失。设计一种时钟校时系统显得尤为重要,而且此系统还可以随意的定时报时,及时提醒下一步要发生的事情或要完成的事情,给人们的生活、学习和工作带来更多的方便。高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟、石英表、石英钟都采用了石英技术,因此走时精度高、稳定性好、使用方便、不需要经常调校。数字式电子钟用集成电路计时,译码器电路代替机械式传动,用LED 显示器代替指针显示时间,减小了计时误差,这种时钟具有时、分、秒显示时间的功能,还可以进行时、分、秒的校对,片选的灵活性好。专门的时钟芯片还可以提供高精度的准确时间,本设计采用的时钟芯片是DS1302。
该电子时钟主要采用AT89C51单片机作为主控核心,由DS1302时钟芯片提供时钟、LED 动态扫描显示屏显示。AT89C51单片机是由Atmel 公司推出的,功耗小,电压可选用4~6V 电压供电;DS1302时钟芯片是美国DALLAS 公司推出的具有涓细电流充电功能的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小;数字显示是采用的LED 显示屏来显示,可以同时显示年、月、日、星期、时、分、秒和温度等信息。此外,该电子时钟还具有时间校准等功能。
2 总体方案设计与论证
2.1数字时钟方案
数字时钟是本设计的最主要的部分。根据需要,可利用两种方案实现。
方案一 采用专用时钟芯片DS1302
该芯片是美国DALLAS 公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM ,采用SPI 三线接口与CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM 数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。工作电压宽达2.5~5.5V 。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。 DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
图1 DS1302外部引脚图
各引脚的功能为:
Vcc1:备用电源;Vcc2:主电源。当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2
SCLK :串行时钟,输入;
I/O:三线接口时的双向数据线;
CE :输入信号,在读、写数据期间,必须为高。该引脚有两个功能:第一,CE 开始控制字访问移位寄存器的控制逻辑;其次,CE 提供结束单字节或多字节数据传输的方法。 DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h ~8Dh ,写时80h ~8Ch ),存放的数据格式为BCD 码形式。
方案二 完全用软件实现数字时钟
原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将十字节清零。该方案具有硬件电路简单的特点。但由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。而且,由于是软件实现,当单片机不上电,程序不执行时,时钟将不工作。
基于硬件电路的考虑,本设计采用方案一完成数字时钟的功能。
2.2显示方案
方案一 LCD液晶显示
采用LCD1602液晶显示器。在我们的日常生活中,我们对LCD1602液晶显示器并不陌生,在计算器、万用表、电子表及很多家用电子产品中都可以用到它显示的主要是数字、专用符号和图形。特别是在单片机的人机交流界面中用它作为输出器件有显示质量高、采用数字式接口、体积小、重量轻。功耗低等优点。通常按显示方式咳咳分为段式、字符式、点阵式等。但是在用它做显示器的时候,我们要对它进行编程,比如我们要显示一个字符,那么这个时候就复杂了,因为一个字符由6x8或8x8点阵组成,我们这时候既要找到和显示屏幕上某几个位置对应的显示RAM 区8字节,还要使每个字节的不同位为“1”,其他的为“0”,为“1”的点亮,为“0”的不亮。这样一来在显示简单的数字上就大大的加大了我们设计的难度,所以,对于一些简单的数字,我们不应采用LCD1602液晶显示来显示。
方案二 数码管显示
使用多个LED 数码管显示。LED 数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp 来表示。当数码管特定的段加上电压后,这些特定的段就会发亮,以形成我们眼睛看到的字样了。
图2 数码管
如:显示一个“2”字,那么应当是a 亮b 亮g 亮e 亮d 亮f 不亮c 不亮dp 不亮。LED 数码管有一般亮和超亮等不同之分,也有0.5寸、1寸等不同的尺寸。小尺寸数码管的显示笔画常用一个发光二极管组成,而大尺寸的数码管由二个或多个发光二极管组成,一般情况下,单个发光二极管的管压降为1.8V 左右,电流不超过30mA 。发光二极管的阳极连接到一起连接到电源正极的称为共阳数码管,发光二极管的阴极连接到一起连接到电源负极的称为共阴数码管。常用LED 数码管显示的数字和字符是0、1、2、3、4、5、6、7、8、9、A 、B 、C 、D 、E 、F 。再一个,数码管相对于LCD1602液晶显示器来说具有亮度大、接口设计比较容易,价格相对较便宜等优点。且在本次设计中恰好能把我们要显示的数字显示出来。所以,本次设计采用多个LED 数码管显示器来显示数字。
3 硬件系统的方案设计
3.1 系统框图
图3 系统框图
3.2 单片机的选择
根据所学单片机知识,AT89C51采用INTEL 公司可靠的CHMOS 工艺技术制造的高性能8位单片机,属于标准的MCS-51的HCMOS 产品。它结合了HMOS 的高速和高密度技术及CHMOS 的低功耗特征,它继承和扩展了MCS-48单片机的体系结构和指令系统。此外,AT89C51还可工作于低功耗模式,可通过两种软件选择空闲和掉电模式。在空闲模式下冻结CPU 而RAM 定时器、串行口和中断系统维持其功能。掉电模式下,保存RAM 数据,时钟振荡停止,同时停止芯片内其它功能。所以我们选用AT89C51单片机作为主控芯片,其引脚图如下图2所示
图4 AT89C51单片机引脚图
AT89C51单片机引脚介绍
Vss(20脚):接地
VCC (40脚): 主电源+5V
XTAL1(19脚):接外部晶体的一端。在片内它是振荡电路反相放大器的输入端在采用外部时钟时,对于HMOS 单片机,该端引脚必须接地;对于CHMOS 单片机,此引脚作为驱动端。
XTAL2(18脚): 接外部晶体的另一端。在片内它是一个振荡电路反相放大器的输出端,振荡电路的频率是晶体振荡频率。若需采用外部时钟电路,对于HMOS 单片机,该引脚输入外部时钟脉冲;对于CHMOS 单片机,此引脚应悬浮。
RST (9脚): 单片机刚接上电源时,其内部各寄存器处于随机状态,在该脚输入24个时钟周期宽度以上的高电平将使单片机复位(RESET )
PSEN (29脚): 在访问片外程序存储器时,此端输出负脉冲作为存储器读选通信号。CPU 在向片外存储器取指令期间,PSEN 信号在12个时钟周期中两次生效。不过,在访问片外数据存储器时,这两次有效PSEN 信号不出现。PSEN 端同样可驱动8个LSTTL 负载。我们根据PSEN 、ALE 和XTAL2输出端是否有信号输出,可以判别AT89C51是否在工作。
ALE/PROG(30脚):在访问片外程序存储器时,此端输出负脉冲作为存储器读选通信号。CPU 在向片外存储器取指令期间,PSEN 信号在12个时钟周期中两次生效。不过,在访问片外数据存储器时,这两次有效PSEN 信号不出现。PSEN 端同样可驱动8个LSTTL 负载。我们根据PSEN 、ALE 和XTAL2输出端是否有信号输出,可以判别AT89C51是否在工作。
EA/VPP(31脚): 当EA 端输入高电平时,CPU 从片内程序存储器地址0000H 单元开始执行程序。当地址超出4KB 时,将自动执行片外程序存储器的程序。当EA 输入低电平时,CPU 仅访问片外程序存储器。在对AT89C51编程时,此引脚用于施加编程电压VPP 。
输入/输出引脚:
(1)P0.0—P0.7 (39脚—32脚)
(2)P1.0—P1.7 (1脚—8脚)
(3)P2.0—P2.7 (26脚—21脚)
(4)P3.0—P3.7 (10脚—17脚)
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL 门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH 编程时,P0 口作为原码输入口,当FIASH 进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL 门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH 编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL 门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH 编程和校验时接收高八位地址信号和控制信号。
P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL 门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL )这是由于上拉的缘故。P3口也可作为AT89C51的一些特殊功能口,如下表所示:
表1 P3口特殊功能
3.3 时钟电路DS1302
DS1302的性能特性:
● 实时时钟,可对秒、分、时、日、周、月以及带闰年补偿的年进行比较;
● 用于高速数据暂存的31*8位RAM ;
● 最少引脚的串行I/O;
● 2.5~5.5V 电压工作范围;
● 2.5V 时耗小于300nA ;
● 用于时钟或RAM 数据读/写的单字节或多字节(脉冲方式)数据传送方式;
● 简单的三线接口;
● 可选的慢速充电(至Vcc1)的能力。
图5 DS1302电路图
DS1302在任何数据传送时必须先初始化,把RST 脚置为高电平,然后把8位地址和命令字装入移位寄存器,数据在SCLK 的上升沿被访问到。在开始8个时钟周期,把命令字节装入移位寄存器后,另外的时钟周期在读操作时输出数据,在写操作时写入数据。时钟脉冲的个数在单字节方式下为8+8,在多字节方式下为8+字节数,最大可达248字节数。如果在传送过程中置RST 脚为低电平,则会终止本次数据传送,并且I/O引脚变为高阻态。上电运行时,在Vcc≥2.5V之前,RST 脚必须保持低电平。只有在SCLK 为低电平时,才能将RST 置为高电平。
DS1302的控制字如表所示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。位6如果为0,则表示存取日历时钟数据;为1则表示存取RAM 数据。位5~1(A4~A0)指示操作单元的地址。最低有效位(位0
)如果为
0,则表示药进行写操作;为1表示进行读操作。控制字节总是从最低位开始输入/输出。
为了提高对32个地址寻址能力(地址/命令位1~5=逻辑1), 可以把时钟/日历或RAM 寄存器规定为多字节(burst )方式。位6规定时钟或RAM ,而位0规定读或写。在时钟/日历寄存器中的地址9~31或RAM 寄存器中的地址31不能存储数据。在多字节方式下,读或写从地址0的位0开始。必须按数据传送的次序写最先的8个寄存器。但是,当以多字节方式写RAM 时,为了传送数据不必写所有的31字节,不管是否谢了全部31字节,所写的每一字节都将传送至RAM 。
表2 DS1302控制字
DS1302共有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD 码形式。其日历、时间寄存器及其控制字如上表所示,其中奇数为读操作,偶数为写操作。
时钟暂停:秒寄存器的位7定义位时钟暂停位。当它为1时,DS1302停止振荡,进入低功耗的备份方式,通常在对DS1302进行写操作时(如进入时钟调整程序), 停止振荡。当它为0时,时钟将开始启动。
AM-PM/12-24小时方式:小时寄存器的位7定义为12或24小时方式选择位。它为高电平时,选择12小时方式。在此方式下,位5为第二个10小时位(20~23h )。
DS1302的晶振选用32768Hz ,电容推荐值为6pF 。因为振荡频率较低,也可以不接电容,对计时精度影响不大。
3.4 时钟电路及复位电路
根据设计要求和计算简便的原则,我们选择12M 的石英晶振、30PF 的陶瓷电容、22uF 的瓷片电容、10k 电阻、+5V电源,时钟电路及复位电路图如下:
图6 时钟电路及复位电路图
3.5 驱动电路
51单片机的输出能力有限,再加上数码管采用动态扫描方式,所以需要驱动电路驱动数码管。考虑到数码管是动态扫描的方式,驱动电路采用38译码器进行驱动,而非往日的三极管驱动,这样大大简化了电路的复杂性,同时还节约了单片机的I/O口,节约了单片机的资源。
图7 驱动电路图
3.6 显示电路
显示电路采用2个位为共阴数码管进行显示。数码管的位权与单片机的P0口相接,段权分别与38译码器的输出相接,只要P0输出为高,相应的数码管就会点亮,显示出相应的数字。
图8 显示电路
3.7 按键接口
按键开关在电路中的连接如图所示。按键未按下时,A 点电位为高电平5V ;按键按下时,A 点电位为低电平。A 点电位就用于向CPU 传递按键的开关状态。但是由于按键的结构为机械弹性开关,在按键按下和断开时,触点在闭合和断开瞬间还会接触不稳定,引起A 点电平不稳定,如图5)b 所示,键盘的抖动时间一般为5~10ms ,抖动现象会引起CPU 对一次键操作进行多次处理,从而可能产生错误。因此必须设法消除抖动的不良后果。
图9 键操作和键抖动
为了节省硬件,通常在单片机系统中,一般不采用硬件方法消除键的抖动,而是用软件消除抖动的方法。根据抖动特性,在第一次检测到按键按下后,执行一段延时5~10ms让前延抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认真正有键按下。当检测到按键释放后,也要给5~10ms的延时,待后延抖动消失后才转入该键处理程序。
图10 按键电路
4 软件系统设计
4.1 时间信息获取程序
通过单片机不断地读取DS1302的时,分,秒,年,月,日寄存器(81H 、83H 、85H 、87H 、89H 、8DH )获取时间信息。
4.2 显示程序
将单片机从DS1302寄存器中读取的数据送至单片机的P0口,再通过单片机的P2口选通相对应的的数码管,采用动态扫描方式显示时分秒年月日。
5 系统调试
5.1 系统调试
首先,硬件调试主要是先搭建硬件平台,然后利用万用表等工具对电路检测,最后用程序进行功能调试,硬件调试比较费时,需要细心和耐心也需要熟练掌握电路原理。
然后,可以直接应用编辑或仿真软件进行调试,比如单片机C51编辑软件Keil. 该软件提供了一个集成开发环境uVision ,它包括C 编辑、宏编辑、连接器、库管理和一个功能强大的仿真调试器。通过编译。运行,可以检查程序错误。但使用此方法,仍需要十分了解所使用元器件的工作方式和管脚连接方式。软件调试过程中要仔细耐心,即便是要多写一两个字符,都无法编译成功。而有时往往在Keil 中编译。运行无错,但烧录到单片机中运行出错,很有可能是编程时管脚或时序编辑得不对。
还有一种方式,即应用仿真软件搭建电路的软件平台,再导入程序进行仿真调试,如果电路出错,可以在计算机上方便的修改电路,程序出错可以重新编辑程序,这种方法节时、省力、经济、方便。我们这里应用的是Protuse7.5. 总之,调试过程是一个软硬件结合调试的过程,硬件电路是基础,软件是检测硬件电路和实现其功能的关键。
5.2 时钟显示
我们首先进行时钟信号测试、多个LED 数码管显示的的调试,以实现基本功能,看看在把程序导进去是否有线路没有接通或虚焊的现象出现。
在这个过程中,我们主要让数码管上有数字显示出来,具体是什么数这就不用关了。
5.3 DS1302的调试
该电路含DS1302芯片、主电源、备用电源、晶振等部分。在与单片机连接的过程中需要注意以下几点:
1)、清楚DS1302与单片机连接的管脚。本设计定义为:DS1302的SCLK 连接P3.1,I/O口连接P3.2,RST 口连接P3.0。
2)、注意电源正负极连接。
3)、DS1302连接32.768KHz 的晶振。该晶振体形比较小,在焊接是要小心的,注意不要将晶振引脚弄断。同时也要尽量使晶振离DS1302的X1、X2引脚近距离焊接。
4)、编写DS1302的时钟/日历程序,只要能够正确显示时间。烧录进单片机,检查电路电源正负极连接是否正确。检查无误后再上电检查。
5.4 按键电路调试
按键电路比较简单,故而调试起来也比较容易,只需要保证按键焊接正确,没有虚焊或忘焊的现象出现一般不会出很大的问题。
6 总结
通过课程设计,我学到了不少的知识。把以前没有学好的模拟电路的知识进行了补充和加强。这使我受益很大。加深了我对于单片机和数字电路的认识,相信在以后的学习和工作中碰到这些基础的元器件我会更加得心应手。通过查阅大量的资料,我获得了以前在课堂上学不到的东西,我想这对于以后的毕业设计,或者工作也好,都是很有帮助的。我很认真地对待这个过程中的每一个细节,希望自己能做得更好。希望今后还有这样的机会,能够让我学到更多的知识。在此次的数字钟设计过程中, 更进一步地熟悉了芯片的结构及掌握了各芯片的工作原理和其具体的使用方法。
其次,巩固了Keil C51工程文件的建立,程序编写以及编译的掌握程度。最重要的是,因为只是水平有限,要自己编写C 程序很难,但在此实验中,最大的收获莫过于看懂别人的程序,分析之后,自己拼凑编写以实现不同的功能。并且掌握了程序的编写过程。掌握了Proteus 的使用方法,从实际操作中认识到Proteus 在仿真方面的优越性,激发了自己学习Proteus 的兴趣。因为自己要修改程序,所以单单花费在程序分析的时间就很多,为了更好的理解程序,我把每句主要程序的后面都注释了该语句的意思,详情可以见程序清单,发现注释语义的工作量也是非常大的。写实验报告时,每个模块的流程图都是自己画的,用WORD 文档画图真的很麻烦,而且不是很美观。因为时间比较仓促,流程图写的条理性不够,不过相信以后多多练习,就可以做得更好。
在这次实验中我遇到了很多故障,不过通过各种渠道(比如网络,请教同学,老师等等)解决了一些故障,虽然没有全部解决,但能在短短一周内通过此次作业,实现电子钟的功能,还是有点成就感的。在解决这些问题的过程中发现网络确实是一个很好的学习平台,利用前人的经验可以提高自己的解决实际问题的能力。通过这一个多礼拜的学习实践,使我对所学的知识进行了系统的复习和巩固,在以前学习中不够清晰的概念得到了更好的理解。相信通过不断的学习,能使自己扬长补短。
良好的学习态度,不怕困难、坚持不懈、吃苦耐劳的精神是我在这次设计中最大的收益。我想这是一次意志的磨练,是对我实际能力的一次提升,也会对我未来的学习和工作有很大的帮助。在这次毕业设计中也使我们的同学关系更进一步了,同学之间互相帮助,有什么不懂的大家在一起商量,听听不同的看法对我们更好的理解知识,所以在这里非常感谢帮助我的同学。
在此更要感谢我的指导老师和专业老师,是你们的细心指导和关怀,使我能够顺利的完成这次课程设计。在此我要向鞠老师致以最衷心的感谢和敬意。
参考文献
1. 刘迎春. 传感器原理. 国防工业出版社.2004年
2. 袁希光. 传感器技术手册. 国防工业出版社.1986年
3. 郑秀瑗. 应力应变电测技术. 国防工业出版社.1985年
4. 蔡春源. 新编机械设计手册. 辽宁科学技术出版社.1993年
5. 王森. 仪表常用数据手册. 化学工业出版社.1998年
6. 孙传友. 测控电路及装置. 北京航空航天大学出版社.2002年
7. 王俊杰. 检测技术与仪表. 武汉理工大学出版社. 2002年
8. 贾伯年,俞朴. 传感器技术. 南京:东南大学出版社,2000:33-62
9. 单成祥. 传感器理论设计基础及其应用. 北京:国防工业出版社,1999年
10. 李道华,李玲,朱艳. 传感器电路分析与设计. 武汉大学出版社,2000年
附录:系统程序
#include
sbit RST=P3^0;
sbit SCLK=P3^1;
sbit IO=P3^2;
sbit A0=ACC^0;
sbit A7=ACC^7;
sbit set=P3^3;
sbit jia=P3^4;
sbit jian=P3^5;
sbit led=P3^6;
sbit P37=P3^7;
#define uchar unsigned char
uchar miao,fen,shi,ri,yue,nian,zhou;
uchar flag;
uchar num,num1;
uchar code tim[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00};
/******************DS1302:写入操作(上升沿)*********************/
void write_byte(uchar da)
{ uchar i;
ACC=da;
for(i=8;i>0;i--)
{
IO=A0;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
}
/******************DS1302:写入数据(先送地址,再写数据)
***************************/
void write_1302(uchar addr,uchar da)
{
RST=0; //停止工作
SCLK=0;
RST=1; //重新工作
write_byte(addr); //写入地址
write_byte(da);
SCLK=1;
RST=0;
}
/******************DS1302:读取操作(下降沿)*****************/
uchar read_byte(void)
{
uchar i;
for(i=0;i
{
ACC=ACC>>1;
A7=IO;
SCLK=1;
SCLK=0;
}
return(ACC);
}
/******************DS1302:读取数据(先送地址,再读数据)
**************************/
uchar read_1302(uchar addr)
{
uchar temp;
RST=0; //停止工作只有将秒寄存器的该位置改写为0时,时钟才能开始运行。
SCLK=0;
RST=1; //重新工作
write_byte(addr); //写入地址
temp=read_byte();
SCLK=1;
RST=0;//停止工作
return(temp);
}
/***********************延时程序=a*1ms**************************************/ void delay(unsigned char a)
{
unsigned char i;
while(a--!=0)
{
for(i=0;i
}
}
/***********************显示**************************************/
void disp_yu(uchar shu)
{
P0=tim[shu%16];
delay(1);
P0=0x00;
}
void disp_zhe(uchar shu)
{
P0=tim[shu/16];
delay(1);
P0=0x00;
}
void disp_off()
{
P0=0;
delay(1);
P0=0x00;
}
void disp_k()
{
P0=0x40;
delay(1);
}
void disp(uchar miao,fen,shi,ri,yue,nian,zhou)
{
P2=0xb8;
if((num%2==1)&&(flag==8))
disp_off();
else
disp_yu(miao);
P2=0xb0;
if((num%2==1)&&(flag==8))
disp_off();
else
disp_zhe(miao);
P2=0xa8;
disp_k();
P2=0xa0;
if((num%2==1)&&(flag==1))
disp_off();
else
disp_yu(fen);
P2=0x98;
if((num%2==1)&&(flag==1))
disp_off();
else
disp_zhe(fen);
P2=0x90;
disp_k();
P2=0x88;
if((num%2==1)&&(flag==2))
disp_off();
else
disp_yu(shi);
P2=0x80;
if((num%2==1)&&(flag==2))
disp_off();
else
disp_zhe(shi);
P2=0x47;
if((num%2==1)&&(flag==3))
disp_off();
else
disp_yu(ri);
P2=0x46;
if((num%2==1)&&(flag==3))
disp_off();
else
disp_zhe(ri);
P2=0x45;
disp_k();
P2=0x44;
if((num%2==1)&&(flag==4))
disp_off();
else
disp_yu(yue);
P2=0x43;
if((num%2==1)&&(flag==4))
disp_off();
else
disp_zhe(yue);
P2=0x42;
disp_k();
P2=0x41;
if((num%2==1)&&(flag==5))
disp_off();
else
disp_yu(nian);
P2=0x40;
if((num%2==1)&&(flag==5))
disp_off();
else
disp_zhe(nian);
if((num%2==1)&&(flag==6))
P37=1;
else
P37=0;
P1=tim[zhou];
}
//******************调时***************************
void set_t()
{ char address,item;
uchar max,mini;
if(flag!=0)
{
TR0=1;led=1;
write_1302(0x8e,0x00);
write_1302(0x80,0x80);
}
if(flag==1) {address=0x82; max=59;mini=0;} //分钟6
if(flag==2) {address=0x84; max=23;mini=0;} //小时5
if(flag==6) {address=0x8a; max=7; mini=1;} //星期4
if(flag==3) {address=0x86; max=31;mini=1;} //日3
if(flag==4) {address=0x88; max=12;mini=1;} //月2
if(flag==5) {address=0x8c; max=99;mini=0;} //年1
//读取1302某地址上的数值转换成10进制赋给item
item=((read_1302(address+1))/16)*10 + (read_1302(address+1))%16; if(jia == 0){
while(!jia) disp(miao,fen,shi,ri,yue,nian,zhou);
item++;//数加 1
}
if(jian == 0){
while(!jian) disp(miao,fen,shi,ri,yue,nian,zhou);
item--;//数减 1
}
if(item>max) item=mini;//查看数值有效范围
if(item
write_1302(0x8e,0x00);//允许写操作
write_1302(address,(item/10)*16+item%10);//转换成16进制写入1302 write_1302(0x8e,0x80);//写保护,禁止写操作
}
//**********************定时器**********************
void TIM0() interrupt 1
{
num1++;
TH0=(65536-25000)/256;
TL0=(65536-25000)%256;
if(num1==15)
{ num++;
num1=0;}
}
/***********************主函数**************************************/ void main()
{
uchar clk_cs[7]={0x00,0x00,0x16,0x28,0x02,0x01,0x11};
uchar addr,j;
addr=0x80; //位置有疑问
led=0;jia=1;jian=1;
num=0;
flag=0;
set=1;
write_1302(0x8e,0x00); //WP=0 写操作
for(j=0;j
{
write_1302(addr,clk_cs[j]);
addr+=2;
}
write_1302(0x8e,0x80); //W=1写保护
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
while(1)
{
miao=read_1302(0x81);
fen=read_1302(0x83);
shi=read_1302(0x85);
ri=read_1302(0x87);
yue=read_1302(0x89);
nian=read_1302(0x8d);
zhou=read_1302(0x8b);
disp(miao,fen,shi,ri,yue,nian,zhou);
if(set==0)
delay(1);
if(set==0)
{ while(!set);flag++;if(flag==7){flag=0; write_1302(0x80,miao); write_1302(0x80,0x00);
write_1302(0x8e,0x80);led=0;}}
if(flag!=0)
set_t();
} }