专 科 毕 业 设 计(论文)
题目 基于51单片机的可调数码日历钟的设计与制作
院(系部) 电子与信息工程系 专业名称 电子信息技术 年级班级 学生姓名 指导教师
摘 要
单片机以其体积小、编程灵活、控制功能强大、价格低廉等特点被广泛应用在各种电子电器产品中。单片机技术的出现和发展带来了电子技术和控制领域的一场革命。
单片机课程作为职业院校电子信息类专业一门重要的基础课程,它既是一门很有实用价值、实践性很强且很有趣味性的课程,同时它又是一门集硬件电路设计与软件编程于一体的学科,既要求我们有较好的电工电子技术基础知识,又要求有一定的逻辑思维和软件开发(编程)能力。通过近几年对单片机的学习,我已掌握单片机的基本知识,并具备了单片机应用系统的初步开发能力。即将毕业之际,我运用我所掌握的单片机知识设计和制作了一个基于51单片机的可调数码日历钟,这既是对我所学知识的总结与高度概括,同时也将自己所掌握的知识与实际应用结合起来,进一步提高工程实践能力。
数码日历钟是实际生活中应用较多的一个电子计时装置,可供人们查询日期、星期及掌握时间。本文首先从数码日历钟的功能要求入手,对设计任务进行了分析,并将任务分解为若干个模块,提出在设计与制作过程中要用到的相关知识点,给出了本设计的硬件电路及软件流程,还给出了部分模块的源程序代码。本设计经过多次调试运行无误,最终提交出一个完整的应用系统产品。
本次毕业设计的数码日历钟能在12864液晶屏上显示出年月日时分秒以及星期几,还能显示当前环境温度,并能通过按键调整日期和时间,在调整日期的同时通过相应算法自动实现星期几的调整,而且无论是否闰年、任何月份,当日期调整时都保证不会出现非法日期。数码日历钟是一个非常实用的设计与制作,成本低廉,如能进一步完善,具有一定的推广使用价值。
本设计任务比较复杂,要考虑的问题很多,C语言的模块化程序设计思想较好地解决了这个问题,故本设计任务采用C语言编程。
关键词:51单片机,C语言,数码日历钟,毕业设计,制作
I
河南理工大学毕业设计论文
目 录
摘要 .............................................................. Ⅰ 1概述.............................................................. 1 1.1 毕业设计的选题背景及制作意义 ................................. 1 1.1.1毕业设计的选题背景 ........................................ 1 1.1.2毕业设计的制作意义 ........................................ 1 1.2 数码日历钟的功能要求 ......................................... 1 1.3 本设计制作的主要内容 ......................................... 2 2数码日历钟的设计与制作任务分析 ................................... 3 2.1数码日历钟的设计与制作任务分析与分解.......................... 3 2.2设计方案的论证及选择 .......................................... 3 3 相关知识链接 ..................................................... 6 3.1 51单片机简介 ................................................. 6 3.1.1 51单片机简介 ............................................. 6 3.1.2 51单片机引脚功能介绍 ..................................... 8 3.2由已知日期推算星期几 ......................................... 11 3.2.1如何判断一个年份是否闰年 ................................. 11 3.2.2由已知日期如何推算星期几 ................................. 11 3.3 12864图形液晶的使用 ......................................... 13 3.3.1 液晶概述 ................................................ 13 3.3.2 LCM引脚功能介绍 ......................................... 14 3.3.3 LCD12864图形液晶显示模块指令集 .......................... 15 3.3.4 LCD12864图形液晶显示模块与单片机的接口 .................. 17 3.3.5 LCD12864图形液晶显示模块的基础函数 ...................... 17 3.4 51单片机中的中断与定时 ...................................... 19 3.4.1 51单片机中的中断 ........................................ 19 3.4.2 51单片机中的定时/计数器 ................................. 22 3.5数字温度传感器DS18B20的使用................................. 28 3.5.1 DS18B20概述 ............................................. 28 3.5.2 DS18B20的内部结构 ....................................... 29 3.5.3 DS18B20与单片机的接口电路 ............................... 32 3.5.4 DS18B20的操作命令 ....................................... 32
-1-
3.5.5 DS18B20的时序 .......................................... 33 3.6 矩阵式按键的检测 ............................................ 36 4系统设计与调试 .................................................. 44 4.1 硬件系统设计与调试 ......................................... 44 4.1.1硬件系统设计原理图 ...................................... 44 4.1.2硬件系统元器件清单 ...................................... 44 4.1.3硬件系统组装与调试 ...................................... 45 4.2 软件系统设计与调试 ......................................... 45 4.2.1软件系统设计 ............................................ 45 4.2.2软件系统调试与仿真 ...................................... 47 5结束语 .......................................................... 49 参考文献 .......................................................... 50 致 谢 .......................................................... 51
-2-
河南理工大学毕业设计论文 1 概述
1、 概述
1.1 毕业设计的选题背景及制作意义
1.1.1毕业设计的选题背景
单片机以其体积小、编程灵活、控制功能强大、价格低廉等特点被广泛地应用在各种电子电器产品中。单片机技术的出现和发展带来了电子技术和控制领域的一场革命。
单片机课程作为职业院校电子信息类专业一门重要的基础课程,它既是一门很有实用价值、实践性很强且很有趣味性的课程,同时它又是一门集硬件电路设计与软件编程于一体的学科,既要求我们有较好的电工电子技术基础知识,又要求有一定的逻辑思维和软件开发(编程)能力。通过近几年对单片机的学习,我已掌握单片机的基本知识,并具备了单片机应用系统的初步开发能力。即将毕业之际,为了将自己所掌握的知识与实际应用结合起来,进一步提高工程实践能力,同时也对自己所学知识作以总结及高度概括向老师汇报,我决定将我的毕业设计课题选作基于51单片机的可调数码日历钟的设计与制作,并以此向老师作毕业汇报。
1.1.2毕业设计的制作意义
数码日历钟是实际生活中应用较多的一个电子计时产品,广泛地应用在酒店、宾馆、车站、家庭及办公室中,可供人们查询日期、星期,掌握当前时间及环境温度。
在上述背景下,需要我运用近几年在学校学到的单片机知识及开发技巧设计和制作出一个功能完善的可调数码日历钟。通过这个设计的制作,必将进一步提高我的工程实践能力和单片机应用系统开发能力,将我所学到的理论知识与实际应用结合起来,做到理论与实践相结合,同时也能对我高职阶段所学知识作以梳理和总结。这是一个非常实用的设计与制作,成本低廉,若将它稍加改进安装在镜框或其它工艺品中,则更加实用。如能进一步完善其功能,具有一定的实际推广使用价值。
1.2数码日历钟的功能要求
本设计制作出来的数码日历钟要求能在12864液晶显示屏上显示出年月日及对应的星期几,当前时间及环境。而且要求日期和时间可通过按键调整,当日期调整时,通过相应算法自动实现星期几的调整,无论是否闰年、任何月份,当日
-1-
1 概述 河南理工大学毕业设计论文
期调整时都保证不会出现非法的日期。本设计制作出来的数码日历钟显示如图1-1所示。
图1-1 毕业设计作品——数码日历钟的显示效果图
1.3 本设计制作的主要内容
本设计制作需要完成的主要内容有: (1)对设计与制作任务进行分析、分解;
(2)对设计与制作方案进行可行性论证,选择一种较为现实可行的方案; (3)根据所选方案列出所需硬件元器件、制作与调试工具(软硬件)清单; (4)准备制作与调试工具(软硬件),照单购买所需元器件并进行逐一测试,保证完好;
(5)根据所选方案,画出硬件电路原理图;
(6)逐一完成每个软件模块的编写与调试,最终编译生成目标程序; (7)整机联调。在Proteus中进行软件仿真,直至实现所有预先设定的功能要求。
(8)根据硬件电路原理图搭建电路,并进行电路焊接;
(9)对硬件电路进行测试与调试,保证无虚焊、短路等故障,将目标程序写入单片机,再次整机联调(实物);
(10)完成毕业设计论文的撰写,提交完整的毕业设计作品,由指导老师审阅,完成毕业设计论文答辩。
-2-
河南理工大学毕业设计论文 2 数码日历钟的设计与制作任务分析
2、 数码日历钟的设计与制作任务分析
2.1 数码日历钟的设计与制作任务的分析与分解
本设计任务比较复杂,要考虑的问题很多,故需对设计与制作任务进行分析和分解,使分解后的每一个子任务都在能够容易解决的范围之内。为此,通过对本设计任务的分析,将其按硬件和软件两个方面各分解为几个模块。它们分别是:
(1) 硬件
①根据所选方案画出硬件电路原理图;
②根据所选方案,列出所需硬件元器件、制作与调试工具清单(软硬件); ③准备制作与调试工具(软硬件);
④照单购买所需元器件并进行逐一测试,保证完好; ⑤根据硬件电路原理图搭建电路,并进行电路焊接; ⑥对硬件电路进行测试与调试,保证无虚焊、短路等故障; (2) 软件
①12864液晶的显示,编写12864液晶的基础显示函数; ②根据已知日期推算出相应的星期几;
③利用实时时钟芯片DS1302提供日期和时间,从而实现电子钟功能; ④编写按键扫描程序,能够识别按键,并通过相应的按键调整年份、月份、日期、时、分;
⑤数字温度传感器18B20的使用; ⑥所测温度结果数据的处理及显示。
2.2设计方案的论证及选择
(1) 硬件方面: 主控模块:
单片机芯片的选择:考虑到本程序较为复杂,目标程序可能占用存储空间较大,故应选择程序存储器容量稍大一些的单片机芯片较好,但又要顾及尽量降低成本,程序开发、调试、载入方便。综合考虑,决定选用目前占有较大市场份额、技术成熟、资料丰富的Atmel公司生产的AT89S52单片机。
晶振的选择:由于本设计中读取时间和温度的时刻由定时/计数器控制,为便于计算定时/计数器的初值和定时时长,故采用稳定性较高的、固有振荡频率为12MHz的石英晶体振荡器。
显示模块:
-3-
2 数码日历钟的设计与制作任务分析 河南理工大学毕业设计论文
显示模块既可采用数码管显示,也可采用液晶显示。数码管的优点是价格便宜,显示亮度高,但它也有不少不足之处:当显示的信息量较大时,所用数码管较多,接口电路复杂,编程麻烦;而且其体积较大,不宜用于便携式产品,显示也不够美观;当其中某一段出现劣化而不能正常显示时,需整体更换。图形液晶显示模块的优点是价格适中,与单片机的接口电路简单,便于编程控制其显示,体积小、质量轻、功耗低(功率为10mW,5V电源供电、工作电流只有2mA)、寿命长、可靠性高、显示操作简单,显示美观,且显示的信息量大,特别适合用于便携式电子产品中作显示器件。故本设计中的显示模块决定采用12864点阵图形液晶显示器。
实时时钟模块:
我们固然可以利用单片机本身自带的定时/计数器提供秒信号实现电子日历钟,但这过于消耗单片机资源,且由于中断响应影响到时钟的精度,而且一旦主机掉电后重新启动时系统的时间日期必将再次初始化,每次上电后必须重新调整日期和时间初始值。本设计决定采用美国Dallas半导体公司的DS1302实时时钟芯片实现日历钟功能。DS1302可以在主机掉电后由后备电源为其供电,从而保证日期和时间在主机掉电后依旧保持运行,不需每次上电调整。而且DS1302还提供了为后备电源涓流充电的功能。DS1302自身还有31个字节的RAM空间,可以存储其他数据,从而为系统功能进一步拓展提供了空间。
温度测量模块:
温度测量模块当然可以采用较为简单的热敏电阻,其阻值会随着周围环境温度的变化而变化。热敏电阻的优点是电路及其工作原理都较为简单,但其测量结果为模拟量,要让单片机去处理其测量结果,需通过ADC(模数转换器)电路,这样又增加了不少成本,且需熟悉ADC与单片机的接口电路及其编程,这就增加了开发的难度和时间,比较麻烦。当然也可采用模拟温度传感器,如LM35,它测得的结果同样是模拟量,也需通过A/D转换,单片机才能处理,既提高了开发成本,又增加了开发难度,故本设计放弃采用以上这两种方案,决定采用DALLAS 公司的“一线式”接口的数字化温度传感器DS18B20。相比热敏电阻,该传感器的优点是可谓多多:首先,它与单片机的接口非常简单,只需一根线即可实现和单片机之间的数据传输。测温范围为-55℃~+125℃,固有测温分辨率0.5℃。具有耐磨耐碰,体积小,工作电源: 3~5V/DC。非常适合要求。
按键调整控制模块:
为了便于用户识记各按键的功能,本设计中只用3个按键来实现对日期和时间的调整。由于所用按键数目较少,为便于编程,按键采用独立式按键的接法,独立式按键接口电路简单,编程方便。
硬件系统的组成框图如图2-1所示:
-4-
河南理工大学毕业设计论文 2 数码日历钟的设计与制作任务分析
图2-1 数码日历钟硬件系统组成框图
(2) 软件方面: 编程语言选择:
考虑到本设计任务较为复杂,C语言的模块化程序设计思想能够较好地解决这个问题,且用C语言编写程序,开发效率高,生成的目标代码质量也较高,执行效率高,综上所述,故本设计任务采用C语言编程。
编译环境软件选择:
本设计选用目前单片机应用系统开发使用最泛的集成开发编译软件——Keil公司的Keil C,它既可用于汇编程言源程序的编辑、编译,生成目标程序,也可用于C语言源程序的编辑、编译、连接并生成目标代码。
仿真软件选择:
在焊接硬件电路之前,为避免不必要的麻烦,要对本设计系统进行软件仿真,直到仿真运行无误后,再焊接元器件,搭建本设计硬件电路。本设计选用目前单片机应用系统仿真中最受欢迎的一款软件——英国Labcenter Electronics公司开发的电子电路设计与仿真软件——Proteus。它包括ISIS\\ARES等软件模块,ARES模块主要用来完成PCB的设计,而ISIS模块用来完成电路原理图的制图与仿真。Proteus 的软件仿真基于VSM技术,它与其他软件最大的不同也是最大的优势就在于它能仿真大量的单片机芯片以及单片机外围电路,例如键盘、LED、LCD等等。通过Proteus软件的使用,我们能够轻易地获得一个功能齐全、实用方便的单片机实验室。
Proteus软件有十多年的历史,在全球广泛使用,除了具有和其它EDA工具一样的原理图制图、PCB自动或人工布线及电路仿真的功能外,其革命性的功能在于其电路仿真是互动的,针对微处理器的应用,还可以直接在基于原理图的虚拟原型上编程,并实现软件源码级别的实时调试,如果显示及输出,还能看到运行后输入输出的效果,此外系统还配置有丰富的虚拟仪器,如示波器、逻辑分析仪等。
-5-
3 相关知识链接 河南理工大学毕业设计论文
3、 相关知识链接
3.1 51单片机简介
3.1.1 51单片机简介
单片机就是将中央处理器(CPU)、存储器(包括程序存储器ROM和数据存储器RAM)、I/O接口电路、定时/计数器、中断系统和时钟电路等计算机基本部件集成在一块芯片上,具有独特功能的单片微型计算机(Single Chip Microcomputer,简写为SCM)。由于其体积小,主要应用在控制领域,所以又被称为微控制器(Micro Controller Unit,简写为MCU)。
单片机出现的历史并不长,其前身起源于上世纪70年代研制成功的微处理器(利用大规模集成电路制造技术将计算机的运算器和控制器集成为一体)。作为一门非常有前途的计算机技术,单片机一经出现就迅速发展起来。一路走来,单片机的性能在不断提高,存储容量也在不断增大,而体积、价格、功耗却在不断降低。由于其体积小、控制功能强大、编程灵活、价格低廉,所以在控制领域得到了广泛的应用。可以说,凡是与控制或简单计算有关的场合,都可以用单片机来实现。目前,单片机已得到了大力推广和广泛应用,从工业控制系统到日常工作和生活的方方面面,单片机的应用几乎无处不在。从形形色色的家用电器、电子玩具、数码产品,到各种医疗器械、智能仪器仪表、通信设备,大到航空航天、雷达、导弹等现代化武器装备,单片机的身影无处不在。复杂的工业控制系统中甚至有上百台单片机在同时工作。
单片机的应用从根本上改变了传统的控制系统的设计思想和设计方法,可以说,单片机技术的出现和发展给现代电子技术和控制领域带来了一场新的革命。以往由硬件电路实现的大部分控制功能现在都能够使用单片机通过软件方式来实现,这种以软件取代硬件并能够提高系统性能的微控制技术,随着单片机应用的推广普及,不断发展,日益完善。因此,学习单片机,掌握其应用和开发技术,也成为当今职业院校电子信息专业的学生必须具备的一项基本技能。
下面谈谈单片机的发展情况及其常用系列。
虽然单片机出现的历史并不长,至今也不到四十年的时间,但其发展却十分迅猛。
1976年,美国的Intel公司在8位微处理器的基础上首先研制成功了最早的单片机产品——MCS-48系列单片机,这是一种低档的8位单片机,但它以其体
-6-
河南理工大学毕业设计论文 3 相关知识链接
积小、功能全、价格低、容易嵌入到其他控制产品中等特点得到了广泛的应用。现在MCS-48系列单片机已经完全退出了历史舞台。20世纪80年代,Intel公司在总结MCS-48系列单片机的基础上推出了8位单片机的第二代产品——MCS-51系列单片机。虽然它仍然是8位单片机,但其功能有了很大的增强。其系列产品包括基本型8031/8051/8751/8951、80C31/80C51,增强型8032/8052,改进型8044/8344/8744等,其中80C31/80C51采用CHMOS工艺制造,功耗更低。上述单片机产品的内核均是8051内核,它们是高档的8位单片机。
由于Intel公司主要致力于计算机的CPU的研究和开发,所以该公司在推出MCS-51体系结构后不久,开放了8051内核技术,授权一些厂商以MCS-51系列单片机为核心生产各自的单片机,为单片机的发展起了很大作用。随后世界各大半导体公司依靠自己的优势,争相研究和开发单片机,发展了MCS-51单片机,创造了许多各具特色的单片机产品,成为事实上的8位单片机主流和经典。这些单片机统称MCS-51系列单片机,它们与MCS-51单片机兼容,又各具特点。
目前,全世界生产单片机的厂家不计其数,单片机的型号也五花八门。值得一提的是,本设计中所采用的AT89S52单片机是Atmel公司的产品,它拥有与MCS-51单片机同样的内核和引脚排列,它除了具有和MCS-51单片机的全部功能外,还内置了一些非常实用的功能。例如,它采用Flash ROM、支持ISP(在系统可编程)功能,可以反复快速擦写,因此程序写入和调试非常方便,使得我们在写入程序时不需再依靠传统的编程器,只需使用它所支持的专用ISP软件就可轻易将程序写入,它改变了单片机应用系统的结构模式和开发运行条件,此外它还增加了一些外部接口功能,内置有看门狗。AT89S52是目前占有较大市场份额、性能卓越的典型的51系列单片机。
AT89S52单片机的主要参数如下:
8KB在系统可编程Flash ROM存储器。 片内256B RAM存储器。 工作电源电压:4.0V~5.5V。 可重复擦写1000次。 时钟频率0Hz~33MHz。 加密结构:三级。
可编程并行I/O口:4×8位。
定时/计数器:3个16位可编程定时/计数器。 中断源:8个可编程中断源。 全双工UART串行通道。
具有低功耗空闲工作模式和掉电保持模式。 内置看门狗定时器和复位电路。 双数据指针。
-7-
3 相关知识链接 河南理工大学毕业设计论文
3.1.2 51单片机引脚功能介绍
单片机就是一块集成电路,在使用其之前,必须先了解其外部引脚功能。51单片机有多种封装方式,下面以DIP-40封装为例介绍其引脚功能。DIP-40封装的AT89S52单片机实物图如图3-1所示。
图3-1 DIP-40封装的AT89S52单片机实物图
由于受到集成电路芯片引脚数目的限制,许多引脚具有双重功能。AT89S52单片机的引脚排列如图3-2所示。按其功能类别来划分,这40个引脚可分为以下四类:电源引脚、时钟引脚、I/O接口引脚、编程控制引脚。各引脚功能介绍如下。
(1) 电源引脚Vcc和GND
集成电路都需要电源供电才能正常工作,单片机也不例外。采用DIP-40封装的AT89S52单片机的第40脚Vcc为电源正极输入端,一般接+5V,第20脚GND为电源负极输入端,接电源负极,也作为电路中的公共接地端。
图3-2 DIP-40封装的AT89S52单片机外部引脚图
(2) 时钟引脚XTAL1和XTAL2
第19脚XTAL1为片内振荡电路输入端,第18脚XTAL2为片内振荡电路输出端。在使用片内时钟发生电路时,这两个引脚用于外接石英晶体和振荡电容(取值一般为10p~30p),此时晶振频率即为时钟振荡频率;在使用片外时钟电路时,这两个引脚用于外接外部时钟源。需要说明的是:本设计采用单片机内部时钟振荡电路,所以这两个引脚外接石英晶体和振荡电容。为便于计算定时器的初始值及定时时间,晶振频率为12MHz。
-8-
河南理工大学毕业设计论文 3 相关知识链接
(3) 并行I/O接口引脚
AT89S52单片机共有4个8位并行I/O口,分别为P0、P1、P2、P3(字母P为英文单词Port(意为“端口”)的第一个字母),每个I/O口均有8位,分别表示成Pm.n的形式(m=0,1,2,3;n=0,1,2,3,4,5,6,7),在用C语言写程序时则应写成Pm^n的形式。
P0口(第39~30脚,其中第39脚为P0.0,即最低位,第32脚为P0.7,即最高位,其余依此递推)为8位双向三态I/O口。值得注意的是,P0口内部没有上拉电阻,不能正常输出高电平,因此P0口在作为通用I/O口作基本输入输出使用时必须外接上拉电阻,否则应输出高电平时为高阻态,无法正常输出高电平。上拉电阻阻值一般取10K。P0口除了作为I/O口使用外,在系统扩展时还作为低8位地址总线和数据总线分时复用。本设计中的12864液晶显示器的数据总线就是与P0口连接的,已外接上拉电阻。
P1口(第1~8脚,其中第1脚为P1.0,即最低位,第8脚为P1.7,即最高位,其余递推)为8位准双向并行I/O口。P1口内部已接有上拉电阻,故在使用时无需再接上拉电阻。P1口功能较为简单,仅作基本I/O口使用,没有第二功能。本设计中用P1口作为矩阵式按键接口使用。
P2口(第21~28脚,其中第21脚为P2.0,即最低位,第28脚为P2.7,即最高位,其余递推)为8位准双向并行I/O口。P2口内部也已接有上拉电阻,故在使用时无需再接上拉电阻。P2口除了作为I/O口使用外,在系统扩展时还作为高8位地址总线使用。
P3口(第10~17脚,其中第10脚为P3.0,即最低位,第17脚为P3.7,即最高位,其余递推)作为第一功能使用时为普通的8位并行I/O口,在使用时也无需再接上拉电阻。需要强调的是:P3口的每个引脚又各自具有非常重要的第二功能。P3口的每个引脚的第二功能如表3-1所示。
表3-1 AT89S52单片机P3口的第二功能 引脚名称 P3.0 P3.1 P3.2 P3.3 P3.4 P3.5 P3.6 P3.7 第二功能 RXD TXD 功能描述 串行数据输入 串行数据输出 外部中断0中断请求输入 外部中断1中断请求输入 定时/计数器0外部时钟输入 定时/计数器1外部时钟输入 外部RAM写选通信号 外部RAM读选通信号 INT0 INT1 T0 T1 WR RD -9-
3 相关知识链接 河南理工大学毕业设计论文
注意:P3口每个引脚各自具有的第二功能都是比较重要的控制信号,在实际应用中应优先满足第二功能使用需要,然后再用剩余的口线作为数据的输入和输出使用。由于本设计中不涉及到P3口第二功能的使用,故不再对P3口的第二功能作详细介绍。
以上四个I/O口既可字节操作(8位同时并行输入输出),亦可位操作(即每根口线均可独立控制)
(4) 编程控制引脚
第9脚RST/Vpd为复位信号输入端。当RST端保持两个机器周期以上的高电平时即可使单片机进入复位状态,完成一系列初始化操作。单片机复位时,使片内各特殊功能寄存器的内容复位到初始状态,程序计数器PC的值归零,即指向ROM的第一个单元。复位操作还使4个并行I/O口的每根口线都置为高电平状态。除作为复位信号输入外,该引脚也具有不太常用的第二功能,即作为片内RAM的备用电源输入端。一旦电源断电或者电压降到一定值时,可通过该引脚为片内RAM供电,以保护片内RAM中的数据不丢失,且上电后能够继续工作。
第29脚PSEN为外部ROM的读选通信号,当访问片外扩展ROM时,只有该引脚为低电平有效信号,才能选通片外程序存储器对其进行读操作。本设计中无外接扩展ROM,不涉及对该引脚的使用,故悬空。
第30脚ALE/PROG为地址锁存使能/片内ROM编程脉冲信号输入端。在单片机扩展外部存储器时,该引脚作第一功能使用,用于控制把P0口提供的低8位地址送锁存器锁存起来,以实现低8位地址和数据的隔离。在没有访问外部存储器时,该引脚以时钟周期频率的6分频固定频率输出,因此可作为外部时钟,或可作为外部定时脉冲使用。该引脚的第二功能PROG为片内ROM的编程脉冲输入端。这是为兼容以往的低版本单片机而设置的。以往低版本单片机的片内ROM要靠编程脉冲才能将程序写入,而AT89S52支持ISP功能,无需编程脉冲输入。本设计中既没有扩展外部存储器,往片内ROM写入程序时也无需编程脉冲输入,故不涉及该引脚的使用,故闲置。
第31脚EA/Vpp具有双重功能。其第一功能为访问片内、片外ROM的控制信号,当该引脚接低电平时,CPU对ROM的访问限定在片外ROM(对于片内没有ROM的单片机,如8031,CPU只能访问片外ROM,则该引脚一直是接低电平的);当该引脚接高电平时,CPU对ROM的访问方式为,如果地址不超过片内ROM的存储单元范围,则访问片内ROM(低端地址),当地址信号所标志的存储单元超出片内ROM范围时(高端地址),则自动延伸至片外ROM(即只能访问片外ROM的高端存储单元)。该引脚的第二功能Vpp用于对片内含有EPROM的单片机(如8751),对其内部EPROM写入程序时作编程电压输入端。本设计中采用的AT89S52单片机片内含有8KB Flash ROM,其存储容量已能满足需求,无需扩展片外ROM,
-10-
河南理工大学毕业设计论文 3 相关知识链接
且AT89S52单片机支持ISP(在系统可编程)功能,无需编程电压输入,故此引脚直接接高电平(与第40脚电源正极相连),仅限于对片内程序存储器的访问。
3.2 由已知日期推算星期几
3.2.1如何判断一个年份是否是闰年
数码日历钟显示的年份如果是闰年,则2月为29天,否则为28天。在本设计任务中,无论是日期的调整,还是星期几的推算,都涉及到闰年的判断。查阅相关资料可知,如果一个年份是闰年,则该年份必然满足以下两个条件其中之一:
(1) 年份是4的整数倍但不是100的整数倍; (2) 年份是400的整数倍。
只要年份能满足以上两个条件其中之一,便可判定是闰年,否则不是闰年。于是,不难写出判断一个年份是否闰年的函数如下:
bit leap(int year) //判断是否闰年函数
{ return(year%4==0&&year%100!=0||year%400==0); }//闰年的条件 该函数的类型为C51中扩展的bit型(即位类型),这种类型的函数的返回值只能是0或1,不能为其它值。具体到本函数,若年份能满足闰年的条件则返回1,否则返回0。
3.2.2由已知日期如何推算星期几
我们在日常生活中经常会遇到这样的问题,忘记了某年某月某日是星期几,特别是一些重大节日或是一些值得纪念的日子,这就是星期几的推算问题。那么,如何由一个已知日期推算出是星期几呢?
人们一般会采用这样的方法:从一个已知星期几的某天开始推算,先计算已知星期几的这一天距要推算的那天共相差几天,由于星期是7天一轮回的,故可以将相差的天数除以7取余数,再用已知的那天星期几加上余数,就可以推算出要计算的这天是星期几了。在此,我们也采用类似的方法进行推算。已知公元元年1月1日正好是星期一,那么,只需计算出从公元元年1月1日到要推算的这一天总共多少天(s),再用天数s除以7取余数,余0则说明正好够整数个星期,则要推算的这一天正好就是一个星期的最后一天,也就是星期日;余1则说明整数个星期还多一天,那么要推算的这一天就是星期一了;依次类推,余2就是星期二,余3就是星期三.……。但是我们在计算天数时会发现由于中间会经历平年(365天)、闰年(366天),每年的不同月份天数也不相同,这样算来,计算量是很大的,计算也十分不便。有没有改进的方法呢?我们不妨这样来考虑:如果一个年份是平年,则该年有365天,也就是52个星期多一天;如果一个年份是闰年,则该年有366天,也就是52个星期多两天;于是,对于以前的年份,如
-11-
3 相关知识链接 河南理工大学毕业设计论文
果是平年,则只计为一天(扣除其中的整数个星期),同理,如果是闰年,则计为两天。这样一来,则计算量大大减少。
再进一步,把要推算的这一年之前的所有年份都先按平年计算,则之前有多少年,就有多少天(一个平年只计一天,其中的整数个星期已扣除)。设要推算的年份为y,则之前有y-1个年份,就计为y-1天。其中y-1个年份中有若干个年份是闰年,由于闰年比平年多一天(平年2月28天,闰年2月29天,闰年和平年的其它相应月份的天数是一样的,只有2月份不同),则需再加上闰年的个数,于是可以算出y年之前有(y-1) +(y-1)/4-(y-1)/100+(y-1)/400天。注意:先把之前y-1年中凡是4的整数倍的年份都暂按闰年计算,然后再去掉是100的整数倍的年份,再加上是400的整数倍的年份,即可算出y年之前有之少天了(整数个星期已扣除)。
然后再计算要推算的这一天是当年的第多少天,这个不难计算。如果要推算的日子在该年的前两个月,则与该年是否闰年无关;如果是2月份以后的月份,可以先按平年计算,如果是闰年,则再加上一天(因为闰年的2月份比平年的2月份多一天)。这样,就可以对要推算的日子所在的月份进行测试,并按各种情况计算出要推算的这一天所在的月份之前当年已过了多少天,再加上要推算的这一天是当月的第几天,就可以算出要推算的这一天是当年的第多少天了。用之前所算出的当年之前的总天数加上要推算的这一天是当年的多少天,如此计算出总天数,再用这个总天数除以7取余数,余0则是星期日,余1则是星期一,余2则是星期二,……如此等等。
由已知日期推算星期几的函数的参考源代码如下:
char tuisuan(int y, char m, char d) //根据已知日期推算星期几 { int s; //变量s用于存放总天数 switch (m)
{ case 1: s=0; break;
//如果欲推算的这一天在1月份,则当月之前经历了0天 case 2: s=31;break; case 3: s=59; break; case 4: s=90;break; case 5: s=120; break; case 6: s=151;break; case 7: s=181; break; case 8: s=212;break; case 9: s=243; break; case 10: s=273;break;
-12-
河南理工大学毕业设计论文 3 相关知识链接
case 11: s=304; break; case 12: s=334;break; }
if(m>2&&leap(y)) s=s+1; s=s+d;
s=s+(y-1)+(y-1)/4-(y-1)/100+(y-1)/400; return (s%7); }
程序运行期间,通过按键调整日期,运行结果测试如表3-2所示:
表3-2 星期计算问题测试数据表
测试数据 第一组 第二组 第三组 2000年1月1日 2008年8月8日 2014年4月19日 运行结果 星期六 星期五 星期六 3.3 12864点阵图形液晶的使用
3.3.1液晶概述
液晶(Liquid Crystal)是一种高分子材料,由于它具有特殊的物理、化学、光学特性,被广泛地应用在各种轻薄型显示器上,如手机屏幕、笔记本电脑显示屏及各种便携式电子信息产品中。
液晶显示器(Liquid Crystal Display,简写为LCD)的主要显示原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。为叙述方便,通常把各种液晶显示器都直接叫做液晶。
液晶显示器具有体积小、质量轻、功耗低(功率为10mW,5V电源供电、工作电流只有2mA)、可靠性高、显示操作简单等优点,被广泛地应用在各种便携式电子信息产品中作显示器件。特别是电池供电的单片机产品中,液晶显示器几乎是必选的显示器件。但是,液晶也有一个致命的弱点,那就是其使用的温度范围很窄,通用型液晶正常工作温度范围为0℃~+55 ℃,存储温度范围为-20℃~+60 ℃。即使是宽温级液晶,其正常工作温度范围也仅为-20℃~+70 ℃,存储温度范围为-30℃~+80 ℃。(高寒地区难以正常工作)。因此在设计相应产品时务必要考虑周全,选取合适的液晶。
按照能够显示的字符个数和行数,液晶有多种型号(如1602、0801等,它们属于字符液晶,只能用于显示英文字母、阿拉伯数字及其他一些ASCII字符,不可用来显示汉字)。也有的液晶型号是按照液晶显示点阵的行、列数来命名的,
-13-
3 相关知识链接 河南理工大学毕业设计论文
如:12232、12864,这些都是图形液晶,可用于显示图形与汉字。12864意即横向有128列、竖向有64行的点阵,通过编程控制让其中哪些点亮、哪些点不亮,就可以显示一个特定的画面。
根据显示的色彩,液晶还可分为单(色)显液晶和彩(色)显液晶。 根据操作的方式不同,液晶还可分为串行操作方式与并行操作方式。目前,市场上的12864液晶以并行操作方式居多。
3.3.2 LCM引脚功能介绍
通常将LCD控制器、显示器及RAM(用于存储显示的数据)、ROM(用于存放指令)连接在一块印刷电路板上,称为液晶显示控制模块(LCM)。12864液晶显示模块有20个引脚,其引脚功能介绍如表3-3所示:
表3-3 12864液晶显示模块引脚功能表
引脚编号 1 2 3 4 5 6 7 8 9 10 符号 功能说明 电源地(负极) 电源正极 液晶显示对比度调节端 数据/命令选择端 读/写控制端 读写使能端 数据和命令通道 数据和命令通道 数据和命令通道 数据和命令通道 引脚编号 11 12 13 14 15 16 17 18 19 20 符号 功能说明 数据和命令通道 数据和命令通道 数据和命令通道 数据和命令通道 左半屏选择信号 右半屏选择信号 复位信号,低电平有效 液晶驱动电压输出端 背光电源正极 背光电源负极 VSS D4 D5 D6 D7 VDD VO RS R/W CS1 EN D0 CS2 RSTVEE D1 D2 D3 LED LED 引脚功能说明:
第1脚VSS、第2脚VDD为整个LCM模块的电源端,第19脚LED、第20脚LED为背部光源的电源正、负极。引脚如此设置,第1脚和第20脚均是接地,第2脚和第19脚均是电源正极,即使插错,最多导致液晶不能正常工作显示,但不至于烧坏液晶。
RS为存储器选择位,RS=1,对数据存储器进行读写,RS=0,对指令存储器进行读写。
R/W为读写控制信号,R/W=1,对模块进行读操作;R/W=0,对模块进行
写操作。
EN为LCM模块的使能控制端,高电平有效,下降沿锁定数据。
D0~D7为LCM的数据/指令总线。
-14-
河南理工大学毕业设计论文 3 相关知识链接
CS1、CS2为左右半屏选择信号,高电平有效。其中当CS1=1、CS2=0时选中左半屏;当CS1=0、CS2=1时选中右半屏。
RS、R/W控制读、写存储器操作格式如表3-4所示:
表3-4 RS、R/W的功能描述 RS 0 0 1 1 R/W 0 1 0 1 操 作 对指令存储器进行写操作 从指令存储器读出“忙”标志信号和当前地址到数据总线 对数据存储器进行写操作 对数据存储器进行读操作 3.3.3 LCD12864图形液晶显示模块指令集 LCD12864图形液晶显示模块指令集如表3-5所示。
表3-5 LCD12864图形液晶显示模块指令集
读写操作 数据口 指令及指令关键字说明 显示开关控制指令:0x3f~0x3e RS R/W D7 D6 D5 D4 D3 D2 D1 D0 0 0 0 0 0 1 1 1 1 1 D D=1,开显示(0x3f);D=0,关显示(0x3e) 设置显示起始行指令:0xc0+add 0 1 1 L5 L4 L3 L2 L1 L0 add=L5L4L3L2L1L0,add的取值范围为0~63。该指令用于控制显示的起始行。 页地址设置指令:0xb8+add 0 0 1 0 1 1 1 P2 P1 P0 add=P2P1P0,add的取值范围为0~7。该指令用于设置后续读写的页地址。 列地址设置指令:0x40+add add=C5C4C3C2C1C0,add的取值范围为0 0 0 1 C5 C4 C3 C2 C1 C0 0~63。该指令用于设置后续读写的列地址。整个屏幕分为左右两个半屏,每半屏各64列(0~63) 读状态字指令: 0 1 BF 0 on/ off rst 0 0 0 0 BF为LCD控制模块的“忙”标志位。On/off=1说明显示关闭;rst=1说明LCD控制模块正在复位。 写显示数据指令: 1 0 D7 D6 D5 D4 D3 D2 D1 D0 将要显示的字模数据写入LCD控制模块的数据存储器中。 读显示数据指令: 从LCD控制模块的数据存储器中读出字1 1 D7 D6 D5 D4 D3 D2 D1 D0 模数据,送至数据总线,以便修改后重新写入从而实现特效显示。 -15- 3 相关知识链接 河南理工大学毕业设计论文
必要说明:
(1) BF为LCD控制模块的“忙”标志位。BF=1,LCD控制模块忙,不能接收任何指令或数据;BF=0,LCD控制模块不忙,可以接收指令或数据。向LCD控制模块发送指令或数据前应先查询BF状态。
(2)12864液晶显示器规定每8行点阵为1页,整个屏幕64行分为8页。 (3)12864液晶显示器把整个屏幕分为左右两个半屏,每个半屏各64列。左、右半屏通过CS1、CS2来选择。在读写数据时,当页地址不变时,列地址会自动加1,在0~63列之间循环,不换页。
LCD12864的显示缓存DDRAM页地址、列地址与显示器的点阵位置对应,单片机只需把字模数据送到DDRAM,就可以在点阵相应位置显示出字符。
3.3.4 LCD12864图形液晶显示模块与单片机的接口
LCD12864图形液晶显示模块与单片机的硬件连接如图3-3所示。
图3-3 LCD12864图形液晶显示模块与单片机的硬件连接图
3.3.5 LCD12864图形液晶显示模块的基础函数 (1) 引脚定义:
sbit CS1=P2^1; //左半屏选择位,高电平有效 sbit CS2=P2^2; //右半屏选择位,高电平有效
sbit RS=P2^4; //定义液晶模块的数据/指令存储器选择位 sbit RW=P2^5; //定义液晶模块的读/写控制选择位
sbit EN=P2^6; //定义液晶模块的使能端,高电平写入,下降沿锁存 (2) 忙检测函数:
void busy_12864( ) //用于检测12864是否忙,无返回值,如忙则等待
-16-
河南理工大学毕业设计论文 3 相关知识链接
{
P0=0xff ; //将P0口置于准备“读”状态 RS=0;RW=1; //读状态操作 EN=1; //使EN有效
while(P0&0x80); //若P0口最高位为1则表示“忙”,需等待 EN=0 ; //关闭使能信号 }
(3) 向12864液晶显示模块写命令函数:
void writelcd_cmd(unsigned char cmd) //形式参数cmd为要写入的指令 {
busy_12864( ); //忙检测,若忙则等待 RS=0; RW=0; //置于写命令工作模式
P0=cmd; //将要写入的命令字节数据放在数据线上 EN=1;EN=0; //送出命令,并使之有效 }
(4) 向12864液晶显示模块写数据函数:
void writelcd_dat(unsigned char dat) //形式参数dat为要写入的数据 {
busy_12864( ); //忙检测,若忙则等待 RS=1; RW=0; //置于写数据工作模式 P0=cmd; //将要写入的数据放在数据线上 EN=1;EN=0; //送出数据,并使之有效 }
(5) 向12864液晶显示器指定位置写数据函数:
//将要显示的一字节数据dat写入到12864液晶显示器的第p页、第c列 void sendlcd_dat(unsigned char p, unsigned char c,unsigned char dat) {
if(c>63) CS1=0, CS2=1,c=c-64; //如果列号超过63,则应显示在右半屏 else CS1=1,CS2=0 ; //如果列号不超过63,则应显示在左半屏 writelcd_cmd(0xb8+p); //定位于p页 writelcd_cmd(0x40+c); //定位于c列
writelcd_dat(dat); //向指定位置写入待显示的数据 }
(6) 12864液晶显示模块的清屏函数:
由于本设计中所采用的是不带字库的12864显示屏,没有清屏指令,需要自
-17-
3 相关知识链接 河南理工大学毕业设计论文
己编写清屏函数,原理就是向DDRAM的每页每列处写0。
void cls() {
uchar i, j; for(i=0;i<8;i++) }
(7) 12864液晶显示模块的初始化函数:
void lcd_init( ) //12864液晶显示模块的初始化函数 { }
(8) 在12864液晶显示器的指定位置显示某个汉字的函数定义如下: void xhz (uchar p,uchar c,uchar n)
//p为页地址,c为列地址,n为该汉字在字模数组中的序号 { }
说明:源程序中已定义要显示的各个汉字和特殊字符的字模数据,字模数据由取字模软件获得。zm[][32]为汉字字模,每个汉字的字模包括32个字节数据。
(9) 在12864液晶显示器的指定位置显示某个数字字符的函数定义如下: void xsz (bit flag, uchar p,uchar c,uchar n)
//p为页地址,c为列地址,n为该数字在字模数组中的序号 { }
说明:源程序中已定义要显示的各ASCII码字符的字模数据,由取字模软件获得。sz[][16]为ASCII码字符字模,每个ASCII码字符的字模包括16个字节数
-18-
for(j=0;j<128;j++) sendlcd_dat(i,j,0) ; //
writelcd_cmd(0x3f); //开显示
writelcd_cmd(0xc0); //设置显示起始行 cls(); //清屏
uchar i; for(i=0;i<32;i++)
sendlcd_dat (p+i/16,c+i%16,zm[n][i]);
uchar i; for(i=0;i<16;i++)
sendlcd_dat(p+i/8,c+i%8,flag?~sz[n][i]:sz[n][i]);
河南理工大学毕业设计论文 3 相关知识链接
据。形式参数变量flag决定是否反显,flag=1则反显,flag=0则正常显示。当要调整日期时间时需反显要调整的数据项,以免错调,此时应使变量flag等于1。
(10) 12864液晶显示模块的显示函数
12864液晶显示器的显示函数只需调用以上显示汉字和ASCII码字符的函数在指定位置显示特定的汉字或数字即可。略写。
3.4 51单片机中的定时器中断
本设计中需要用单片机的定时器来标识读取实时时钟和环境温度的时刻。51单片机内部有2个16位的定时器,分别是T0和T1。当定时器计满溢出时就会向CPU发出中断请求,在开中断的前提下,CPU检测到中断请求后会暂停主程序的执行,转去执行中断处理程序,待中断处理程序执行完毕后再返回原程序断点处继续运行。
定时器的启动与停止、是否计满溢出申请中断是由定时器控制寄存器TCON来控制和管理的。TCON是一个可位寻址的特殊功能寄存器,可对其每一位单独进行操作。单片机复位时,TCON的所有位均被清0。其各位名称如表3-6所示。
表3-6 定时器控制寄存器TCON的各位功能说明 位 号 位名称 D7 D6 D5 D4 D3 D2 D1 D0 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TCON寄存器中和定时中断有关的位的功能介绍如下:
TR0:定时器T0的启动控制位。当TR0=1时,T0启动计数;当TR0=0时,T0停止计数;
TF0:定时器T0的溢出中断标志位。当T0计满溢出时,由硬件自动将TF0置1,并向CPU发出中断请求,当CPU响应该中断进入中断服务程序后,由硬件自动将该位清0,不需用专门的语句将该位清0。
TR1:定时器T1的启动控制位。其功能及使用方法同TR0。 TF1:定时器T1的溢出中断标志位。其功能及使用方法同TF0。
其余四位与外部中断相关,是两个外部中断的中断请求标志位和触发方式控制位,本设计不涉及,故不再赘述。
在51单片机的中断系统中,中断的允许或禁止是在中断允计寄存器IE中设置的。IE也是一个可位操作的8位特殊功能寄存器,即可以对其每一位单独进行操作,当然也可以进行整体字节操作。单片机复位时,IE全部被清0。其各位定义如表3-7所示。
表3-7 中断允许寄存器IE的各位功能定义 位 号 位名称 D7 D6 EA — D5 — D4 ES -19-
D3 D2 D1 D0 ET1 EX1 ET0 EX0 3 相关知识链接 河南理工大学毕业设计论文
中断允许寄存器IE中和定时器中断有关的位的功能定义说明如下: EA:即Enable All的缩写,全局中断允许控制位。当EA=0时,则所有中断均被禁止;当EA=1时,全局中断允许打开,在此条件下,由各个中断源的中断控制位确定相应的中断允许或禁止。换言之,EA就是各种中断源的总开关。
ET0:定时器T0的中断允许位。如果ET0置1,则允许定时器T0中断,否则禁止定时器T0中断。
ET1:定时器T1的中断允许位。如果ET1置1,则允许定时器T1中断,否则禁止定时器T1中断。
例如:如果我们要设置定时/计数器T0中断允许,其他中断不允许,则IE寄存器各位取值如表3-8所示。
表3-8 IE寄存器的各位取值
位 号 位名称 取 值 D7 D6 EA — 1 0 D5 — 0 D4 ES 0 D3 0 D2 0 D1 1 D0 0 ET1 EX1 ET0 EX0 即IE=0x82。当然,我们也可以用位操作指令来实现:EA=1,ET0=1。 (5) 中断初始化及中断服务程序结构
中断初始化实质上就是对与中断有关的特殊功能寄存器TCON、IE进行管理和控制,具体实施如下:
① CPU的开、关中断(即全局中断允许控制位的打开与关闭,EA=1或EA=0);
② 具体中断源中断请求的允许和禁止(屏蔽);
中断的管理和控制(即中断初始化)程序一般都包含在主函数的初始化函数中,根据需要通常只需几条赋值语句即可完成。中断服务程序是一种具有特定功能的独立程序段,往往写成一个独立函数,函数内容可根据中断源的要求进行编写。
C51的中断服务程序(函数)的格式如下: void 中断处理程序函数名( ) interrupt 中断序号 {
中断处理程序内容; }
中断处理函数不会返回任何值,故其函数类型为void型,函数类型名void后紧跟中断处理程序的函数名,函数名可以任意命名,只要合乎C51中对标识符的规定即可;中断处理函数不带任何参数,所以中断函数名后面的括号内为空;interrupt即“中断”的意思,是为区别于普通自定义函数而设;中断序号是编译
-20-
河南理工大学毕业设计论文 3 相关知识链接
器识别不同中断源的唯一符号,它对应着中断服务程序入口地址,因此在写中断函数时一定要把中断序号写准确,否则中断程序将得不到运行。定时器T0和T1的中断号分别是1和3,在编写中断函数时一定不要写错。
T0和T1都是16位的加法计数器,它们的容量是有限的,不可能无限制地持续计数,其计数最大值为65535(即二进制数1111 1111 1111 1111B),此时,若再输入一个计数脉冲则计满溢出,将对应的计满溢出标志位置1,向CPU发出中断申请,请求CPU暂停当前程序的执行,转而来执行相应的中断处理程序。
图3-4 51单片机的定时器逻辑结构图
51单片机内部的定时器的逻辑结构如图3-4所示,T0和T1都是16位的可编程定时/计数器,通过设置和它们相关的特殊功能寄存器可以选择其工作状态和工作方式。需要注意的是:51单片机中的定时/计数器是单片机内部一个独立的硬件部分,它与CPU和晶振通过内部某些控制线连接并相互作用,一旦CPU启动计数器工作时,计数器便在输入脉冲的作用下开始计数,计数器的计数与CPU的工作是同时进行的,直到计数器计满溢出将相应的溢出标志位置1,向CPU发出中断请求,CPU在允许中断的情况下才暂停当前程序的执行,转去执行相应的中断服务程序。
由图3-5可知:51单片机的定时器系统由定时器T0、T1、定时器控制寄存器TCON和定时器工作方式寄存器TMOD组成。T0和T1都可对输入脉冲进行加法计数,即每来一个脉冲计数器的值加1,直到计满溢出。每一个计数器都是由两个8位计数器(即高8位THX(X=0,1)和低8位TLX(X=0,1))组成,TH1、TL1、TH0、TL0都可以单独访问。当定时/计数器的计数脉冲来自单片机内部(对机器周期进行加法计数,一个机器周期等于12个时钟周期,即机器周期脉冲是时钟脉冲的十二分频)时,由于晶振产生的时钟脉冲的周期是非常稳定的,所以
-21-
3 相关知识链接 河南理工大学毕业设计论文
当计数值一定时,计数的时间也随之而定,此时定时/计数器工作于定时状态。
对于16位的计数器而言,其计数最大容量为65536。如果其初始值为零,当输入65535个脉冲后,其计数值为65535(即二进制数1111 1111 1111 1111B),再来一个脉冲,计数器的值将计满溢出回零(进位信号将相应的计满溢出标志位TFX(X=0,1)置1,从而向CPU发出中断请求)。如果所需计数值小于65536,怎么办呢?这就好比一个空的水瓶,要滴1万滴水才会滴满溢出,我们在开始滴水之前先放入一些水,就不需要1万滴了。比如先放入2000滴,再滴8000滴就可以把瓶子滴满。在单片机中,也采用类似的方法,称为预置初始数法。我们要计50000,那就先预置计数器的初始值为15536(65536-50000),再输入50000个脉冲,到65536就计满溢出。
使用定时器时,首先在程序中用相关赋值语句设定好定时/计数器的启动方式、功能模式、工作方式及计数初始值(这一过程我们习惯称为定时/计数器的初始化),然后启动它工作,定时/计数器将按照设定好的工作方式,从计数初始值开始,对指定的计数脉冲加1计数,此时不占用CPU时间,CPU的工作与计数器的计数是同时进行的且互不影响,直到定时/计数器计满溢出才向CPU发出中断请求信号,CPU通过中断或软件查询方式处理溢出后的服务。如果计满溢出后没有停止定时/计数器工作,则定时/计数器继续进行加1计数,每次计满溢出时都会向CPU发出中断请求。
定时器的定时时间长短与系统晶振的振荡频率密切相关。为便于计算,本设计中的单片机系统采用12MHz的晶振,一个机器周期由12个振荡脉冲组成,则计数脉冲的频率为振荡频率的12分频,即12MHz/12=1MHz,计数周期为1s,如果计数器的初始值为零,则最长定时时间为65536s,即65.536ms。如果赋予定时器一个合适的初始值,就可获取一个需要的定时时间。如果所需定时时间大于定时器所能定时的最长时间,可采用多次定时法以达到要求。
下面简要介绍一下定时/计数器的工作方式和控制寄存器。
我们可以通过设置定时器工作方式寄存器TMOD来决定定时/计数器的启动方式、计数脉冲源的选择(从而可以决定使其工作于计数功能或定时功能)、工作方式,可通过设置定时器控制寄存器TCON来控制定时/计数器的启动与停止。
(1) 定时器工作方式寄存器TMOD
TMOD是一个字节操作的特殊功能寄存器,不可对其进行位操作。单片机复位时,TMOD的各位均被清0。其各位名称如表3-9所示。
由表3-12可知。定时器工作方式寄存器TMOD的高4位用于控制定时/计数器T1,低4位用于控制定时/计数器T0,下面对其各位功能介绍如下:
-22-
河南理工大学毕业设计论文 3 相关知识链接
表3-9 定时器工作方式寄存器TMOD的各位功能说明
位号 位名称 D7 GATE D6 D5 M1 D4 M0 D3 GATE D2 D1 M1 D0 M0 C/T C/T 高4位控制定时/计数器T1 低4位控制定时/计数器T0 GATE:门控位。该位影响定时/计数器的启动控制方式。
当GATE=0时,定时/计数器的启动与停止仅受定时器控制寄存器TCON中的TRX(X=0,1)的控制。此时,若TRX=1,接通定时/计数器的输入脉冲,启动定时/计数器工作;若TRX=0,则切断定时/计数器的输入脉冲来源,使定时/计数器停止工作。
当GATE=1时,定时/计数器的启动与停止由定时器控制寄存器TCON中的TRX和外部中断引脚(INT0或INT1)上的电平状态共同控制。此时,若TRX和INTX(X=0,1)均为高电平,则接通定时/计数器的输入脉冲,启动定时/计数器工作;若TRX和INTX不全为高电平,则切断定时/计数器的输入脉冲来源,使定时/计数器停止工作。
C/T:定时/计数功能选择位。
当C/T=0时,定时/计数器的计数脉冲来源于单片机内部时钟脉冲的十二分频(即机器周期),此时,由于计数周期是固定的,计数就转化为定时,定时/计数器工作在定时功能模式。当C/T=1时,定时/计数器的计数脉冲来源于单片机外部(从单片机的P3.4(T0)、P3.5(T1)输入),此时,由于计数脉冲的周期是不固定的,定时/计数器工作在计数功能模式。
GATE与C/T对定时/计数器的控制作用(以T0为例)如图3-5所示。
图3-5 定时器控制逻辑图
M1和M0:工作方式选择位。
T0和T1,每个定时/计数器都有四种工作方式,由M1和M0来设定。定时/计数器的工作方式选择与M1M0值的对应关系如表3-10所示。本设计中只用定时
-23-
3 相关知识链接 河南理工大学毕业设计论文
器中断来标志读时间和读温度的时刻,定时时间较长,故使定时/计数器工作在方式1,即其16位全部使用。
表3-10 定时/计数器的4种工作方式选择表
M1 M0 0 0 0 1 1 0 1 1 工作方式 方式0 方式1 方式2 方式3 功能说明 仅作为13位的定时/计数器使用 作为16位的定时/计数器使用 作为8位定时/计数器使用,初始值可自动重载 仅适用于T0,分成两个8位的计数器使用,T1停止工作 定时器的定时时间长短与定时器的位数、计数初始值、时钟频率密切相关。定时时间的计算公式如下:
t2n计数初始值机器周期2n计数初始值12/fOSC
f其中,t为定时时间,n为定时器位数,OSC为系统的晶振时钟频率。
f例如:已知系统晶振频率为OSC=12MHz,在方式1下,T0的最大定时时间为 T(2160)12/(12106)65536106s65536s65.536ms
如果在方式1下要定时50ms,晶振频率为12MHz,则T0应赋的初始值的计算方法如下:
由于晶振频率为12MHz,则机器周期为1s,若定时50ms,即50000s,则计数初始值应为65536-50000=15536,将15536/256赋与定时/计数器的高8位THX,将15535%256赋与定时/计数器的低8位TLX。
本设计中定时中断的初始化函数参考源代码为: void init_timer(void) //定时器初始化函数
{ TMOD=0x01; //使用模式1,16位定时器,工作在定时模式下
TH0=15536/256; //设定定时器T0的初始值,定时50ms,即50000us TL0=15536%256;
TR0=ET0=EA=1; } //打开中断,启动定时器T0 本设计中定时中断的中断服务程序参考源代码为: void timer0( ) interrupt 1 //定时器T0的中断服务程序 { static uchar n; //定义静态变量n,用于统计定时中断的次数 TH0=15536/256; TL0=15536%256; //重新给定时器T0赋初值 n++;
if(n%2) ReadTimeFlag=1;}
if(n==60) { n=0; ReadTempFlag=1;} //ReadTimeFlag和ReadTempFlag为bit
型,已在程序开头定义为全局变量,分别用于标志读时间和读温度时刻
//每隔3秒将读温度标志位置1,即每3秒钟采集一次环境温度
-24-
河南理工大学毕业设计论文 3 相关知识链接
}
3.5实时时钟芯片DS1302的使用
3.5.1 DS18B20概述
DS1302是美国的DALLAS半导体公司推出的一种高性能、低功耗、带有31字节静态RAM的实时时钟芯片(RTC),它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿和大小月的计算功能,其工作电压宽达2.5~5.5V。DS1302采用SPI三线接口与单片机进行串行同步通信,并可采用突发方式一次传送多个字节的时钟信息或RAM数据。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/备用电源双电源供电功能,同时提供了对备用电源进行涓细电流充电的能力。在主电源关闭或掉电的情况下,也能通过备用电源供电保持时钟的连续运行,从而保证时间信息和RAM数据不会丢失。DS1302工作时功耗很低,保持数据和时钟信息时功耗小于1mW。由于其接口电路简单(仅需三根线与单片机连接)、价格低廉、使用方便,被广泛地用在各种测量电路中,以便保存带有时间信息的测量数据,便于用户后期对数据进行观察、分析。DS1302 的内部结构及外部引脚如图3-6、3-7所示。
DS1302
图3-6 DS1302的内部结构框图 图3-7 DS1302外部引脚图
引脚功能说明如下:
VCC2:主电源。VCC1:后备电源。DS1302由VCC1 和VCC2两者中较大者供电,当VCC2大于VCC10.2V时,由VCC2主电源供电;当VCC2小于VCC1时,由VCC1备用电源供电。
GND:电源地。
X 1、X2:外接32.768KHz的晶体振荡器,为DS1302提供振荡源,从而保证时钟走时; 晶振的精度决定了DS1302的走时的精度。
I/O:串行数据输入/输出端(双向),即数据线,用于和单片机进行数据交换。 SCLK:串行通信时钟信号,为串行通信提供时间基准。
RST:复位/片选引脚。当此引脚为高电平时,方允许DS1302和单片机数据
-25-
3 相关知识链接 河南理工大学毕业设计论文
通信;当它为低电平时,数据线为高阻态。在数据传送过程中,如果将此引脚置为低电平,则会终止该次数据传送。上电运行时,当VCC>2.0V之前, RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。
3.5.2 DS1302与单片机的接口
DS1302采用SPI总线方式与单片机接口。SPI(Serial Peripheral Interface)是一种高速、全双工、同步串行通信总线,与单片机的连接只需三根线:数据线、串行通信时钟信号线、复位信号线。由于51单片机没有配置SPI总线接口,但可以利用其并行口线模拟SPI串行总线时序,以便实现对DS1302的各种操作。DS1302与单片机的接口电路如图3-8所示:
图3-8 DS1302与单片机的接口电路
图中,I/O引脚为双向串行通信数据线,SCLK为串行通信时钟信号线,RST为复位信号线。分别与单片机的并行I/O口相连。实际应用中,这三根线通常需要通过上拉电阻(4.7K)接至电源正极。
3.5.3 DS1302的读写操作
对DS1302的操作可分为读操作和写操作,均由命令字节实现。命令字节的格式如下:
位:D7 D6 D5 D4 D3 D2 D1 D0
1 R/C A4 A3 A2 A1 A0 R/W 其中D7位固定为1,R/C为时钟/RAM数据操作选择位,当该位为0时选
R/W择操作时钟数据,为1时则选择操作RAM数据。A4A3A2A1A0为操作地址,
-26-
河南理工大学毕业设计论文 3 相关知识链接
为读写选择位,为0时进行写操作,为1时进行读操作。
单字节写操作时序:
从写操作时序图可以看出,无论命令字节还是数据,都是在RST为高电平的情况下按照由低位到高位的顺序在SCLK的上升沿依次串行写入移位寄存器,先将要写入数据的寄存器地址写入移位寄存器,然后再写入指定的数据。
单字节读操作时序:
从读操作时序图可以看出,从DS1302读出数据时,也是在RST为高电平的情况下,先将要访问的寄存器地址按照由低位到高位串行写入到移位寄存器中,然后在紧接着的下一个下降沿开始读出数据。
通过以上时序图可以看出,对DS1302的读写操作均可以分解为两个步骤。对于读操作而言,可以分解为先向DS1302写入目的地址,然后再从目的地址处读出数据;对于写操作来说,可以分解为先向DS1302写入目的地址,然后再向目的地址处写入数据。这样,我们就可以将DS1302的读写操作分解为3个步骤:写地址操作、写数据操作、读数据操作。对于多字节连续读写操作实际上就是一个写地址操作加上多个读/写数据操作。以上3个步骤的C函数分别编写如下:
void DS1302_write_add ( uchar add ) //写地址操作 {
unsigned char i ;
RST=0 ; SCLK=0 ; RST=1 ; //严格按照时序图顺序编写 for ( i=0 ; i<8 ; i++ ) //逐位将目标地址写入 {
SCLK=0 ;
SDA=add&0x01 ; //从低位到高位逐位写入
-27-
3 相关知识链接 河南理工大学毕业设计论文
SCLK=1 ; //在SCLK的上升沿将地址写入 add=add>>1; } }
void DS1302_write_dat ( uchar dat ) //写数据操作 {
unsigned char i;
for ( i=0 ; i<8 ; i++) //逐位将数据写入 {
SCLK=0 ;
SDA=dat&0x01 ; //将数据从低位到高位逐位写入 SCLK=1 ; dat=dat>>1 ; } }
unsigned char DS1302_read_dat ( ) //读数据操作 {
unsigned char i , temp=0 ;
SDA=1 ; //读取数据之前,先将数据线拉高,以便准确接收数据 for ( i=0 ; i<8 ; i++) {
SCLK=1 ; SCLK=0 ; //在时钟信号的下降沿将数据读出
if ( SDA ) temp=temp|(0x01<return temp ; //返回读取结果 }
以上三个函数为DS1302的底层驱动函数(基础操作函数),它们实现以后,对DS1302的各种读写操作就可以用这3个函数组合实现。对DS1302的具体读写函数如下:
void DS1302_write_byte( unsigned char add , unsigned char dat ) //向DS1302某地址add写入单字节数据dat 的函数 {
DS1302_write_add ( add ) ; //写入目标地址 DS1302_write_dat ( dat ) ; //向目标地址写入数据 RST=0 ;
-28-
河南理工大学毕业设计论文 3 相关知识链接
}
unsigned char DS1302_read_byte(unsigned char add) //从DS1302某地址add 读取单字节数据函数 {
uchar temp=0 ;
DS1302_write_add ( add ) ; //写入目标地址
temp=DS1302_read_dat ( ) ; //从目标地址处读取数据,保存在变量temp中 RST=0 ; //复位数据线
return temp ; //返回读取的数据结果 }
3.5.4 DS1302的寄存器
DS1302具有丰富的日历、时钟寄存器和RAM寄存器,具体介绍如下: DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关(分别是年份寄存器、月份寄存器、日寄存器、星期寄存器、小时寄存器、分钟寄存器、秒钟寄存器),存放的数据为BCD码形式,各寄存器及其读写操作的命令字如表3-11所示:
void DS1302_write_time( ) {
uchar i,tmp;
for(i=1;i<8;i++) //将十进制数转换为其BCD码形式 {
tmp=time_buf[i]/10; time_buf[i]=time_buf[i]%10; time_buf[i]=tmp*16+time_buf[i]; }
DS1302_write_byte(0x8e,0x00); //关闭写保护 DS1302_write_byte(0x80,0x80); //时钟暂停 //DS1302_write_byte(0x90,0xab); //涓流充电 DS1302_write_byte(0x8c,time_buf[1]); //写年 DS1302_write_byte(0x8a,time_buf[7]); //写星期 DS1302_write_byte(0x88,time_buf[2]); //写月 DS1302_write_byte(0x86,time_buf[3]); //写日 DS1302_write_byte(0x84,time_buf[4]); //写时
-29-
3 相关知识链接 河南理工大学毕业设计论文
DS1302_write_byte(0x82,time_buf[5]); //写分
DS1302_write_byte(0x80,time_buf[6]&0x7f); //写秒并启动时钟 DS1302_write_byte(0x8e,0x80); //打开写保护 }
void DS1302_read_time() {
uchar i,tmp;
time_buf[1]=DS1302_read_byte(0x8d); //读年 time_buf[2]=DS1302_read_byte(0x89); //读月 time_buf[3]=DS1302_read_byte(0x87); //读日 time_buf[4]=DS1302_read_byte(0x85); //读时
time_buf[5]=DS1302_read_byte(0x83); //读分 time_buf[6]=DS1302_read_byte(0x81); //读秒 if(time_buf[6]&0x80)time_buf[6]=time_buf[6]&0x7f; //如果此时时钟停走,则屏蔽最高位
time_buf[7]=DS1302_read_byte(0x8b); //读星期 for(i=1;i<8;i++) //将BCD码转换为十进制数形式 {
tmp=time_buf[i]/16; time_buf[i]=time_buf[i]%16;
time_buf[i]=tmp*10+time_buf[i];
} }
3.5数字温度传感器DS18B20的使用
3.5.1 DS18B20概述
DS18B20是美国DALLAS 半导体公司的数字温度传感器,它也是世界上第一片支持“一线总线”接口的温度传感器。一线总线独特而且经济的特点,使用
-30-
河南理工大学毕业设计论文 3 相关知识链接
户可轻松地组建传感器网络。DS18B20的测温范围为-55ºC~+125ºC。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性,适合于恶劣环境的现场温度测量,支持3V~5.5V的电压范围,使系统设计更加灵活、方便。DS18B20可通过编程设定9~12位的分辨率,精度为±0.5ºC。分辨率的设定以及用户设定的报警温度存储在其EEPROM中,掉电后依然保存。DS18B20 的性能是新一代产品中最好的,性价比也非常出色。DS18B20使电压、特性及封装有更多的选择,让我们可以构建适合自己的经济的测温系统。DS18B20 的引脚及底视图如图3-7 所示。
图3-7 DS18B20引脚及底视图
引脚功能说明如下: GND:地信号;
DQ:数据输入/输出引脚。单总线接口引脚。当工作于寄生电源时,也可以向器件提供电源;
VDD:可选择的VDD引脚。当工作于寄生电源时,该引脚必须接地。 DS18B20 的性能特点如下: ➢ 只要求 1 根口线即可实现通信。
➢ 每个DS18B20器件上都有独一无二的序列号。 ➢ 实际应用中不需要外接任何元器件即可实现测温。 ➢ 测量温度范围在-55ºC~+125ºC之间。
➢ 用户可通过编程为数字温度传感器设定9~12 位的分辨率。 ➢ 内部有温度上、下限报警设置。 3.5.2 DS18B20的内部结构
DS18B20的内部结构如图 3-8 所示,主要由五部分组成:64 位光刻ROM,高速缓存,温度传感器,非挥发的温度报警触发器TH 和TL、配置寄存器。
-31-
3 相关知识链接 河南理工大学毕业设计论文
图 3-8 DS18B20 内部结构图
下面具体介绍DS18B20每一部分的结构和作用。 (1) 64位光刻 ROM
光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该 DS18B20的地址序列码。64位光刻ROM的排列是:开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身的唯一序列号,最后8 位是前面56位的循环冗余校验码(CRC)。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20 的目的。
(2) 高速缓存存储器
高速缓存存储器包含了 9个连续字节,如表3-14所示。前两个字节存放测得的温度值,第一个字节的内容是所测温度的低八位,第二个字节是所测温度的高八位。第三和第四个字节分别是TH、TL的易失性拷贝,第五个字节是结构寄存器的易失性拷贝,这三个字节的内容在每一次上电复位时被刷新,第六、七、八个字节用于内部计算。第九个字节是冗余检验字节,是前面所有8个字节的 CRC码,可用来保证通信正确。
表 3-14 DS18B20 字节定义 寄存器内容 温度低字节 温度高字节 高温限制 低温限制 保留 保留 计数剩余值 每度计数值 每度计数值 字节地址 0 1 2 3 4 5 6 7 8 配置寄存器为高速缓存存储器中的第 5个字节,其内容用于确定温度值的数字转换分辨率,DS18B20 工作时按此寄存器中的分辨率将温度转换为相应精度的数值。该字节各位的定义如下:
-32-
河南理工大学毕业设计论文 3 相关知识链接
TM R1 R0 1 1 1 1 1 低5位一直都是1,TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。在 DS18B20出厂时该位被设置为 0,用户不要去随意改动,R1和R0决定温度转换的精度位数,即设置分辨率,如表3-15 所示(DS18B20 出厂时分辨率被设置为 12位)。
从表3-15中数据可知,设定的分辨率越高,所需要的温度转换时间就越长。因此,在实际应用中要在分辨率和转换时间两者之间权衡考虑。 实际上,18B20的转换精度为±0.5ºC,分辨率的位数设置得多并不具有多少实际意义,而且设定的分辨率越高,所需要的温度转换时间也越长,可以说“得不偿失”,故在本设计中,将其分辨率设置为9位即可。
表 3-15 温度转换精度位数及转换时间表 R1 0 0 1 1 R0 0 1 0 1 分辨率 9位 10位 11位 12位 温度最大转换时间 (单位:ms) 93.75 187.5 275.0 750.0 (3) 温度传感器
DS18B20中的温度传感器可完成对温度的测量,以 12 位转化为例:用16位符号扩展的二进制补码形式提供,以 0.0625ºC/LSB 形式表达,其中 S为符号位。如表3-16 所示。
表3-16 12 位转化的数据位
低字节 高字节 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 23 S 22 S 21 S 20 S 21 S 22 26 23 bit9 24 bit8 bit15 bit14 bit13 bit12 bit11 bit10 25 24 这是转换后得到的12位数据,存储在高速缓存的前两个字节中,二进制中的高5位是扩展的符号位,如果测得的温度高于0 ºC,这5 位都为0,只要将该二进制数转换后十进制数再乘以0.0625即可得到实际温度;如果温度低于0 ºC,这5 位都为 1,测得的二进制数值按位取反加1(对于负数,存储的是其补码,需转换为原码,负数的补码转换为原码,只需将补码按位取反后再加1即可)后再乘以0.0625即可得到实际温度。
(4) CRC 的产生
在64位光刻 ROM的最高字节中存储有循环冗余校验码(CRC)。主机根据
-33-
3 相关知识链接 河南理工大学毕业设计论文
ROM的前56 位来计算 CRC 值,并和存入 DS18B20 中的 CRC 值做比较,以判断主机收到的 ROM 数据是否正确。
3.5.3 DS18B20与单片机的接口电路
DS18B20 与单片机的典型接口电路如图3-9 所示,DS18B20 的正电源3脚接+5V,1脚接地,2脚接单片机的I/O口,3脚和 2脚之间接一个 4.7K的上拉电阻。
在本设计方案中,DS18B20的数据端与单片机的P2.7相连。
说明:在源程序预包含的头文件head.h中已含有数字温度传感器与单片机的接口的定义语句:sbit DQ= P2^7;
3-9 DS18B20 与单片机接口电路
3.5.4 DS18B20的操作命令
根据DS18B20 的通讯协议,对DS18B20进行操作必须经过三个步骤:复位、发送ROM操作命令、发送RAM操作命令。
(1) 复位
单片机发出复位脉冲,紧跟其后接收 DS18B20 发出的存在脉冲,收到的存在脉冲表明DS18B20 已准备好进行发送和接收数据,单片机可以发送所要求的ROM操作命令和存储器操作命令。
(2) 发送 ROM操作命令
对于只存在单个DS18B20芯片的情况,可直接执行跳过ROM操作命令,对于多个芯片则必须进行读 ROM、搜索ROM、匹配ROM等命令操作。ROM操作命令如表 3-17 所示。
表3-17 DS18B20 的 ROM 操作命令表 命令 读 ROM 0 ROM 匹配 命令代码 0x33 0x55 功能简介 读 DS18B20 的 ROM 中的编码(即 64 位地址) CPU 通过数据总线读出 DS18B20 的 ROM 代码,以通知该器件准备工作。 跳过 ROM 0xcc 忽略64位ROM地址,直接向DS18B20 发出温度转换命令,适用于单片DS8B20工作。 -34-
河南理工大学毕业设计论文 3 相关知识链接
搜索 ROM 0xf0 当数据总线上有多个 DS18B20时,可通过该命令搜索各个器件的 ROM地址 报警搜索命令 0xec 判断温度是否超界 (3) 发送 RAM操作命令
RAM操作命令主要有启动温度转换、读出存储器中的温度值、写存储器等命令操作。RAM操作命令如表 3-18 所示。
表3-18 RAM操作命令
命令 温度转换 读存储器 写入存储器 拷贝存储器 读电源状态 读TH和TL 命令代码 0x44 0xbe 0x4e 0x48 0xb4 0xb8 功能简介 启动 DS18B20 开始温度转换 读出存储器中的温度值 将 TH 和 TL值输入存储器中 将存储器中的值拷贝进计算机中 判断电源工作方式 读出存储器中的 TH 和 TL值 3.5.5 DS18B20的时序
由于DS18B20采用的是“单总线”协议方式,即在一根数据线上实现数据的双向传输,而对AT89S52单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线的协议时序来完成对 DS18B20的访问。
由于 DS18B20 是在一根 I/O 线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20 有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机(单片机)作为主设备,单总线器件(DS18B20)作为从设备。而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。数据和命令的传输都是低位在先。
(1) DS18B20的复位时序
初始化时序包括单片机送出的复位脉冲和DS18B20向单片机返回的存在脉冲。主机总线最小发出480s的低电平复位脉冲,接着释放总线并进入接收状态,器件在接收到总线的电平上升沿后,等待15~60s后发出60~240s的低电平存在脉冲信号,表明DS18B20 存在,如图3-10所示。
图3-10 DS18B20 复位时序图
-35-
3 相关知识链接 河南理工大学毕业设计论文
DS18B20的初始化函数参考源代码为:
void init_DS18B20(void) //温度传感器的初始化函数 { DQ=1; //DQ的初始状态为高电平
DQ=0; //单片机将DQ拉低,给出复位脉冲 delay(90); //精确延时 大于480us、小于960us DQ=1; //单片机释放单总线
delay(20); //延时15~60us后,等待接收传感器返回60-240us的存在脉冲 }
(2) DS18B20的读时序
DS18B20的读时序分为读0 时序和读1 时序两种过程。对于DS18B20 的读时序是从单片机把单总线拉低之后,在 15s之内就得释放单总线,以便让DS18B20 把数据传输到单总线上。DS18B20 完成一个读时序过程,至少需要 60s才能完成。DS18B20 的读时序如图3-11所示。
图3-11 DS18B20的读时序图
DS18B20的读数据函数的参考源代码为:
uchar ReadByte( ) //读数据函数,调用它可得到温度传感器测得的环境温度数值 { uchar i,dat; //变量i用于控制循环次数,变量dat用于存放读取的结果以便反馈给主调函数
for (i=0;i<8;i++) { DQ=1;
dat>>=1; //dat右移一位,由于它是无符号数,其左边最高位自动补0 DQ=0; //给出时钟,以便温度传感器回传数据 delay(1); //稍作延时,以便符合操作的时序要求
DQ=1; //释放总线,以便检测温度传感器回传的数据是0还是1
if(DQ) dat=dat|0x80; //如果读取到的该位数据为1,则将最高位调整为1; //如果读取到的该位数据确实为0,则不做修改。 delay(10); //适当延时,以便完成本次读操作 }
-36-
河南理工大学毕业设计论文 3 相关知识链接
return(dat); //经过8次循环已读到一个字节数据,存放在dat中,返回主调函数 }
(3) DS18B20的写时序
对于DS18B20 的写时序,仍然分为写 0时序和写 1 时序两个过程。对于 DS18B20 写 0时序和写 1 时序的要求不同,当要写 0时序时,单总线要被拉低至少 60s,以便保证 DS18B20能够在 15s到 45s 之间能够正确地采样 I/O 总线上的“0”电平;当要写 1时序时,单总线被拉低之后,在 15s之内就得释放单总线。DS18B20 的写时序如图3-12 所示。
图3-12 DS18B20的写时序图
DS18B20的写数据函数的参考源代码为:
void WriteByte(uchar dat) //写字节函数,调用它可以向温度传感器发送指令和数据 //形式参数dat为要写入的数据或指令 { uchar i; //变量i用于控制循环次数
for (i=0;i<8;i++) { DQ=1; //总线初始化
DQ=0; //拉低总线,给出时钟,以便向温度传感器写入数据或指令 DQ=dat&0x01; //先写入的是低位
delay(10); //稍作延时,以便温度传感器采集单总线上主机写入的数据 DQ=1; //主机释放单总线
dat=dat>>1; //dat左移一位,为下次写操作做准备 delay(5); //适当延时,以便完成本次写操作 } }
根据设计任务要求,要完成的工作是启动 DS18B20进行温度转换,读取转换结果,测得的温度数据经处理后送液晶显示模块显示测温结果。
DS18B20的工作主程序的参考源代码如下: void DS18B20( ) //温度传感器18B20的工作主程序 { init_DS18B20( ); // 温度传感器初始化复位 WriteByte(0xcc); // 跳过读序号列号的操作 WriteByte(0x44); // 启动温度转换
-37-
3 相关知识链接 河南理工大学毕业设计论文
delay(20000);
// 延时,待温度传感器采集数据并完成模数转换后再读取转换结果 init_DS18B20( ); // 温度传感器复位 WriteByte(0xcc); // 跳过读序号列号的操作 WriteByte(0xbe);
// 读取温度寄存器中转换的结果(共可读9个寄存器,其中前两个字节就是温度)
c1=ReadByte(); // 低位字节 c2=ReadByte(); } // 高位字节
//全局变量c1和c2用以存放温度传感器测得的温度数据(两个字节) 至于测得的温度数据如何处理,详见下一章“4.4 软件系统设计”部分中主函数部分的源代码。
3.6 独立式按键的检测
为了便于用户记住各按键的功能,本设计中只使用3个按键用于实现对日期和时间的调整,其中一个按键负责移动光标至要调整的数据项(光标所至数据项反显,以便标识调整项),另外两个按键分别负责对选中的数据项的增减。由于所用按键数量不多,故采用独立式按键接法,即每个按键的一端接地,另一端接到单片机的一个并行I/O口线上,如图3-13所示:
图3-13 独立式按键与单片机的接口
独立式按键接法的优点是电路较为简单,每个按键独占一根I/O口线,每个按键工作时不影响其他口线的状态。对独立式按键的检测一般分为五步:第一步是判断按键是否按下,如果没有按下,则直接转到其他程序的执行。如果有键按下,再进行第二步;第二步是消除按键抖动带来的影响,第三步是要再确认一下按键是否真的被按下,如果属实进入第四步,否则直接转到其他程序的执行。第四步是等待按键释放,第五步则是待按键释放后根据按下的是哪一个键执行相应的功能。
独立式按键的扫描程序参考模块如下:
sbit key=Px.x; //程序开头应有定义独立式按键接在某个口线上 void keyscan( )//独立式按键扫描函数 {
-38-
河南理工大学毕业设计论文 3 相关知识链接
if(!key) //首先判断按键是否按下 { delay(1000); //软件延时去抖 if(!key) //再次确认按键真的按下 {
while(!key) ; //等待按键释放 相应功能代码; //执行相关功能
} }
}
根据按下的是哪一个按键,确定执行相应功能。本设计中的按键处理函数设计如下:
sbit SET=P3^0; sbit ADD=P3^1; sbit SUB=P3^2; void keyscan( )
{ if(SET==0||ADD==0||SUB==0) //如果有键按下
{ delay(800); //延时去抖
if(SET==0||ADD==0||SUB==0) //再次确认有键按下 { if(SET==0) //如果按下的是调整键 { while(SET==0); //等待按键释放
count=(count+1)%7;//count为全局变量,程序已有定义 //变量count用于统计SET键按下的次数,以确定要调整的数据项
}
if(ADD==0) //如果按下的是增加键 { while(ADD==0); //等待按键释放
if (count) //如果当前处于日期时间调整模式 { DS1302_read_time(); //读取当前日期和时间
switch(count) //根据光标所在位置确定调整数据项 { case 1: time_buf[1]=(time_buf[1]+1)%100; if(time_buf[2]==2&&time_buf[3]>28) time_buf[3]=28;
/*如果原来为闰年,年份加1后必然不是闰年,此时如果2月份天数大于28, 则应适当调整2月份天数;其他月份的天数则不受是否闰年的影响*/
break;
case 2: time_buf[2]++; //月份加1
if(time_buf[2]>12) time_buf[2]=1;
-39-
3 相关知识链接 河南理工大学毕业设计论文
if(time_buf[3]>30&&(time_buf[2]==4||time_buf[2]==6||time_buf[2]==9|| time_buf[2]==11)) time_buf[3]=30;//考虑大月变小月后日期最大值的调整 if(time_buf[2]==2&&time_buf[3]>28)//月份加1后如果为2月份要特殊处理 time_buf[3]=leap(2000+time_buf[1])?29:28;//leap为判断是否闰年的函数
break;
case 3: time_buf[3]++; //日期加1
if(time_buf[3]>28) {
if(time_buf[2]==2&&(time_buf[3]>29||!leap(2000+time_buf[1])))
time_buf[3]=1; //2月份的天数超过最大值后归1
if(time_buf[3]>30&&((time_buf[2]==4||time_buf[2]==6||time_buf[2]==9||time_buf[2]==11)||(time_buf[3]>31&&(time_buf[2]==1||time_buf[2]==3||time_buf[2]==5||time_buf[2]==7||time_buf[2]==8||time_buf[2]==10||time_buf[2]==12)))) time_buf[3]=1;
} break;
case 4: time_buf[4]=(time_buf[4]+1)%24;break;//小时加1 case 5: time_buf[5]=(time_buf[5]+1)%60;break;//分钟加1
case 6: time_buf[6]=0; //秒数归0。调整时间时不向日期进位 }
time_buf[7]=week_calc(2000+time_buf[1],time_buf[2],time_buf[3])+1; //根据调整后的日期重新计算星期几
DS1302_write_time();//将更新后的日期时间数据写回实时时钟芯片DS1302}
}
if(SUB==0) //如果按下的是减小键 { while(SUB==0); if(count!=0)
{ DS1302_read_time(); //读取当前日期和时间
switch(count) //根据光标所在位置确定调整数据项 {
case 1: time_buf[1]--; //年份减1 if(time_buf[1]>99) time_buf[1]=99; if(time_buf[2]==2&&time_buf[3]>28) time_buf[3]=28;
/*如果原来为闰年且2月份天数大于28,,年份减1后必然不是闰年, 此时应适当调整2月份天数;其他月份的天数则不受是否闰年的影响*/
break;
-40-
河南理工大学毕业设计论文 3 相关知识链接
case 2: time_buf[2]--; //月份减1 if(time_buf[2]<1)
if(time_buf[3]>30&&(time_buf[2]==4||time_buf[2]==6||time_buf[2]==9|| time_buf[2]==11)) time_buf[3]=30;//考虑大月变小月后日期最大值的调整 if(time_buf[2]==2&&time_buf[3]>28)
time_buf[3]=leap(2000+time_buf[1])?29:28;
//月份变化后如果为2月份且当时的天数超过28要特殊处理,闰年2月最多有29天,平年则最多只有28天
break;
case 3: time_buf[3]--; //日期减1
if(time_buf[3]<1) //如果日期少于1要做相应处理 {
if(time_buf[2]==2) time_buf[3]=leap(2000+time_buf[1])?29:28;
//2月份的最大天数取决于是否闰年
else if (time_buf[2]==4||time_buf[2]==6||time_buf[2]==9 ||time_buf[2]==11) time_buf[3]=30; //这几个月的最大天数为30 else time_buf[3]=31; //其余月份的最大天数为31
} break;
case 4: time_buf[4]--;
if(time_buf[4]>23) time_buf[4]=23;break;//小时减1
case 5: time_buf[5]--;
if(time_buf[5]>59) time_buf[5]=59;break;//分钟减1
case 6:time_buf[6]=time_buf[6]^0x80; //秒寄存器最高位取反,控制时钟走停 }
time_buf[7]=week_calc(2000+time_buf[1],time_buf[2],time_buf[3])+1; //根据调整后的日期重新计算星期几
DS1302_write_time();//将更新后的日期时间数据写回实时时钟芯片DS1302 }}}}}}
要准确调整时钟时,可先使时钟停下来,将秒钟归零,待整分钟时使时钟恢复运行。由于秒钟变化较快,按照生活常识,本设计中不再设置秒钟的加1、减1功能,只设置将秒钟归零、控制时钟走停的功能。
time_buf[2]=12;
-41-
4 系统设计与调试 河南理工大学毕业设计论文
4、 系统设计与调试
4.1 硬件系统设计与调试
4.1.1 硬件系统设计原理图
本设计的硬件系统设计如下:为了节约制作成本,本设计最后完成的作品用便携式电源供电,故不再设计电源电路部分;按键输入模块由3个独立式按键组成,它们的一端接地,另一端接至单片机的P3口上;液晶显示模块的数据口与单片机的P0口相连,其他控制线与P2口的某些位相连;数字温度传感器的数据通信端与单片机的P2.7相连,实时时钟芯片DS1302的串行时钟、数据线、复位信号线分别与单片机的P1.0、P1.1、P1.2相连,具体硬件系统电路原理图如图4-1所示。
图4-1 数码日历钟硬件系统电路原理图
4.1.2 硬件系统元器件清单
数码日历钟硬件系统元器件清单如表4-1所示。
-42-
河南理工大学毕业设计论文 4 系统设计与调试
表4-1 数码日历钟硬件系统元器件清单
代号 U1 X1 X2 C1、C2 C3 C4、C5 R1 R2 LCM RP1 RV1 R3 U2 U3 S1~S4 名称 单片机 石英晶体振荡器 石英晶体振荡器 瓷介质电容 电解电容 瓷介质电容 电阻 电阻 图形液晶显示模块 排阻 电位器 电阻 实时时钟芯片 数字温度传感器 轻触按键(4只) DIP-40 IC插座 直流电源插口 规格 AT89S52 11.0592MHz 32.768KHz 30pF 10μF 6pF 10KΩ 100Ω LCD12864 Respack-8(560Ω) 1K 4.7K DS1302 DS18B20 BUTTON 双列直插式40引脚IC插座 USB接口
4.1.3 硬件系统组装与调试
按图4-1所示数码日历钟硬件系统电路原理图所示,先在电路板上规划好元器件布局,按照规划好的布局依次进行元器件的排列与插装,再按照规范的焊接工艺要求依次对元器件进行焊接,直到所有的元器件连接并焊完为止。值得说明的是:单片机属于本系统中的“贵重品”,不宜直接将单片机焊在电路板上,而是在电路板上焊接一个40引脚的双列直插式通用IC插座,调试时再直接把单片机插在该插座上即可。
通电调试之前先用万用表检查各种电源线与地线之间是否有短路现象。经检查没有短路现象时,再给硬件系统加电,检查所有插座或元器件的电源源是否有符合要求的电压值、接地端电位是否为0。插上单片机芯片,接通电源,用万用表测量单片机各脚电压是否正常,用示波器测试单片机的第18脚(XTAL2)、第19脚(XTAL1)、第30脚(ALE)是否有正常波形,如果有则表明时钟电路已经起振。
-43-
4 系统设计与调试 河南理工大学毕业设计论文
4.2 软件系统设计与调试
4.2.1软件系统设计
软件设计流程图如图4-2所示,各模块源程序参考代码见上一章,此处不再重复。
图4-2 数码日历钟软件系统设计流程图
-44-
河南理工大学毕业设计论文 4 系统设计与调试
以下给出主函数部分的源代码: main()
{ unsigned int t=0;
// 无符号整型变量t用于存放读取到的温度转换结果的全部数据,共两个字节
unsigned char TempZh,TempXs; // 无符号字符型变量TempZh、TempXs分别用于存放温度转换结果的整数部分和小数部分
init(); // 主程序初始化,主要是初始化固定显示的字符(此后不需再做变化)及温度初始值
init_lcd(); // 液晶初始化,设定工作模式,8位数据总线,5*7点阵,开显示,关光标,DDRAM地址指针递加计数,光标右移,
init_timer();
// 初始化定时器,设定工作模式及定时器初始值,开中断,启动定时器T0计数
while (1) // 主循环
{ keyscan( ); // 扫描键盘有无按键按下
chaifen( ); // 拆分年月日时分秒的各位,以便送液晶显示。 display( ); // 调用液晶显示函数 if(ReadTempFlag==1)
//如果到读温度时间,则读取温度转换结果并加以处理,送液晶显示 { ReadTempFlag=0; // 将读温度标志位归零
DS18B20( ); // 调用温度传感器的工作主程序,以便完成温度转换 t=t|c2; t=t<<8; t=t|c1;
if(t&0x8000) // 如果获取到的温度值为负值 t =~t; // 取反
t=t+1; // 加1,还原为原码
{ temp1[9]='-'; // 在此处显示负号
}
else temp1[9]=' '; // 如果读取到的温度值为正值,则正号不显示 TempXs=c1&0x0f; // 获取温度转换结果的小数部分 TempXs=TempXs*5/8; //处理温度转换结果的小数部分 TempZh=c2<<4|c1>>4; // 获取温度转换结果的整数部分 if(TempZh/10==0) temp1[10]=' ';
// 若温度的绝对值不到十度,则十位上不显示
else temp1[10]='0'+TempZh/10; // 十位温度
-45-
4 系统设计与调试 河南理工大学毕业设计论文
temp1[11]='0'+TempZh%10; //个位温度
temp1[13]='0'+TempXs; //温度的小数部分(由于温度伟感器测温有较大误差,无需保留多位小数,故本程序中只保留一位小数)
} } }
4.2.2 软件系统调试与硬件仿真
在Keil C软件中建立工程,将源程序添加到工程中,经编译无误后生成扩展名为“*.hex”的目标程序,在Keil C软件中设置硬件仿真选项,进行硬件仿真运行,逐个检查各程序模块运行是否正确(先检查显示模块,再检查实时时钟模块是否走时正常,再检查各个按键的功能是否正常,重点检查各个特殊日期调整时会不会出现非法日期,调整日期时星期显示是否正确,最后检查温度传感器能否正常工作、所测温度是否正常。最后将所有模块联调,仿真运行调试无误后将目标程序下载到实物单片机中,观察运行结果与仿真运行结果是否一致,如有问题再修改程序源代码。
将日期分别调整为“1949年10月1日”、“2008年8月8日”、“2012年4月21日”,显示结果分别如图4-3、4-4、4-5所示。
图4-3 “2000年1月1日”显示效果图
图4-4 “2008年8月8日”显示效果图 图4-5 “2014年4月19日”显示效果图
-46-
河南理工大学毕业设计论文
5、结束语
由于本人才疏学浅,加之时间和精力有限,再加上受论文篇幅的限制,本设计中的很多功能还不够完善,本文的理论研究和实际制作都有待今后进一步深化和拓展,需大力加强,还需要笔者在今后的工作、学习中进行更深入的研究。通过设计与调试数码日历钟,进一步提高了我的工程实践能力,并对以前所学的单片机知识加以梳理、总结,并应用到实际开发中,使自己所掌握的知识得到了巩固和加强,这就是我这次毕业设计的最大收获。
本设计制作存在的主要问题和需要进一步开展的工作有: (1) 系统时间有误差,可采用补偿方式予以修正。
(4) 功能尚不够完善,如果再增加整点报时、定时闹铃等功能,则将设计出一个更为实用的数码日历钟。
(5) 如将本作品嵌入在镜框或其他工艺品中,将使其更加美观,又可作为实用的室内装饰品。
可以预料,随着单片机技术的不断发展,新产品、新思路将会不断出现,基于51单片机的数码日历钟系统的开发将更趋实用,功能也将不断完善。
-47-
4 系统设计与调试 河南理工大学毕业设计论文
参考文献
[1]梁洁婷.单片机原理及应用[M].北京:高等教育出版社.2006.
[2]金杰.新编单片机技术应用项目教程[M].北京:电子工业出版社.2009. [3]舒伟红.单片机原理与实训教程[M].北京:科学出版社,2008. [4]谭浩强.C程序设计[M].北京:清华大学出版社,2006.5.
[5]郭天祥.新概念51单片机C语言教程(入门、提高、开发、拓展全攻略)[M].北京:电子工业出版社,2009,12.
[6]金杰.MCS-51单片机C语言程序设计与实践[M].北京:电子工业出版社,2011. [7]雷林均.单片机控制装置安装与调试 [M].北京:电子工业出版社,2011. [8]周永东.单片机技术及应用(C语言版)[M].北京:电子工业出版社,2012. [9]谢龙汉.Proteus电子电路设计与仿真[M].北京:电子工业出版社,2012. [10] 白炽贵.单片机C语言案例教程[M].北京:电子工业出版社,2010.
[11] 周兴华.手把手教你学单片机(第2版)[M].北京:北京航空航天大学出版社,2007. [12] Atmel Microcontroller Handbook,2001.
[13] 张毅刚.新编MCS-51单片机应用设计[M].哈尔滨:哈尔滨工业大学出版社,2003. [14] 林立等.单片机原理及应用——基于Proteus和Keil C[M].北京:电子工业出版社,2011. [15] 杨暾等.单片机技术及应用——基于Proteus仿真的C语言程序设计[M].北京:电子工业出版社,2012.
[16] 孙焕铭等.51单片机C程序应用实例详解[M].北京:北京航空航天大学出版社,2011.
-48-
河南理工大学毕业设计论文
致 谢
基于51单片机的数码日历钟的设计与制作及毕业设计论文的撰写是在我的指导老师吴云志老师的精心指导下完成的,在我的学业和毕业设计与制作、毕业设计论文中无不倾注着吴老师辛勤的汗水和心血。本文从设计选题到最后论文定稿成文,吴老师一直给予了悉心指导,吴老师严谨的治学态度、渊博的知识、无私的奉献精神、严谨求实的作风,使我深受启迪和教益。从尊敬的老师身上,我不仅学到了扎实、宽广的专业知识,也学到了很多做人的道理。在此,我要向吴云志老师致以最衷心的感谢和深深的敬意。
另外,我还要感谢在高职阶段学习期间,辛勤教导我的各位师长,是你们的传道、授业、解惑使我增长了知识,让我受益匪浅。学友们的无私帮助也让我感激不尽,你们在我撰写论文期间提供了很多无私的帮助,使我开拓了思路,增加了一些新的知识,你们的鼓励和帮助永远是我前进的动力。在此,我谨向所有关心和帮助过我的各位老师、同学和朋友们表示由衷的感谢!今后,我将更加努力地学习和工作,以更加出色的成绩回报你们!
最后,我衷心地感谢在百忙之中评阅论文和参加答辩的各位老师!
张威振 2014年4月18日
49
因篇幅问题不能全部显示,请点此查看更多更全内容