电子综合设计总结报告

电子综合设计总结报告

课题:多功能电子数字时钟

成员:岳雪凌、闫蕾芳、周天琪

二零一三年六月二十日

于单片机的万年历设计

摘 要

随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。目前,单片机技术的应用产品已经走进了千家万户。电子万年历的出现给人们的生活带来了诸多方便。

本设计是一个基于STC89C52RC单片机的日历显示系统,本设计能显示公历年、月、日,以及时、分、秒、温度、星期等信息,而且还提供了农历信息,具有调整时间,温度采集,闹钟及个性化的闹铃等功能。系统所用的时钟日历芯片DS1302具有高性能、低功耗、接口简单的特点,使本系统电路简化,编程方便,同时功能也很强。采用STC89C52RC单片机的万年历系统可以很好的改善传统采用模拟电路引起的计时不准确,不可靠,一致性差等问题。此系统计时精确,价格低廉,可以广泛应用在生活,学习和工作等任何领域,并且起到重要作用。

关键词:万年历;单片机;时钟芯片;温度芯片;

目 录

摘 要

第一章 引 言

1.1 概述

1.2 单片机的简介

第二章 方案设计与论证

2.1 单片机芯片设计与论证

2.2 电源模块设计与论证

2.3 按键控制模块设计与论证

2.4 时钟模块设计与论证

2.5 温度采集模块设计与论证

2.6 显示模块模块设计与论证

第三章 系统的硬件设计

3.1 主控芯片AT89S52与最小外围系统

3.1.1 AT89S52的概述

3.1.2 AT89S52最小系统的设计7

3.2 时钟芯片DS1302接口设计与性能分析

3.2.1 DS1302性能简介

3.2.2 DS1302接口电路设计

3.3 温度芯片DS18B20接口设计与性能分析

3.3.1 DS18B20性能简介

3 基于单片机电子万年历设计

3.3.2 DS18B20接口电路设计

3.3.3 DS18B20的工作时序

3.4 闹钟模块接口设计与性能分析

3.4.1 AT24C02器件使用

3.4.2 接口电路设计

3.5 LCD显示模块

3.5.1 LCM1602的特性及使用说明

3.5.2 LCM1602与MCU的接口电路

3.6 按键模块设计

第四章 软件设计

4.1 软件总体部分的设计

4.2 LCD驱动及液晶显示

4.3 按键识别及处理

4.4 温度数据采集

4.5 时间数据采集

4.6 闹钟程序

第五章 系统的调试

总结

参考文献

附录A 设计原理图

附录B 源程序

4

第一章 引 言

1.1 概述

随着电子技术的发展,人类不断研究,不断创新纪录。万年历目前已经不再

局限于以书本形式出现。以电脑软件或者电子产品形式出现的万年历被称为电子

万年历。与传统书本形式的万年历相比,电子万年历得到了越来越广泛的应用,

采用电子时钟作为时间显示已经成为一种时尚。目前市场上各式各样的电子时钟

数不胜数,但多数是只针对时间显示,功能单一不能满足人们日常生活需求。

本文提出了一种基于STC89C52RC单片机的万年历设计方案,利采用一个LCD

显示。本方案以STC89C52RC单片机作为主控核心,与时钟芯片DS1302、温度芯

片DS18B20、闹钟模块、闹钟设置存储模块、按键、LCD显示等模块组成硬件系

统。在硬件系统中设有4个独立按键和一个LCD显示器,能显示丰富的信息,根

据使用者的需要可以随时对时间进行校准、选择时间、星期、温度显示等,综上

所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多

优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

1.2 单片机的简介

单片机是一种集成电路芯片。它采用超大规模技术将具有数据处理能力的微

处理器(CPU)、存储器(含程序存储器ROM和数据存储器RAM)、输入、输出接

口电路(I/O接口)集成在同一块芯片上,构成一个即小巧又很完善的计算机硬件

系统,在单片机程序的控制下能准确、迅速、高效地完成程序设计者事先规定的

任务。所以说,一片单片机芯片就具有了组成计算机的全部功能。

然而单片机又不同于单板机(一种将微处理器芯片、存储器芯片、输入输出

接口芯片安装在同一块印制电路板上的微型计算机),单片机芯片在没有开发前,

它只是具备功能极强的超大规模集成电路,如果对它进行应用开发,它便是一个

小型的微型计算机控制系统,但它与单板机或个人电脑(PC机)有着本质的区别。

不同的单片机有着不同的硬件特征和软件特征,即它们的技术特征均不尽相

同,硬件特征取决于单片机芯片的内部结构,用户要使用某种单片机,必须了解

该型产品是否满足需要的功能和应用系统所要求的特性指标。这里的技术特征包

括功能特性、控制特性和电气特性等等,这些信息需要从生产厂商的技术手册中

得到。软件特征是指指令系统特性和开发支持环境,指令特性即我们熟悉的单片

机的寻址方式,数据处理和逻辑处理方式,输入输出特性及对电源的要求等等。

开发支持的环境包括指令的兼容及可移植性,支持软件(包含可支持开发应用程

序的软件资源)及硬件资源。要利用某型号单片机开发自己的应用系统,掌握其

结构特征和技术特征是必须的。

单片机控制系统能够取代以前利用复杂电子线路或数字电路构成的控制系

统,可以以软件控制来实现,并能够实现智能化,现在单片机控制范畴无所不在,

例如通信产品、家用电器、智能仪器仪表、过程控制和专用控制装置等等,单片

机的应用领域越来越广泛。

第二章 方案设计与论证

按照系统设计的要求,初步确定系统由电源模块、时钟模块、显示模块、键

盘接口模块、温度测量模块和闹钟模块共六个模块组成,电路系统构成框图如图

2.1

图2.1 硬件电路框图

2.1 单片机芯片设计与论证

方案一:

采用STC89C51RC芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存

储空间,能于3V的超低电压工作,而且与MCS-51系列单片机完全兼容,但是运用于

电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序

的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造

成一定的损坏。

方案二:

采用STC89C52RC芯片作为硬件核心,采用Flash ROM,能以3V的超低电压工

作,而且与MCS-51系列单片机完全兼容,该芯片内部存储器为8KB ROM 存储

空间。同样具有STC89C52RC的功能,且具有在线编程可擦除技术,当在对电路

进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要

对芯片多次拔插,所以不会对芯片造成损坏。

综合考虑,采用STC89C52RC作为主控芯片。

2.2 电源模块设计与论证

方案一:采用市电经变压器降压成5V电源,为MCU及外部电路提供电源,

能提供较为稳定的电压及足够的功率,制作简单,成本较高、笨重,不利于便携

设备携带。

方案二:采用USB电源线接电脑USB口为系统提供5V电源,携带方便,价

格便宜。

考虑系统为一个便携式用品,方案一不便于携带,故采用方案二。

2.3 按键控制模块设计与论证

方案一:采用矩阵键盘,由于按键多可实现数值的直接键入,但在系统中需

要CPU不间断的对其端口扫描。

方案二:采用独立按键,查询简单,程序处理简单,可节省CPU资源。

因系统中所需按键不多,为了释放更多的CPU占有时间,故采用方案二。

2.4 时钟模块设计与论证

方案一:直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、

星期、时、分、秒计数。采用此种方案虽然减少芯片的使用,节约成本,但是,

实现的时间误差较大。

方案二:采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟

芯片,可自动对秒、分、时、日、周、月、年以及闰年补偿的年进行计数,而且

精度高,位的RAM作为数据暂存区,工作电压2.5V~5.5V范围内,2.5V时耗电小

于300nA.

综合考虑制作难度及精度,故采用方案二。

2.5 温度采集模块设计与论证

方案一:采用温度传感器(如热敏电阻或AD590),再经AD转换得到数字

信号,精度较准,但价格昂贵,电路较复杂。

方案二:采用数字式温度传感器DS18B20,它能直接读出被测温度,并且可

根据实际要求通过简单的编程实现9-12位的数字值读数方式,但准确度不高,

误差最大达2度。

综合考虑,采用方案二,用DS18B20温度芯片,采用单总线访问,降低成

本、降低制作难度且可节省单片机宝贵的GPIO资源。

2.6 显示模块模块设计与论证

方案一:采用静态显示方法,静态显示模块的硬件制作较复杂及功耗大,要

用到多个移位寄存器,但不占用端口,只需两根串口线输出。

方案二:采用动态显示方法,动态显示模块的硬件制作简单,段扫描和位扫

描各占用一个端口,总需占用单片机14个端口,采用间断扫描法功耗小、硬件

成本低及整个硬件系统体积相对减小。

方案三:采用LCD的方法,具有硬件制作简单可直接与单片机接口,显示内容多,

功耗小,成本低等优点,LCM1602可显示32个字符,采用LCD的缺点是亮度不够。

比较以上三种方案:方案一硬件复杂体积大、功耗大;方案二硬件简单、功

耗小;方案三硬件简单,显示内容多,功耗小,成本低等。本系统设计要求达到功

耗小、体积小、成本低,显示信息多等要求,权衡三种方案,选择方案三。

第三章 系统的硬件设计

3.1 主控芯片STC89C52RC与最小外围系统

3.1.1 STC89C52RC的概述

STC89C52RC 单片机是以51内核为主的系列单片机,STC单片机是宏晶生

产的单时钟/机器周期的单片机,是高速、低功耗、超强抗干扰的新一代8051单

片机,指令代码完全兼容传统8051,但速度快8—12倍,内部集成MAX810专

用复位电路。4路PWM 8路高速10位A、D转换,针对电机控制,强干扰场合。

STC89C52RC单片机引脚如下图:

STC89C52RC单片机主要性能

●高速:1 个时钟/ 机器周期,增强型8051 内核,速度比普通8051 快8~12 倍

●宽电压:5.5~3.8V,2.4~3.8V(STC12LE5410AD 系列)

●低功耗设计:空闲模式,掉电模式(可由外部中断唤醒)

●工作频率:0~35MHz,相当于普通8051:0~420MHz 实际可到48MHz,相当

于8051: 0~576MHz

●时钟:外部晶体或内部RC 振荡器可选,在ISP 下载编程用户程序时设置

● 16K 字节片内Flash 程序存储器,擦写次数10 万次以上

● 512 字节片内RAM 数据存储器

●芯片内EEPROM 功能

● ISP / IAP,在系统可编程/ 在应用可编程,无需编程器/ 仿真器

● 10 位ADC,8 通道, STC12C5A16S2 系列为8 位ADC。4 路PWM 还可当4 路

D/A 使用

● 2 个硬件16 位定时器,兼容普通8051 的定时器。4 路PCA 还可再实现4 个

定时器

●硬件看门狗(WDT)

●高速SPI 通信端口

●全双工异步串行口(UART),兼容普通8051 的串口

●先进的指令集结构,兼容普通8051指令集;4 组8 个8 位通用工作寄存器(共

32 个通用寄存器);有硬件乘法/ 除法指令

●通用I/O 口(27/23/15 个),复位后为: 准双向口/ 弱上拉(普通8051 传统

I/O 口)。可设置成四种模式:准双向口/ 弱上拉,推挽/ 强上拉,仅为输入/ 高

阻,开漏每个I/O 口驱动能力均可达到20mA,但整个芯片最大不得超过55mA。

3.1.2 AT89S52最小系统的设计

图3.2单片机最小系统

(1) 复位电路

上电自动复位通过外部复位电路的电容C5的充电来实现,只要电源VCC的

上升时间不超过1ms,就可以实现自动上电复位。

(2) 时钟振荡电路

考虑系统运行速度,采用12MHZ的石英晶振,并使用两个小电容作为微调

电容,具体设计见图3.2。

3.2 时钟芯片DS1302接口设计与性能分析

3.2.1 DS1302性能简介

DS1302是Dallas公司生产的一种实时时钟芯片。它通过串行方式与单片机

进行数据传送,能够向单片机提供包括秒、分、时、日、月、年等在内的实时时

间信息,并可对月末日期、闰年天数自动进行调整;它还拥有用于主电源和备份

电源的双电源引脚,在主电源关闭的情况下,也能保持时钟的连续运行。另外,

它还能提供31字节的用于高速数据暂存的RAM。

DS1302时钟芯片内主要包括移位寄存器、控制逻辑电路、振荡器。DS1302

与单片机系统的数据传送依靠RST,I/O,SCLK三根端线即可完成。其工作过程

可概括为:首先系统RST引脚驱动至高电平,然后在SCLK时钟脉冲的作用下,

通过I/O引脚向DS1302输入地址/命令字节,随后再在SCLK时钟脉冲的配合下,

从I/O引脚写入或读出相应的数据字节。因此,其与单片机之间的数据传送是十分

容易实现的,DS1302的引脚排列及内部结构图如图3.3:

DS1302引脚说明:

X1,X2 32.768kHz晶振引脚

GND 地线

RST 复位端

I/O 数据输入/输出端口

SCLK 串行时钟端口

VCC1 慢速充电引脚

VCC2 电源引脚 图3.3 DS1302管脚

3.2.2 DS1302接口电路设计

1、 时钟芯片DS1302的接口电路及工作原理:

32.1.2.3

图3.4 DS1302与MCU接口电路

图3.4为DS1302的接口电路,其中Vcc1为后备电源,Vcc2为主电源。VCC1

在单电源与电池供电的系统中提供低电源并提供低功率的电池备份。VCC2在双

电源系统中提供主电源,在这种运用方式中VCC1连接到备份电源,以便在没有

主电源的情况下能保存时间信息以及数据。

DS1302由VCC1或VCC2 两者中较大者供电。当VCC2大于VCC1+0.2V时,

VCC2给DS1302供电。当VCC2小于VCC1时,DS1302由VCC1供电。

DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置 “0”,接

着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图3.5所示。表-1为

DS1302的控制字,此控制字的位7必须置1,若为0则不能对DS1302进行读写

数据。对于位6

,若对时间进行读/写时,CK=0,对程序进行读/写时RAM=1。位

1至位5指操作单元的地址。位0是读/写操作位,进行读操作时,该位为1;进

行写操作时,该位为0。控制字节总是从最低位开始输入/输出的。表-2为DS1302

的日历、时间寄存器内容:“CH”是时钟暂停标志位,当该位为1时,时钟振荡器

停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。“WP”是写保护

位,在任何的对时钟和RAM的写操作之前,“WP”必须为0。当“WP”为1时,写

保护位防止对任一寄存器的写操作。

表1 DS1302的控制字格式

3、数据输入输出(I/O)

在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,

数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK

脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。如下图3.5

所示。

图3.5 DS1302读/写时序图

4、DS1302的寄存器

DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据

位为BCD码形式,其日历、时间寄存器及其控制字见表2。

表2 DS1302的日历、时间寄存器

此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存

器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器

外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM

单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,

其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方

式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。

3.3 温度芯片DS18B20接口设计与性能分析

3.3.1 DS18B20性能简介

1.DS18B20的主要特性

DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能

温度传感器,与传统的热敏电阻等元件相比,它能直接读出被测温度,并且可根

据实际要求通过简单的编程实现9-12位的数字值读数方式。现场温度直接以

线总线

温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。与前一代

产品不同,新的产品支持3V~5.5V的电压范围,使系统设计更灵活、方便。其

性能特点可归纳如下:

1) 独特的单线接口仅需要一个端口引脚进行通信;

2) 测温范围在-55℃到125℃,分辨率最大可达0.0625℃;

3) 采用了3线制与单片机相连,减少了外部硬件电路;

4) 零待机功耗;

5) 可通过数据线供电,电压范围在3.0V-5.5V;

6) 用户可定义的非易失性温度报警设置;

7) 报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件;

8) 负电压特性,电源极性接反时,温度计不会因发热烧毁,只是不能正

常工作。

2.DS18B20工作原理

DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数

因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。 DS18B20测

温原理如图3.6所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产

生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显

改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在

-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图3.6中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。

图3.6 DS18B20测温原理 图3.7温度传感器DS18B20接口电路 3.3.2 DS18B20接口电路设计

如3.7图所示,该系统中采用数字式温度传感器DS18B20,具有测量精度高,电路连接简单特点,此类传感器仅需要一条数据线进行数据传输,用P2.3与DS18B20的DQ口连接,Vcc接电源,GND接地。 3.3.3 DS18B20的工作时序 1、复位时序图

2、 读时序图

图3.9读时序图

3、写时序图

图3.10 写时序图

3.4 闹钟模块接口设计与性能分析

此部分硬件上利用AT24C02存储闹钟时间,普通蜂鸣器作为闹铃播放器件。 3.4.1 AT24C02器件使用

1、AT24C02的特性:

1) 与400KHz I2C 总线兼容 2) 到6.0 伏工作电压范围 3) 低功耗CMOS 技术

4) 写保护功能当 WP 为高电平时进入写保护状态 5) 自定时擦写周期

6) 1,000,000 编程/擦除周期 7) 8 脚DIP SOIC 或TSSOP 封装 8) 温度范围商业级工业级和汽车级 2、AT24C02功能说明

AT24C02支持I2C 总线数据传送协议,I2C 总线协议规定任何将数据传送到总线的器件作为发送器,任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据,发送或接收的模式通过器件地址输入端A0、A1 和A2 可以实现将最多8个24WC01和24WC02 器件连接到总线上。

管脚描述如下:

A0 A1 A2 器件地址选择 SDA 串行数据/地址

SCL 串行时钟 图3.11 AT24C02管图 WP 写保护

VCC/VSS +1.8V~6.0/地 3、工作时序

1)总线时序 2)写周期时序

图3.12 总线时序 图3.12写周期时序

3)起始/停止时序 4)应答时序

图3.13 起始/停止时序 图3.14 应答时序

5)立即地址读时序

图3.15 立即地址读时序

3.4.2 接口电路设计

AT24C02与单片机的接口电路如图3.165所示:

3.16 AT24C02与MCU的接口电路

3.5 LCD显示模块

3.5.1 LCM1602的特性及使用说明

1、 LCM1602的接口信号说明如表3:

2

、基本操作时序如下:

1)读状态:RS=L,RW=H,E=H

2)写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲 3)读数据:RS=H,RW=H,E=H

4)写数据:RS=H,RW=L,D0~D7=数据,E=高脉冲 3、初始化设置

1)显示模式设置如表4:

表4显示模式设置

2)显示开/关及光标设置如表5:

表5 显示开/关及光标设置

3.5.2 LCM1602与MCU的接口电路

接口电路如图3.16所示:

LCD的D0~D7分别接单片机的的P0口,作为数据线,因为P0口内部没有上拉电阻,所以外部另外加上10K的上拉电阻;P2.0—P2.2分别接LCD的RS、RW、E三个控制管脚;RV1用来调节LCD的显示灰度;BLK、BLA为背光的阴极和阳极,接上相应电平即点亮背光灯(图中未画出)。

.4

.5

.6

.7

图3.16 LCM1602与单片机接口电路 图3.17 按键电路

3.6 按键模块设计

如图3.17所示。

本系统用到了4个独立按键,此种接法查询简单,程序处理简单,可节省CPU资源, 4个独立按键分别与单片机的P2.4、P2.5、P2.6、P2.7接口相连。

S1——SET(时间设置键),S2——UP键,S3——DOWN键,S4——SET1(闹钟设置键)。

SET键:按下SET键进入时间校准状态,按一下进入秒调整,两下分调整,依此类推可进行各年月日,时分秒以及星期的校准;

UP键:当SET键按下时,UP进行SET选定项(如:小时)的加操作;

DOWN键:当SET键按下时,DOWN进行SET选定项(如:小时)的减操作; SET1键:当SET键按下时,此键功能为设置闹钟时间和开关闹钟功能。

第四章 软件设计

整个软件系统采用C51编程,主要实现以下功能: 1) LCD的驱动 2) 时间数据的采集 3) 闹铃的设置 4) 温度的采集 5) 按键的识别处理

4.1 软件总体部分的设计

程序从main()主函数开始运行,随后对LCD、DS18B20、DS1302、闹钟模块等器件进行初始化操作并对标志位赋初值,随后进入while(1)循环中运行按键扫描程序及液晶显示程序,详细程序见附录B。 (1) 主程序流程图如图4.1所示:

(2)

图4.1 主函数流程图

4.2 LCD驱动及液晶显示

1、LCD驱动

LCD的驱动包括初始化操作、写指令、写数据、显示模块的设定等操作。LCM1602有以下几个基本时序:

1)读状态:RS=L,RW=H,E=H

2)写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲 3)读数据:RS=H,RW=H,E=H

4)写数据:RS=H,RW=L,D0~D7=数据,E=高脉冲

驱动函数是根据这几个基本时序来完成的,下面是LCD的几个主要驱动函数(详细见附录):

1)LCD_Write() 功能:LCD写指令/数据 2)LCD_Initial() 功能:LCD初始化

3)GotoXY(unsigned char x, unsigned char y) 功能:字符显示的位置 4)Print(unsigned char *str) 功能:输出字符串到LCD 2、液晶显示模块流程图,如图4.2所示:

图4.2液晶显示模块流程图 图4.3温度采集模块流程图

4.3 按键识别及处理

本设计中按键采用查询法识别按键,程序简单。本系统中含有四个调整按键,分别命名为SET、UP、DOWN、SET1。在主函数里面查询SET、SET1P两个按键是否按下,UP、DOWN键的功能由SET和SET1键激活。这样设计可以减少CPU的工作量,下面简单介绍本设计中键盘扫描程序(以伪代码的形式),详细见附录B中 4.4 温度数据采集

由于DS18B20单线通信功能为分时完成,有严格的时隙概念,因此读\写时序很重要[12]。系统对DS18B20的各种操作必须按协议进行。操作协议为:初始化DS18B20(发复位脉冲)——发ROM功能命令——发存储操作命令——处理数据。

根据单总线操作协议,首先要对DS18B20进行初始化,而初始化有严格的时序控制,如图3.6所示,即总线控制器(TX)发出一个复位脉冲(至少480us的低电平),然后释放总线进入接收状态,总线由5.1K上拉电阻上拉为高电平,探测到I/O引脚上的上升沿后,DS18B20等待15us~60us后,然后发出一个存在脉冲(60us~240us的低电平信号)。下面是几个驱动函数:

1)Init_DS18B20(void) 功能:DS18B20初始化 2)ReadTemp(void) 功能:读取温度值 温度采集模块流程图如图4.3所示。

4.5 时间数据采集

串行时钟芯片DS1302的主要组成部分:移位寄存器、控制逻辑、振荡器、实时时钟以及RAM。为了初始化任何的数据传送,把RST

置为高电平且把提供地址和命令信息的8位装入到移位寄存器。数据在SCLK的上升沿串行输入。无论是发生读周期还是写周期,也无论传送方式是单字节传送还是多字节传送,开始8位指定40个字节中的那个将被访问。在开始8个时钟周期把命令字装入移位寄存器之后,另外的时钟在读操作时输出数据,在写操作时输入数据。时钟脉冲的个数在单字节方式下为8加8,在多字节方式下为8加最大可达248的数。

DS1302时钟部分子程序主要涉及以下几个主要函数:

1)void DS1302InputByte(unsigned char d) 功能:实时时钟写入一字节(内部函数)

2)unsigned char DS1302OutputByte(void) 功能:实时时钟读取一字节(内部函数

3)Write1302() 功能:DS1302写入数据函数 4)Read1302() 功能:读取DS1302某地址的数 5)void DS1302_GetTime(SYSTEMTIME *Time)

功能:获取时钟芯片的时钟数据到自定义的结构型数组

4.6 闹钟程序

这一部分的实现是采用E2PROM存储器来储存闹钟信息,因为它具有掉电仍能保存数据的特性。所以本设计中把闹钟信息写先写入AT24C02存储器中,然后在程序中读出数据与当前时间进行比较,如果相等则发出闹钟警告。如果要对闹钟值进行修改,可通过几个按键进行,系统能根据用户的设定自动更新闹钟信息,图4.4是闹钟程序的流程图:

图4.4闹钟程序的流程图

第五章 系统的调试

调试分为硬件调试和软件调试。

硬件调试主要是检查线路板的焊接是否正确、连接是否正确,各模块之间的数据线是否导通。

软件调试主要有以下两种方法:

1) 将整个联合起来调试,对整个软件的功能进行验证;

2)分开调试,也就是将系统分成独立的小模块,然后分别对这些小模块写入程序调试。这样可以提高调试效率,也容易解决调试中出现的问题。

本系统采用分开调试方法调试了DS18B20和DS1302两个模块,并用LCD显示出了温度以及公历日期、时间,同时也实现了按键的简单调整;但整体调试的时候没有达到预期效果。

总结

论文首先对本设计作了简要描述,随后提出了不同的设计方案,经过论证最后确定该设计采用电源模块、时钟模块、显示模块、键盘接口模块、温度测量模块和闹钟模块共六个模块组成,接着分别从硬件系统和软件系统两方面对基于单片机的电子万年历设计作了详细论述,另外还简要介绍了一下系统的调试。

在整个设计过程中,硬件方面主要设计了STC89C52RC单片机的最小系统、DS1302接口电路、DS18B20接口电路、闹钟及LCD显示;软件方面借助各个渠道的资料,主要设计了阳历数据读取程序、阳历转阴历程序、温度采集程序、闹铃程序以及LCD显示程序;系统的调试主要是通过一块STC89C52RC开发板,再借助于Keil、STC以及少许自己搭建的外围电路实现的;再此过程中,分步调试时显示出了阳历的日期及时间,还有实时温度,集中调试时没有达到预期效果。但在此过程中培养了自己的动手能力。

此万年历具有读显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

附:参考文献

1.张萌.单片机应用系统开发综合实例[M]. 北京:清华大学出版社,2007.7 2.楼然苗.单片机课程设计指导[M]. 北京:北京航空航天大学出版社,2007.7

3.沈德金.MCS-51系列单片机接口电路与应用程序实例[M]. 北京:北京航空航天大学出版社,1991.4

4.朱思荣.51单片机实现公历与农历、星期的转换[Z].当当电子网

5.AT24WC01/02/04/08/16 1K/2K/4K/8K/16K 位串行E2PROM[D].广州周立功单片机有限公司 6.DS1302 Trickle Charge Timekeeping Chip datasheet[D] 7.马忠梅,籍顺心等.单片机的C语言应用程序设计[M].北京航空航天大学出版社, 2001年

8.陈明荧. 8051单片机课程设计实训教程[M].北京:清华大学出版社 9.何立民.单片机高级教程[M].北京:北京航空航天大学出版社,2003年 10.新编单片机原理与应用(第二版).西安电子科技大学出版社,2007.2 11. 李广弟. 单片机原理及应用[M] 北京航空航天大学出版社,2004年 12.王越明.电子万年历的设计[J].黑龙江科技信息,2004年

13.SCM1602 LCM 使用说明书[DB]长沙:长沙太阳人电子有限公司 14.赵亮. 单片机C语言编程与实例[M] 人民邮电出版社,2003年 15.http://www.mcu51.com 16.http://www.cnki.net 17.http://www.2lic.com

附录A 仿真电路图

附录B 源程序 #include #include

uchar code tabe1[]=

uchar code tabe2[]=

miao,fen,shi,nian,yue,ri,week,wendu_shi,wendu_ge,wendu_shu,variate,alarm_shi,alarm_fen,alarm_miao; uchar

flag=1,count=0,flag_up=0,flag_down=0,flag_alarm=0,alarm_on,alarm_count=0,done=0;

uint wendu; //定义IO

sbit DQ = P1^0; //ds18b20温度传送数据IO口 sbit ds1302_rst = P1^1; //1302复位 sbit ds1302_io = P1^2; //数据输入输出 sbit ds1302_sclk= P1^3; //串行时钟

sbit alarm_out = P3^6;

sbit lcd1602_rs = P2^0; // 1602命令、数据选择 sbit lcd1602_rw = P2^1; sbit lcd1602_e = P2^2;

sbit set = P2^4;

//选择按键

// 1602写

// 1602使能

sbit up = P2^5; //加 sbit down= P2^6; //减

sbit nao = P2^7;

sbit ACC0=ACC^0; sbit ACC7=ACC^7; //延时

void delay(uchar x) { uchar y,z; for(z=x;z>0;z--)

for(y=110;y>0;y--);

}

void delay1() { _nop_(); _nop_();

}

ds18b20_delay(uchar xus) //延时xus { while(xus--); }

/*******ds18b20温度控制程序***********/

void ds18b20_init() //DS18B20初始化 { uchar x=0; DQ=1;

ds18b20_delay(8); DQ=0;

ds18b20_delay(80); DQ=1;

ds18b20_delay(14);

x=DQ;

ds18b20_delay(20);

}

void write_onechar(uchar dat) //写一字节 {

uchar i; for(i=8;i>0;i--) { DQ=0;

if(dat&0x01==0x01) DQ=1;

else

DQ=0; ds18b20_delay(5); DQ=1;

ds18b20_delay(1); dat>>=1;

}

}

uchar read_onechar() //读一字节

{ uchar value=0,i; for(i=8;i>0;i--) {

value>>=1; DQ=0;

ds18b20_delay(1); DQ=1; if(DQ==1) value|=0x80;

else

value&=0x7f;

ds18b20_delay(4);

}

return value;

}

}

ds1302_sclk=1; //拉高sclk ACC>>=1;

uint read_wendu() //DS18B20读温度 uchar read_byte() { uchar a=0,b=0; uint wen=0x0000; ds18b20_init();

//初始化

write_onechar(0xcc);

// 跳过读序号列

号的操作 write_onechar(0x44); // 启动温度转换 ds18b20_delay(150); ds18b20_init();

//初始化

write_onechar(0xcc); //跳过读序号列号的操作

write_onechar(0xbe); //读取温度寄存器

等(共可读9个寄存器) 前两个就是温度 ds18b20_delay(150); b=read_onechar(); //读取温度值低位 a=read_onechar(); //读取温度值高位

wen=a;

wen=(wen

}

/*****ds1302时钟闹钟控制**********/ void write_byte(uchar dat) //写一字节 { uchar k;

ACC=dat;

for(k=8;k>0;k--) { ds1302_io=ACC0;

ds1302_sclk=0;

//拉低sclk

{

uchar k;

for(k=8;k>0;k--) { ACC7=ds1302_io;

ds1302_sclk=1; //拉高sclk ds1302_sclk=0; //拉低sclk

ACC>>=1; }

return ACC;

}

void ds1302_write(uchar add,uchar date) {

ds1302_rst=0;

ds1302_sclk=0; //在rst没拉高之前先把sclk置0 ds1302_rst=1; write_byte(add); write_byte(date);

ds1302_sclk=1; ds1302_rst=0;

}

uchar ds1302_read(uchar add) { uchar temp;

ds1302_rst=0;

ds1302_sclk=0; //在rst没拉高之前先把sclk置0

ds1302_rst=1; write_byte(add); temp=read_byte();

ds1302_sclk=1; ds1302_rst=0; return temp;

}

void ds1302_init() //ds1302初始化 { ds1302_rst=0; ds1302_sclk=1; ds1302_write(0x8e,0x00); //写允许

ds1302_write(0x80,0x58); ds1302_write(0x82,0x56); ds1302_write(0x84,0x23); ds1302_write(0x86,0x21); ds1302_write(0x88,0x12); ds1302_write(0x8a,0x02); ds1302_write(0x8c,0x10);

ds1302_write(0x90,0xa5); //充电 ds1302_write(0x8e,0x80); //写保护

}

/*********lcd1602***************/

void lcd_write_com(uchar com) //命令字写入lcd单元中 {

lcd1602_rw=0; delay1();

lcd1602_rs=0;// RW=1,RS=0,写LCD命令字 delay1();

P0=com; //将com中的命令字写入LCD

数据口 delay1();

lcd1602_e=1; //E端时序 delay1(); lcd1602_e=0; delay1(); lcd1602_rw=1; delay(5);

}

void lcd_write_date(uchar date) //数据写入lcd单元中 {

lcd1602_rw=0; delay1();

lcd1602_rs=1; // RW=0,RS=1,写LCD命令字 delay1();

lcd1602_e=1; // E端时序 delay1(); P0=date; // 将dat中的显示数据

写入LCD数据口 delay1(); lcd1602_e=0; delay1(); lcd1602_rw=1; delay(5); }

void lcd1602_init() //LCD初始化函数 { uchar lcdnum; P3=0xdf;

lcd_write_com(0x38);

lcd_write_com(0x0c); lcd_write_com(0x06); lcd_write_com(0x01); lcd_write_com(0x80);

for(lcdnum=0;lcdnum

uchar shi,ge; shi=date/10; ge=date%10;

lcd_write_com(0x80+0x40+add); lcd_write_date(0x30+shi); //写第一行数据 { lcd_write_date(tabe1[lcdnum]); delay(2);

}

lcd_write_com(0x80+0x40);

//写入第二行数据 for(lcdnum=0;lcdnum

}

}

/**************显示部分***************/

void write_time1(uchar add,uchar date) //日期送显示 {

uchar shi,ge; shi=date/10; ge=date%10;

lcd_write_com(0x80+add); lcd_write_date(0x30+shi); lcd_write_date(0x30+ge);

}

void write_time2(uchar add,uchar date) //时间送显示 {

lcd_write_date(0x30+ge);

}

uchar bcd_decimal(uchar bcd)//bcd转换十进制 { uchar decimal; decimal=bcd>>4;

decimal=decimal*10+(bcd&=0x0f);

return decimal;

}

void wendu_decimal(uint dat) //温度转换后送显示 { float temp;

temp=dat*0.625; //dat*0.0625*10

wendu_shi=temp/100;

//取十位 temp除不用定义类型

wendu_ge =((uint)temp)%100/10;

//取个位 temp求模要定义类型,为16位,故定义uint

wendu_shu=((uint)temp)%100%10;

//取小数

lcd_write_com(0x80+0x40+10); //送显示 lcd_write_date(0x30+wendu_shi); lcd_write_date(0x30+wendu_ge); lcd_write_date(0x2e);

lcd_write_date(0x30+wendu_shu);

lcd_write_date(0xdf); }

}

lcd_write_date('U'); lcd_write_date('N'); break;

//温度符号 }

void write_week(uchar we) //星期送显示 lcd_write_date(0x43);

{ lcd_write_com(0x80+0x0d); switch(we) { case 1: lcd_write_date('M'); lcd_write_date('0'); lcd_write_date('N');

break;

case 2: lcd_write_date('T'); lcd_write_date('U'); lcd_write_date('E');

break;

case 3: lcd_write_date('W'); lcd_write_date('E'); lcd_write_date('D');

break;

case 4: lcd_write_date('T'); lcd_write_date('H'); lcd_write_date('U');

break;

case 5: lcd_write_date('F'); lcd_write_date('R'); lcd_write_date('T');

break;

case 6: lcd_write_date('S'); lcd_write_date('A'); lcd_write_date('T');

break;

case 7: lcd_write_date('S');

/*********按键处理*************/

uchar key_bcd(uchar key_decimal) //转成ds1302所需的BCD码 { uchar temp;

temp=(((key_decimal/10)&0x0f)

decimal%10); return temp;

}

void key_up_down() //加减键处理 { if(up==0) { delay(2); flag_up=1;

//加 更新标志

while(!up); switch(count) { case 1: miao++; if(miao>59)

miao=0;

break;

case 2: fen++; if(fen>59)

fen=0;

break; case 3: shi++; if(shi>23)

shi=0;

break;

case 4: week++; if(week>7)

week=1;

break;

case 5: ri++; if(ri>31)

ri=1;

break;

case 6: yue++; if(yue>12)

yue=1;

break;

case 7: nian++; if(nian>99)

nian=0;

break;

}

}

if(down==0) //减键处理 { delay(2);

flag_down=1; //减更新标志

while(!down);

switch(count) { case 1: miao--; if(miao==255)

miao=59;

break;

case 2: fen--; if(fen==255)

fen=59;

break;

case 3: shi--; if(miao==255)

shi=23;

break;

case 4: week--; if(week

week=7;

break;

case 5: ri--; if(ri

ri=31;

break;

case 6: yue--; if(yue

yue=12;

break;

case 7: nian--;

if(nian==255)

nian=99;

break;

} }

}

/**********24c02时间模块******/

void alarm_ring() { if(alarm_on==1)

//alarm_on=1 为闹钟有效

{

if(shi==alarm_shi && fen==alarm_fen && miao==alarm_miao) flag_alarm=1; }

//闹钟时间到,闹钟标志位置1

if(flag_alarm==1) { uchar i,j,t; t=30;

for(i=0;i

alarm_out=~alarm_out; for(j=0;j

if(set==0 || up==0 || down==0 ||

nao==0) //闹钟响时,按任意键取消闹钟 { while(!set);

while(!up);

lcd_write_date(0x3a);

while(!down); while(!nao);

flag_alarm=0; alarm_out=1;

}

}

}

void c02_init() { c_init();

alarm_shi=c02_read_add(1); //读取闹钟时 delay(200);

alarm_fen=c02_read_add(2); //分 delay(200);

alarm_miao=c02_read_add(3); //秒

delay(200);

alarm_on =c02_read_add(4); //读取闹钟开关值,为0关,为1开 delay(200);

}

void alarm_huan() //按下闹钟键后,切换界面{ uchar num;

lcd_write_com(0x01); lcd_write_com(0x80);

for(num=0;num

//写第一行数据 { lcd_write_date(tabe3[num]); delay(2);

}

lcd_write_com(0x0f); write_time2(4,alarm_shi);

write_time2(7,alarm_fen);

lcd_write_date(0x3a); write_time2(10,alarm_miao); if(alarm_on==0) { lcd_write_com(0x80+0x40+13); lcd_write_date('O'); lcd_write_date('F'); lcd_write_date('F');

}

if(alarm_on==1) { lcd_write_com(0x80+0x40+13); lcd_write_date(' '); lcd_write_date('O'); lcd_write_date('N'); }

}

void key_set_alarm() {

if(set==0

&&

alarm_count==0

&&

flag_alarm==0) { delay(2); if(set==0) {

while(!set); //等待set释放

count++; //按set一下,count加1 if(flag==1) { done=1;

flag=0;

ds1302_write(0x8e,0x00); //写允许

ds1302_write(0x80,key_bcd(miao)|0x80); //BIT7为1,晶振停止工作

ds1302_write(0x8e,0x80); //写保护

}

}

}

if(nao==0 && count==0 && flag_alarm==0) { delay(2); if(nao==0) { while(!nao); alarm_count++; if(flag==1) { done=1; flag=0;

alarm_huan(); //切换界面

}

}

}

}

void keyjpress()

//按键处理

{ key_set_alarm();

if(count!=0)

//count不为0,进入时间调整扫描 {

switch(count) { case 1:do

{

lcd_write_com(0x0F); //显示光标,不闪烁

lcd_write_com(0x80+0x40+7);

key_up_down(); if(flag_up || flag_down)

{

flag_up=0; flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x80,key_bcd(miao) | 0x80); ds1302_write(0x8e,0x80); write_time2(6,miao);

lcd_write_com(0x80+0x40+7); //液晶写字

符后光标自动向右移动一位,把光标左移一位 }

}

while(count==2); break;

case 2:do {

lcd_write_com(0x80+0x40+4); key_up_down();

if(flag_up || flag_down) { flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x82,key_bcd(fen));

ds1302_write(0x8e,0x80);

write_time2(3,fen);

lcd_write_com(0x80+0x40+4);

}

}

while(count==3);

break; case 3:do { lcd_write_com(0x80+0x40+1); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00); ds1302_write(0x84,key_bcd(shi));

ds1302_write(0x8e,0x80); write_time2(0,shi);

lcd_write_com(0x80+0x40+1); }

}

while(count==4); break;

case 4: do {

lcd_write_com(0x80+0x0e); key_up_down(); if(flag_up || flag_down)

{

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x8a,key_bcd(week));

ds1302_write(0x8e,0x80); write_week(week); lcd_write_com(0x80+0x0e); }

}

while(count==5);

break; case 5:do {

lcd_write_com(0x80+9); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x86,key_bcd(ri)); ds1302_write(0x8e,0x80); write_time1(8,ri);

lcd_write_com(0x80+9);

} }

while(count==6); break;

case 6:do {

lcd_write_com(0x80+6); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x88,key_bcd(yue)); ds1302_write(0x8e,0x80);

write_time1(5,yue); lcd_write_com(0x80+6);

}

基于单片机电子万年历设计30

}

while(count==7); break;

case 7: lcd_write_com(0x80+3); key_up_down();

if(flag_up || flag_down)

{

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x8c,key_bcd(nian)); ds1302_write(0x8e,0x80);

write_time1(2,nian); lcd_write_com(0x80+3); }

break; case 8:

lcd_write_com(0x0c);

//调整结束,关闭显示光标 flag=1; done=0; count=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x80,key_bcd(miao)&0x7f);

//BIT7为0,晶振开始工作 ds1302_write(0x8e,0x80); break;

default:break;

}

}

if(alarm_count!=0) //闹钟按键扫描 {

switch(alarm_count)

{

lcd_write_com(0x80+0x40+15);

if(up==0) {

delay(2); if(up==0) {

while(!up); alarm_on=1;

lcd_write_com(0x80+0x40+13); lcd_write_date(' '); lcd_write_date('O'); lcd_write_date('N'); c02_write_add(4,alarm_on); delay(200);

lcd_write_com(0x80+0x40+15); }

} if(down==0) {

if(down==0); {

while(!down); alarm_on=0;

lcd_write_com(0x80+0x40+13);

lcd_write_date('O');

lcd_write_date('F');

lcd_write_date('F');

c02_write_add(4,alarm_on); delay(200);

lcd_write_com(0x80+0x40+15);

}

break;

case 2:

lcd_write_com(0x80+0x40+11); if(up==0 || down==0) { delay(2);

if(up==0)

{ while(!up); alarm_miao++; if(alarm_miao>59) alarm_miao=0;

} if(down==0)

{

while(!down); alarm_miao--;

if(alarm_miao==255) alarm_miao=59;

}

write_time2(10,alarm_miao); lcd_write_com(0x80+0x40+11); c02_write_add(3,alarm_miao); delay(200);

} break;

case 3:

lcd_write_com(0x80+0x40+8);

if(up==0 || down==0) {

delay(2);

if(up==0)

31

while(!up);

alarm_fen++; if(alarm_fen>59) alarm_fen=0;

}

if(down==0) {

while(!down); alarm_fen--; if(alarm_fen==255) alarm_fen=59;

}

write_time2(7,alarm_fen); lcd_write_com(0x80+0x40+8); c02_write_add(2,alarm_fen); delay(200);

}

break; case 4: lcd_write_com(0x80+0x40+5); if(up==0 || down==0) { delay(2); if(up==0) {

while(!up); alarm_shi++;

if(alarm_shi>23)

alarm_shi=0;

}

if(down==0)

{

alarm_shi--;

if(alarm_shi==255)

alarm_shi=23;

}

write_time2(4,alarm_shi);

lcd_write_com(0x80+0x40+5); c02_write_add(1,alarm_shi);

delay(200);

}

break; case 5:

alarm_count=0; lcd1602_init(); flag=1; done=0;

break;

} }

}

void xianshi() {

//读秒分时,日月年,星期

miao=bcd_decimal(ds1302_read(0x81)); fen =bcd_decimal(ds1302_read(0x83)); shi =bcd_decimal(ds1302_read(0x85));

ri =bcd_decimal(ds1302_read(0x87)); yue =bcd_decimal(ds1302_read(0x89)); nian=bcd_decimal(ds1302_read(0x8d));

week=bcd_decimal(ds1302_read(0x8b));

//送液晶显示

write_time2(6,miao);

32

write_time2(3,fen); write_time2(0,shi); write_time1(8,ri); write_time1(5,yue); write_time1(2,nian);

write_week(week);

//读温度

wendu=read_wendu();

//温度显示 wendu_decimal(wendu);

} main() { lcd1602_init();

ds18b20_init(); ds1302_init(); c02_init(); while(1) { if(done==1) {

keyjpress();

}

if(done==0) {

xianshi(); //取得并显示日历和时间 key_set_alarm(); alarm_ring(); }

}

}

//闹钟设置时间存储AT2402子程序: #ifndef _24c02

#define _24c02

#define uchar unsigned char #define uint unsigned int

/***********DS18B20管脚配置********/

sbit sda = P1^4;//24c02数据输入输出 sbit scl = P1^5; //24c02时钟

void c02_delay() { ;; }

void start() //开始信号 {

sda=1; c02_delay(); scl=1; c02_delay(); sda=0; c02_delay();

}

void stop() //停止 { sda=0; c02_delay(); scl=1; c02_delay(); sda=1; c02_delay();

}

void respons() //应答 { uchar i;

scl=1;

33

c02_delay();

while((sda==1)&&(i

//如sda=0或i>250,,跳出

scl=0; c02_delay();

}

void c_init() { sda=1; c02_delay(); scl=1; c02_delay();

}

void c02_write_byte(uchar date) //写一字节{ uchar i,temp; temp=date; for(i=0;i

scl=0;

c02_delay(); sda=CY; c02_delay(); scl=1; c02_delay();

} scl=0; c02_delay(); sda=1; c02_delay();

}

uchar c02_read_byte() //读一字节 { uchar i,k; scl=0; c02_delay(); sda=1; c02_delay(); for(i=0;i

{ scl=1; c02_delay(); k=(k

} return k;

}

void c02_write_add(uchar address,uchar date) //写

{ start();

c02_write_byte(0xa0); respons();

c02_write_byte(address); respons();

c02_write_byte(date); respons(); stop(); }

uchar c02_read_add(uchar address) //读

{ uchar date;

start();

34

c02_write_byte(0xa0); respons();

c02_write_byte(address); respons(); start();

c02_write_byte(0xa1);

}

respons();

date=c02_read_byte(); stop(); return date;

35

电子综合设计总结报告

课题:多功能电子数字时钟

成员:岳雪凌、闫蕾芳、周天琪

二零一三年六月二十日

于单片机的万年历设计

摘 要

随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。目前,单片机技术的应用产品已经走进了千家万户。电子万年历的出现给人们的生活带来了诸多方便。

本设计是一个基于STC89C52RC单片机的日历显示系统,本设计能显示公历年、月、日,以及时、分、秒、温度、星期等信息,而且还提供了农历信息,具有调整时间,温度采集,闹钟及个性化的闹铃等功能。系统所用的时钟日历芯片DS1302具有高性能、低功耗、接口简单的特点,使本系统电路简化,编程方便,同时功能也很强。采用STC89C52RC单片机的万年历系统可以很好的改善传统采用模拟电路引起的计时不准确,不可靠,一致性差等问题。此系统计时精确,价格低廉,可以广泛应用在生活,学习和工作等任何领域,并且起到重要作用。

关键词:万年历;单片机;时钟芯片;温度芯片;

目 录

摘 要

第一章 引 言

1.1 概述

1.2 单片机的简介

第二章 方案设计与论证

2.1 单片机芯片设计与论证

2.2 电源模块设计与论证

2.3 按键控制模块设计与论证

2.4 时钟模块设计与论证

2.5 温度采集模块设计与论证

2.6 显示模块模块设计与论证

第三章 系统的硬件设计

3.1 主控芯片AT89S52与最小外围系统

3.1.1 AT89S52的概述

3.1.2 AT89S52最小系统的设计7

3.2 时钟芯片DS1302接口设计与性能分析

3.2.1 DS1302性能简介

3.2.2 DS1302接口电路设计

3.3 温度芯片DS18B20接口设计与性能分析

3.3.1 DS18B20性能简介

3 基于单片机电子万年历设计

3.3.2 DS18B20接口电路设计

3.3.3 DS18B20的工作时序

3.4 闹钟模块接口设计与性能分析

3.4.1 AT24C02器件使用

3.4.2 接口电路设计

3.5 LCD显示模块

3.5.1 LCM1602的特性及使用说明

3.5.2 LCM1602与MCU的接口电路

3.6 按键模块设计

第四章 软件设计

4.1 软件总体部分的设计

4.2 LCD驱动及液晶显示

4.3 按键识别及处理

4.4 温度数据采集

4.5 时间数据采集

4.6 闹钟程序

第五章 系统的调试

总结

参考文献

附录A 设计原理图

附录B 源程序

4

第一章 引 言

1.1 概述

随着电子技术的发展,人类不断研究,不断创新纪录。万年历目前已经不再

局限于以书本形式出现。以电脑软件或者电子产品形式出现的万年历被称为电子

万年历。与传统书本形式的万年历相比,电子万年历得到了越来越广泛的应用,

采用电子时钟作为时间显示已经成为一种时尚。目前市场上各式各样的电子时钟

数不胜数,但多数是只针对时间显示,功能单一不能满足人们日常生活需求。

本文提出了一种基于STC89C52RC单片机的万年历设计方案,利采用一个LCD

显示。本方案以STC89C52RC单片机作为主控核心,与时钟芯片DS1302、温度芯

片DS18B20、闹钟模块、闹钟设置存储模块、按键、LCD显示等模块组成硬件系

统。在硬件系统中设有4个独立按键和一个LCD显示器,能显示丰富的信息,根

据使用者的需要可以随时对时间进行校准、选择时间、星期、温度显示等,综上

所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多

优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

1.2 单片机的简介

单片机是一种集成电路芯片。它采用超大规模技术将具有数据处理能力的微

处理器(CPU)、存储器(含程序存储器ROM和数据存储器RAM)、输入、输出接

口电路(I/O接口)集成在同一块芯片上,构成一个即小巧又很完善的计算机硬件

系统,在单片机程序的控制下能准确、迅速、高效地完成程序设计者事先规定的

任务。所以说,一片单片机芯片就具有了组成计算机的全部功能。

然而单片机又不同于单板机(一种将微处理器芯片、存储器芯片、输入输出

接口芯片安装在同一块印制电路板上的微型计算机),单片机芯片在没有开发前,

它只是具备功能极强的超大规模集成电路,如果对它进行应用开发,它便是一个

小型的微型计算机控制系统,但它与单板机或个人电脑(PC机)有着本质的区别。

不同的单片机有着不同的硬件特征和软件特征,即它们的技术特征均不尽相

同,硬件特征取决于单片机芯片的内部结构,用户要使用某种单片机,必须了解

该型产品是否满足需要的功能和应用系统所要求的特性指标。这里的技术特征包

括功能特性、控制特性和电气特性等等,这些信息需要从生产厂商的技术手册中

得到。软件特征是指指令系统特性和开发支持环境,指令特性即我们熟悉的单片

机的寻址方式,数据处理和逻辑处理方式,输入输出特性及对电源的要求等等。

开发支持的环境包括指令的兼容及可移植性,支持软件(包含可支持开发应用程

序的软件资源)及硬件资源。要利用某型号单片机开发自己的应用系统,掌握其

结构特征和技术特征是必须的。

单片机控制系统能够取代以前利用复杂电子线路或数字电路构成的控制系

统,可以以软件控制来实现,并能够实现智能化,现在单片机控制范畴无所不在,

例如通信产品、家用电器、智能仪器仪表、过程控制和专用控制装置等等,单片

机的应用领域越来越广泛。

第二章 方案设计与论证

按照系统设计的要求,初步确定系统由电源模块、时钟模块、显示模块、键

盘接口模块、温度测量模块和闹钟模块共六个模块组成,电路系统构成框图如图

2.1

图2.1 硬件电路框图

2.1 单片机芯片设计与论证

方案一:

采用STC89C51RC芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存

储空间,能于3V的超低电压工作,而且与MCS-51系列单片机完全兼容,但是运用于

电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序

的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造

成一定的损坏。

方案二:

采用STC89C52RC芯片作为硬件核心,采用Flash ROM,能以3V的超低电压工

作,而且与MCS-51系列单片机完全兼容,该芯片内部存储器为8KB ROM 存储

空间。同样具有STC89C52RC的功能,且具有在线编程可擦除技术,当在对电路

进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要

对芯片多次拔插,所以不会对芯片造成损坏。

综合考虑,采用STC89C52RC作为主控芯片。

2.2 电源模块设计与论证

方案一:采用市电经变压器降压成5V电源,为MCU及外部电路提供电源,

能提供较为稳定的电压及足够的功率,制作简单,成本较高、笨重,不利于便携

设备携带。

方案二:采用USB电源线接电脑USB口为系统提供5V电源,携带方便,价

格便宜。

考虑系统为一个便携式用品,方案一不便于携带,故采用方案二。

2.3 按键控制模块设计与论证

方案一:采用矩阵键盘,由于按键多可实现数值的直接键入,但在系统中需

要CPU不间断的对其端口扫描。

方案二:采用独立按键,查询简单,程序处理简单,可节省CPU资源。

因系统中所需按键不多,为了释放更多的CPU占有时间,故采用方案二。

2.4 时钟模块设计与论证

方案一:直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、

星期、时、分、秒计数。采用此种方案虽然减少芯片的使用,节约成本,但是,

实现的时间误差较大。

方案二:采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟

芯片,可自动对秒、分、时、日、周、月、年以及闰年补偿的年进行计数,而且

精度高,位的RAM作为数据暂存区,工作电压2.5V~5.5V范围内,2.5V时耗电小

于300nA.

综合考虑制作难度及精度,故采用方案二。

2.5 温度采集模块设计与论证

方案一:采用温度传感器(如热敏电阻或AD590),再经AD转换得到数字

信号,精度较准,但价格昂贵,电路较复杂。

方案二:采用数字式温度传感器DS18B20,它能直接读出被测温度,并且可

根据实际要求通过简单的编程实现9-12位的数字值读数方式,但准确度不高,

误差最大达2度。

综合考虑,采用方案二,用DS18B20温度芯片,采用单总线访问,降低成

本、降低制作难度且可节省单片机宝贵的GPIO资源。

2.6 显示模块模块设计与论证

方案一:采用静态显示方法,静态显示模块的硬件制作较复杂及功耗大,要

用到多个移位寄存器,但不占用端口,只需两根串口线输出。

方案二:采用动态显示方法,动态显示模块的硬件制作简单,段扫描和位扫

描各占用一个端口,总需占用单片机14个端口,采用间断扫描法功耗小、硬件

成本低及整个硬件系统体积相对减小。

方案三:采用LCD的方法,具有硬件制作简单可直接与单片机接口,显示内容多,

功耗小,成本低等优点,LCM1602可显示32个字符,采用LCD的缺点是亮度不够。

比较以上三种方案:方案一硬件复杂体积大、功耗大;方案二硬件简单、功

耗小;方案三硬件简单,显示内容多,功耗小,成本低等。本系统设计要求达到功

耗小、体积小、成本低,显示信息多等要求,权衡三种方案,选择方案三。

第三章 系统的硬件设计

3.1 主控芯片STC89C52RC与最小外围系统

3.1.1 STC89C52RC的概述

STC89C52RC 单片机是以51内核为主的系列单片机,STC单片机是宏晶生

产的单时钟/机器周期的单片机,是高速、低功耗、超强抗干扰的新一代8051单

片机,指令代码完全兼容传统8051,但速度快8—12倍,内部集成MAX810专

用复位电路。4路PWM 8路高速10位A、D转换,针对电机控制,强干扰场合。

STC89C52RC单片机引脚如下图:

STC89C52RC单片机主要性能

●高速:1 个时钟/ 机器周期,增强型8051 内核,速度比普通8051 快8~12 倍

●宽电压:5.5~3.8V,2.4~3.8V(STC12LE5410AD 系列)

●低功耗设计:空闲模式,掉电模式(可由外部中断唤醒)

●工作频率:0~35MHz,相当于普通8051:0~420MHz 实际可到48MHz,相当

于8051: 0~576MHz

●时钟:外部晶体或内部RC 振荡器可选,在ISP 下载编程用户程序时设置

● 16K 字节片内Flash 程序存储器,擦写次数10 万次以上

● 512 字节片内RAM 数据存储器

●芯片内EEPROM 功能

● ISP / IAP,在系统可编程/ 在应用可编程,无需编程器/ 仿真器

● 10 位ADC,8 通道, STC12C5A16S2 系列为8 位ADC。4 路PWM 还可当4 路

D/A 使用

● 2 个硬件16 位定时器,兼容普通8051 的定时器。4 路PCA 还可再实现4 个

定时器

●硬件看门狗(WDT)

●高速SPI 通信端口

●全双工异步串行口(UART),兼容普通8051 的串口

●先进的指令集结构,兼容普通8051指令集;4 组8 个8 位通用工作寄存器(共

32 个通用寄存器);有硬件乘法/ 除法指令

●通用I/O 口(27/23/15 个),复位后为: 准双向口/ 弱上拉(普通8051 传统

I/O 口)。可设置成四种模式:准双向口/ 弱上拉,推挽/ 强上拉,仅为输入/ 高

阻,开漏每个I/O 口驱动能力均可达到20mA,但整个芯片最大不得超过55mA。

3.1.2 AT89S52最小系统的设计

图3.2单片机最小系统

(1) 复位电路

上电自动复位通过外部复位电路的电容C5的充电来实现,只要电源VCC的

上升时间不超过1ms,就可以实现自动上电复位。

(2) 时钟振荡电路

考虑系统运行速度,采用12MHZ的石英晶振,并使用两个小电容作为微调

电容,具体设计见图3.2。

3.2 时钟芯片DS1302接口设计与性能分析

3.2.1 DS1302性能简介

DS1302是Dallas公司生产的一种实时时钟芯片。它通过串行方式与单片机

进行数据传送,能够向单片机提供包括秒、分、时、日、月、年等在内的实时时

间信息,并可对月末日期、闰年天数自动进行调整;它还拥有用于主电源和备份

电源的双电源引脚,在主电源关闭的情况下,也能保持时钟的连续运行。另外,

它还能提供31字节的用于高速数据暂存的RAM。

DS1302时钟芯片内主要包括移位寄存器、控制逻辑电路、振荡器。DS1302

与单片机系统的数据传送依靠RST,I/O,SCLK三根端线即可完成。其工作过程

可概括为:首先系统RST引脚驱动至高电平,然后在SCLK时钟脉冲的作用下,

通过I/O引脚向DS1302输入地址/命令字节,随后再在SCLK时钟脉冲的配合下,

从I/O引脚写入或读出相应的数据字节。因此,其与单片机之间的数据传送是十分

容易实现的,DS1302的引脚排列及内部结构图如图3.3:

DS1302引脚说明:

X1,X2 32.768kHz晶振引脚

GND 地线

RST 复位端

I/O 数据输入/输出端口

SCLK 串行时钟端口

VCC1 慢速充电引脚

VCC2 电源引脚 图3.3 DS1302管脚

3.2.2 DS1302接口电路设计

1、 时钟芯片DS1302的接口电路及工作原理:

32.1.2.3

图3.4 DS1302与MCU接口电路

图3.4为DS1302的接口电路,其中Vcc1为后备电源,Vcc2为主电源。VCC1

在单电源与电池供电的系统中提供低电源并提供低功率的电池备份。VCC2在双

电源系统中提供主电源,在这种运用方式中VCC1连接到备份电源,以便在没有

主电源的情况下能保存时间信息以及数据。

DS1302由VCC1或VCC2 两者中较大者供电。当VCC2大于VCC1+0.2V时,

VCC2给DS1302供电。当VCC2小于VCC1时,DS1302由VCC1供电。

DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置 “0”,接

着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图3.5所示。表-1为

DS1302的控制字,此控制字的位7必须置1,若为0则不能对DS1302进行读写

数据。对于位6

,若对时间进行读/写时,CK=0,对程序进行读/写时RAM=1。位

1至位5指操作单元的地址。位0是读/写操作位,进行读操作时,该位为1;进

行写操作时,该位为0。控制字节总是从最低位开始输入/输出的。表-2为DS1302

的日历、时间寄存器内容:“CH”是时钟暂停标志位,当该位为1时,时钟振荡器

停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。“WP”是写保护

位,在任何的对时钟和RAM的写操作之前,“WP”必须为0。当“WP”为1时,写

保护位防止对任一寄存器的写操作。

表1 DS1302的控制字格式

3、数据输入输出(I/O)

在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,

数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK

脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。如下图3.5

所示。

图3.5 DS1302读/写时序图

4、DS1302的寄存器

DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据

位为BCD码形式,其日历、时间寄存器及其控制字见表2。

表2 DS1302的日历、时间寄存器

此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存

器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器

外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM

单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,

其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方

式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。

3.3 温度芯片DS18B20接口设计与性能分析

3.3.1 DS18B20性能简介

1.DS18B20的主要特性

DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能

温度传感器,与传统的热敏电阻等元件相比,它能直接读出被测温度,并且可根

据实际要求通过简单的编程实现9-12位的数字值读数方式。现场温度直接以

线总线

温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。与前一代

产品不同,新的产品支持3V~5.5V的电压范围,使系统设计更灵活、方便。其

性能特点可归纳如下:

1) 独特的单线接口仅需要一个端口引脚进行通信;

2) 测温范围在-55℃到125℃,分辨率最大可达0.0625℃;

3) 采用了3线制与单片机相连,减少了外部硬件电路;

4) 零待机功耗;

5) 可通过数据线供电,电压范围在3.0V-5.5V;

6) 用户可定义的非易失性温度报警设置;

7) 报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件;

8) 负电压特性,电源极性接反时,温度计不会因发热烧毁,只是不能正

常工作。

2.DS18B20工作原理

DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数

因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。 DS18B20测

温原理如图3.6所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产

生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显

改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在

-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图3.6中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。

图3.6 DS18B20测温原理 图3.7温度传感器DS18B20接口电路 3.3.2 DS18B20接口电路设计

如3.7图所示,该系统中采用数字式温度传感器DS18B20,具有测量精度高,电路连接简单特点,此类传感器仅需要一条数据线进行数据传输,用P2.3与DS18B20的DQ口连接,Vcc接电源,GND接地。 3.3.3 DS18B20的工作时序 1、复位时序图

2、 读时序图

图3.9读时序图

3、写时序图

图3.10 写时序图

3.4 闹钟模块接口设计与性能分析

此部分硬件上利用AT24C02存储闹钟时间,普通蜂鸣器作为闹铃播放器件。 3.4.1 AT24C02器件使用

1、AT24C02的特性:

1) 与400KHz I2C 总线兼容 2) 到6.0 伏工作电压范围 3) 低功耗CMOS 技术

4) 写保护功能当 WP 为高电平时进入写保护状态 5) 自定时擦写周期

6) 1,000,000 编程/擦除周期 7) 8 脚DIP SOIC 或TSSOP 封装 8) 温度范围商业级工业级和汽车级 2、AT24C02功能说明

AT24C02支持I2C 总线数据传送协议,I2C 总线协议规定任何将数据传送到总线的器件作为发送器,任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据,发送或接收的模式通过器件地址输入端A0、A1 和A2 可以实现将最多8个24WC01和24WC02 器件连接到总线上。

管脚描述如下:

A0 A1 A2 器件地址选择 SDA 串行数据/地址

SCL 串行时钟 图3.11 AT24C02管图 WP 写保护

VCC/VSS +1.8V~6.0/地 3、工作时序

1)总线时序 2)写周期时序

图3.12 总线时序 图3.12写周期时序

3)起始/停止时序 4)应答时序

图3.13 起始/停止时序 图3.14 应答时序

5)立即地址读时序

图3.15 立即地址读时序

3.4.2 接口电路设计

AT24C02与单片机的接口电路如图3.165所示:

3.16 AT24C02与MCU的接口电路

3.5 LCD显示模块

3.5.1 LCM1602的特性及使用说明

1、 LCM1602的接口信号说明如表3:

2

、基本操作时序如下:

1)读状态:RS=L,RW=H,E=H

2)写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲 3)读数据:RS=H,RW=H,E=H

4)写数据:RS=H,RW=L,D0~D7=数据,E=高脉冲 3、初始化设置

1)显示模式设置如表4:

表4显示模式设置

2)显示开/关及光标设置如表5:

表5 显示开/关及光标设置

3.5.2 LCM1602与MCU的接口电路

接口电路如图3.16所示:

LCD的D0~D7分别接单片机的的P0口,作为数据线,因为P0口内部没有上拉电阻,所以外部另外加上10K的上拉电阻;P2.0—P2.2分别接LCD的RS、RW、E三个控制管脚;RV1用来调节LCD的显示灰度;BLK、BLA为背光的阴极和阳极,接上相应电平即点亮背光灯(图中未画出)。

.4

.5

.6

.7

图3.16 LCM1602与单片机接口电路 图3.17 按键电路

3.6 按键模块设计

如图3.17所示。

本系统用到了4个独立按键,此种接法查询简单,程序处理简单,可节省CPU资源, 4个独立按键分别与单片机的P2.4、P2.5、P2.6、P2.7接口相连。

S1——SET(时间设置键),S2——UP键,S3——DOWN键,S4——SET1(闹钟设置键)。

SET键:按下SET键进入时间校准状态,按一下进入秒调整,两下分调整,依此类推可进行各年月日,时分秒以及星期的校准;

UP键:当SET键按下时,UP进行SET选定项(如:小时)的加操作;

DOWN键:当SET键按下时,DOWN进行SET选定项(如:小时)的减操作; SET1键:当SET键按下时,此键功能为设置闹钟时间和开关闹钟功能。

第四章 软件设计

整个软件系统采用C51编程,主要实现以下功能: 1) LCD的驱动 2) 时间数据的采集 3) 闹铃的设置 4) 温度的采集 5) 按键的识别处理

4.1 软件总体部分的设计

程序从main()主函数开始运行,随后对LCD、DS18B20、DS1302、闹钟模块等器件进行初始化操作并对标志位赋初值,随后进入while(1)循环中运行按键扫描程序及液晶显示程序,详细程序见附录B。 (1) 主程序流程图如图4.1所示:

(2)

图4.1 主函数流程图

4.2 LCD驱动及液晶显示

1、LCD驱动

LCD的驱动包括初始化操作、写指令、写数据、显示模块的设定等操作。LCM1602有以下几个基本时序:

1)读状态:RS=L,RW=H,E=H

2)写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲 3)读数据:RS=H,RW=H,E=H

4)写数据:RS=H,RW=L,D0~D7=数据,E=高脉冲

驱动函数是根据这几个基本时序来完成的,下面是LCD的几个主要驱动函数(详细见附录):

1)LCD_Write() 功能:LCD写指令/数据 2)LCD_Initial() 功能:LCD初始化

3)GotoXY(unsigned char x, unsigned char y) 功能:字符显示的位置 4)Print(unsigned char *str) 功能:输出字符串到LCD 2、液晶显示模块流程图,如图4.2所示:

图4.2液晶显示模块流程图 图4.3温度采集模块流程图

4.3 按键识别及处理

本设计中按键采用查询法识别按键,程序简单。本系统中含有四个调整按键,分别命名为SET、UP、DOWN、SET1。在主函数里面查询SET、SET1P两个按键是否按下,UP、DOWN键的功能由SET和SET1键激活。这样设计可以减少CPU的工作量,下面简单介绍本设计中键盘扫描程序(以伪代码的形式),详细见附录B中 4.4 温度数据采集

由于DS18B20单线通信功能为分时完成,有严格的时隙概念,因此读\写时序很重要[12]。系统对DS18B20的各种操作必须按协议进行。操作协议为:初始化DS18B20(发复位脉冲)——发ROM功能命令——发存储操作命令——处理数据。

根据单总线操作协议,首先要对DS18B20进行初始化,而初始化有严格的时序控制,如图3.6所示,即总线控制器(TX)发出一个复位脉冲(至少480us的低电平),然后释放总线进入接收状态,总线由5.1K上拉电阻上拉为高电平,探测到I/O引脚上的上升沿后,DS18B20等待15us~60us后,然后发出一个存在脉冲(60us~240us的低电平信号)。下面是几个驱动函数:

1)Init_DS18B20(void) 功能:DS18B20初始化 2)ReadTemp(void) 功能:读取温度值 温度采集模块流程图如图4.3所示。

4.5 时间数据采集

串行时钟芯片DS1302的主要组成部分:移位寄存器、控制逻辑、振荡器、实时时钟以及RAM。为了初始化任何的数据传送,把RST

置为高电平且把提供地址和命令信息的8位装入到移位寄存器。数据在SCLK的上升沿串行输入。无论是发生读周期还是写周期,也无论传送方式是单字节传送还是多字节传送,开始8位指定40个字节中的那个将被访问。在开始8个时钟周期把命令字装入移位寄存器之后,另外的时钟在读操作时输出数据,在写操作时输入数据。时钟脉冲的个数在单字节方式下为8加8,在多字节方式下为8加最大可达248的数。

DS1302时钟部分子程序主要涉及以下几个主要函数:

1)void DS1302InputByte(unsigned char d) 功能:实时时钟写入一字节(内部函数)

2)unsigned char DS1302OutputByte(void) 功能:实时时钟读取一字节(内部函数

3)Write1302() 功能:DS1302写入数据函数 4)Read1302() 功能:读取DS1302某地址的数 5)void DS1302_GetTime(SYSTEMTIME *Time)

功能:获取时钟芯片的时钟数据到自定义的结构型数组

4.6 闹钟程序

这一部分的实现是采用E2PROM存储器来储存闹钟信息,因为它具有掉电仍能保存数据的特性。所以本设计中把闹钟信息写先写入AT24C02存储器中,然后在程序中读出数据与当前时间进行比较,如果相等则发出闹钟警告。如果要对闹钟值进行修改,可通过几个按键进行,系统能根据用户的设定自动更新闹钟信息,图4.4是闹钟程序的流程图:

图4.4闹钟程序的流程图

第五章 系统的调试

调试分为硬件调试和软件调试。

硬件调试主要是检查线路板的焊接是否正确、连接是否正确,各模块之间的数据线是否导通。

软件调试主要有以下两种方法:

1) 将整个联合起来调试,对整个软件的功能进行验证;

2)分开调试,也就是将系统分成独立的小模块,然后分别对这些小模块写入程序调试。这样可以提高调试效率,也容易解决调试中出现的问题。

本系统采用分开调试方法调试了DS18B20和DS1302两个模块,并用LCD显示出了温度以及公历日期、时间,同时也实现了按键的简单调整;但整体调试的时候没有达到预期效果。

总结

论文首先对本设计作了简要描述,随后提出了不同的设计方案,经过论证最后确定该设计采用电源模块、时钟模块、显示模块、键盘接口模块、温度测量模块和闹钟模块共六个模块组成,接着分别从硬件系统和软件系统两方面对基于单片机的电子万年历设计作了详细论述,另外还简要介绍了一下系统的调试。

在整个设计过程中,硬件方面主要设计了STC89C52RC单片机的最小系统、DS1302接口电路、DS18B20接口电路、闹钟及LCD显示;软件方面借助各个渠道的资料,主要设计了阳历数据读取程序、阳历转阴历程序、温度采集程序、闹铃程序以及LCD显示程序;系统的调试主要是通过一块STC89C52RC开发板,再借助于Keil、STC以及少许自己搭建的外围电路实现的;再此过程中,分步调试时显示出了阳历的日期及时间,还有实时温度,集中调试时没有达到预期效果。但在此过程中培养了自己的动手能力。

此万年历具有读显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

附:参考文献

1.张萌.单片机应用系统开发综合实例[M]. 北京:清华大学出版社,2007.7 2.楼然苗.单片机课程设计指导[M]. 北京:北京航空航天大学出版社,2007.7

3.沈德金.MCS-51系列单片机接口电路与应用程序实例[M]. 北京:北京航空航天大学出版社,1991.4

4.朱思荣.51单片机实现公历与农历、星期的转换[Z].当当电子网

5.AT24WC01/02/04/08/16 1K/2K/4K/8K/16K 位串行E2PROM[D].广州周立功单片机有限公司 6.DS1302 Trickle Charge Timekeeping Chip datasheet[D] 7.马忠梅,籍顺心等.单片机的C语言应用程序设计[M].北京航空航天大学出版社, 2001年

8.陈明荧. 8051单片机课程设计实训教程[M].北京:清华大学出版社 9.何立民.单片机高级教程[M].北京:北京航空航天大学出版社,2003年 10.新编单片机原理与应用(第二版).西安电子科技大学出版社,2007.2 11. 李广弟. 单片机原理及应用[M] 北京航空航天大学出版社,2004年 12.王越明.电子万年历的设计[J].黑龙江科技信息,2004年

13.SCM1602 LCM 使用说明书[DB]长沙:长沙太阳人电子有限公司 14.赵亮. 单片机C语言编程与实例[M] 人民邮电出版社,2003年 15.http://www.mcu51.com 16.http://www.cnki.net 17.http://www.2lic.com

附录A 仿真电路图

附录B 源程序 #include #include

uchar code tabe1[]=

uchar code tabe2[]=

miao,fen,shi,nian,yue,ri,week,wendu_shi,wendu_ge,wendu_shu,variate,alarm_shi,alarm_fen,alarm_miao; uchar

flag=1,count=0,flag_up=0,flag_down=0,flag_alarm=0,alarm_on,alarm_count=0,done=0;

uint wendu; //定义IO

sbit DQ = P1^0; //ds18b20温度传送数据IO口 sbit ds1302_rst = P1^1; //1302复位 sbit ds1302_io = P1^2; //数据输入输出 sbit ds1302_sclk= P1^3; //串行时钟

sbit alarm_out = P3^6;

sbit lcd1602_rs = P2^0; // 1602命令、数据选择 sbit lcd1602_rw = P2^1; sbit lcd1602_e = P2^2;

sbit set = P2^4;

//选择按键

// 1602写

// 1602使能

sbit up = P2^5; //加 sbit down= P2^6; //减

sbit nao = P2^7;

sbit ACC0=ACC^0; sbit ACC7=ACC^7; //延时

void delay(uchar x) { uchar y,z; for(z=x;z>0;z--)

for(y=110;y>0;y--);

}

void delay1() { _nop_(); _nop_();

}

ds18b20_delay(uchar xus) //延时xus { while(xus--); }

/*******ds18b20温度控制程序***********/

void ds18b20_init() //DS18B20初始化 { uchar x=0; DQ=1;

ds18b20_delay(8); DQ=0;

ds18b20_delay(80); DQ=1;

ds18b20_delay(14);

x=DQ;

ds18b20_delay(20);

}

void write_onechar(uchar dat) //写一字节 {

uchar i; for(i=8;i>0;i--) { DQ=0;

if(dat&0x01==0x01) DQ=1;

else

DQ=0; ds18b20_delay(5); DQ=1;

ds18b20_delay(1); dat>>=1;

}

}

uchar read_onechar() //读一字节

{ uchar value=0,i; for(i=8;i>0;i--) {

value>>=1; DQ=0;

ds18b20_delay(1); DQ=1; if(DQ==1) value|=0x80;

else

value&=0x7f;

ds18b20_delay(4);

}

return value;

}

}

ds1302_sclk=1; //拉高sclk ACC>>=1;

uint read_wendu() //DS18B20读温度 uchar read_byte() { uchar a=0,b=0; uint wen=0x0000; ds18b20_init();

//初始化

write_onechar(0xcc);

// 跳过读序号列

号的操作 write_onechar(0x44); // 启动温度转换 ds18b20_delay(150); ds18b20_init();

//初始化

write_onechar(0xcc); //跳过读序号列号的操作

write_onechar(0xbe); //读取温度寄存器

等(共可读9个寄存器) 前两个就是温度 ds18b20_delay(150); b=read_onechar(); //读取温度值低位 a=read_onechar(); //读取温度值高位

wen=a;

wen=(wen

}

/*****ds1302时钟闹钟控制**********/ void write_byte(uchar dat) //写一字节 { uchar k;

ACC=dat;

for(k=8;k>0;k--) { ds1302_io=ACC0;

ds1302_sclk=0;

//拉低sclk

{

uchar k;

for(k=8;k>0;k--) { ACC7=ds1302_io;

ds1302_sclk=1; //拉高sclk ds1302_sclk=0; //拉低sclk

ACC>>=1; }

return ACC;

}

void ds1302_write(uchar add,uchar date) {

ds1302_rst=0;

ds1302_sclk=0; //在rst没拉高之前先把sclk置0 ds1302_rst=1; write_byte(add); write_byte(date);

ds1302_sclk=1; ds1302_rst=0;

}

uchar ds1302_read(uchar add) { uchar temp;

ds1302_rst=0;

ds1302_sclk=0; //在rst没拉高之前先把sclk置0

ds1302_rst=1; write_byte(add); temp=read_byte();

ds1302_sclk=1; ds1302_rst=0; return temp;

}

void ds1302_init() //ds1302初始化 { ds1302_rst=0; ds1302_sclk=1; ds1302_write(0x8e,0x00); //写允许

ds1302_write(0x80,0x58); ds1302_write(0x82,0x56); ds1302_write(0x84,0x23); ds1302_write(0x86,0x21); ds1302_write(0x88,0x12); ds1302_write(0x8a,0x02); ds1302_write(0x8c,0x10);

ds1302_write(0x90,0xa5); //充电 ds1302_write(0x8e,0x80); //写保护

}

/*********lcd1602***************/

void lcd_write_com(uchar com) //命令字写入lcd单元中 {

lcd1602_rw=0; delay1();

lcd1602_rs=0;// RW=1,RS=0,写LCD命令字 delay1();

P0=com; //将com中的命令字写入LCD

数据口 delay1();

lcd1602_e=1; //E端时序 delay1(); lcd1602_e=0; delay1(); lcd1602_rw=1; delay(5);

}

void lcd_write_date(uchar date) //数据写入lcd单元中 {

lcd1602_rw=0; delay1();

lcd1602_rs=1; // RW=0,RS=1,写LCD命令字 delay1();

lcd1602_e=1; // E端时序 delay1(); P0=date; // 将dat中的显示数据

写入LCD数据口 delay1(); lcd1602_e=0; delay1(); lcd1602_rw=1; delay(5); }

void lcd1602_init() //LCD初始化函数 { uchar lcdnum; P3=0xdf;

lcd_write_com(0x38);

lcd_write_com(0x0c); lcd_write_com(0x06); lcd_write_com(0x01); lcd_write_com(0x80);

for(lcdnum=0;lcdnum

uchar shi,ge; shi=date/10; ge=date%10;

lcd_write_com(0x80+0x40+add); lcd_write_date(0x30+shi); //写第一行数据 { lcd_write_date(tabe1[lcdnum]); delay(2);

}

lcd_write_com(0x80+0x40);

//写入第二行数据 for(lcdnum=0;lcdnum

}

}

/**************显示部分***************/

void write_time1(uchar add,uchar date) //日期送显示 {

uchar shi,ge; shi=date/10; ge=date%10;

lcd_write_com(0x80+add); lcd_write_date(0x30+shi); lcd_write_date(0x30+ge);

}

void write_time2(uchar add,uchar date) //时间送显示 {

lcd_write_date(0x30+ge);

}

uchar bcd_decimal(uchar bcd)//bcd转换十进制 { uchar decimal; decimal=bcd>>4;

decimal=decimal*10+(bcd&=0x0f);

return decimal;

}

void wendu_decimal(uint dat) //温度转换后送显示 { float temp;

temp=dat*0.625; //dat*0.0625*10

wendu_shi=temp/100;

//取十位 temp除不用定义类型

wendu_ge =((uint)temp)%100/10;

//取个位 temp求模要定义类型,为16位,故定义uint

wendu_shu=((uint)temp)%100%10;

//取小数

lcd_write_com(0x80+0x40+10); //送显示 lcd_write_date(0x30+wendu_shi); lcd_write_date(0x30+wendu_ge); lcd_write_date(0x2e);

lcd_write_date(0x30+wendu_shu);

lcd_write_date(0xdf); }

}

lcd_write_date('U'); lcd_write_date('N'); break;

//温度符号 }

void write_week(uchar we) //星期送显示 lcd_write_date(0x43);

{ lcd_write_com(0x80+0x0d); switch(we) { case 1: lcd_write_date('M'); lcd_write_date('0'); lcd_write_date('N');

break;

case 2: lcd_write_date('T'); lcd_write_date('U'); lcd_write_date('E');

break;

case 3: lcd_write_date('W'); lcd_write_date('E'); lcd_write_date('D');

break;

case 4: lcd_write_date('T'); lcd_write_date('H'); lcd_write_date('U');

break;

case 5: lcd_write_date('F'); lcd_write_date('R'); lcd_write_date('T');

break;

case 6: lcd_write_date('S'); lcd_write_date('A'); lcd_write_date('T');

break;

case 7: lcd_write_date('S');

/*********按键处理*************/

uchar key_bcd(uchar key_decimal) //转成ds1302所需的BCD码 { uchar temp;

temp=(((key_decimal/10)&0x0f)

decimal%10); return temp;

}

void key_up_down() //加减键处理 { if(up==0) { delay(2); flag_up=1;

//加 更新标志

while(!up); switch(count) { case 1: miao++; if(miao>59)

miao=0;

break;

case 2: fen++; if(fen>59)

fen=0;

break; case 3: shi++; if(shi>23)

shi=0;

break;

case 4: week++; if(week>7)

week=1;

break;

case 5: ri++; if(ri>31)

ri=1;

break;

case 6: yue++; if(yue>12)

yue=1;

break;

case 7: nian++; if(nian>99)

nian=0;

break;

}

}

if(down==0) //减键处理 { delay(2);

flag_down=1; //减更新标志

while(!down);

switch(count) { case 1: miao--; if(miao==255)

miao=59;

break;

case 2: fen--; if(fen==255)

fen=59;

break;

case 3: shi--; if(miao==255)

shi=23;

break;

case 4: week--; if(week

week=7;

break;

case 5: ri--; if(ri

ri=31;

break;

case 6: yue--; if(yue

yue=12;

break;

case 7: nian--;

if(nian==255)

nian=99;

break;

} }

}

/**********24c02时间模块******/

void alarm_ring() { if(alarm_on==1)

//alarm_on=1 为闹钟有效

{

if(shi==alarm_shi && fen==alarm_fen && miao==alarm_miao) flag_alarm=1; }

//闹钟时间到,闹钟标志位置1

if(flag_alarm==1) { uchar i,j,t; t=30;

for(i=0;i

alarm_out=~alarm_out; for(j=0;j

if(set==0 || up==0 || down==0 ||

nao==0) //闹钟响时,按任意键取消闹钟 { while(!set);

while(!up);

lcd_write_date(0x3a);

while(!down); while(!nao);

flag_alarm=0; alarm_out=1;

}

}

}

void c02_init() { c_init();

alarm_shi=c02_read_add(1); //读取闹钟时 delay(200);

alarm_fen=c02_read_add(2); //分 delay(200);

alarm_miao=c02_read_add(3); //秒

delay(200);

alarm_on =c02_read_add(4); //读取闹钟开关值,为0关,为1开 delay(200);

}

void alarm_huan() //按下闹钟键后,切换界面{ uchar num;

lcd_write_com(0x01); lcd_write_com(0x80);

for(num=0;num

//写第一行数据 { lcd_write_date(tabe3[num]); delay(2);

}

lcd_write_com(0x0f); write_time2(4,alarm_shi);

write_time2(7,alarm_fen);

lcd_write_date(0x3a); write_time2(10,alarm_miao); if(alarm_on==0) { lcd_write_com(0x80+0x40+13); lcd_write_date('O'); lcd_write_date('F'); lcd_write_date('F');

}

if(alarm_on==1) { lcd_write_com(0x80+0x40+13); lcd_write_date(' '); lcd_write_date('O'); lcd_write_date('N'); }

}

void key_set_alarm() {

if(set==0

&&

alarm_count==0

&&

flag_alarm==0) { delay(2); if(set==0) {

while(!set); //等待set释放

count++; //按set一下,count加1 if(flag==1) { done=1;

flag=0;

ds1302_write(0x8e,0x00); //写允许

ds1302_write(0x80,key_bcd(miao)|0x80); //BIT7为1,晶振停止工作

ds1302_write(0x8e,0x80); //写保护

}

}

}

if(nao==0 && count==0 && flag_alarm==0) { delay(2); if(nao==0) { while(!nao); alarm_count++; if(flag==1) { done=1; flag=0;

alarm_huan(); //切换界面

}

}

}

}

void keyjpress()

//按键处理

{ key_set_alarm();

if(count!=0)

//count不为0,进入时间调整扫描 {

switch(count) { case 1:do

{

lcd_write_com(0x0F); //显示光标,不闪烁

lcd_write_com(0x80+0x40+7);

key_up_down(); if(flag_up || flag_down)

{

flag_up=0; flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x80,key_bcd(miao) | 0x80); ds1302_write(0x8e,0x80); write_time2(6,miao);

lcd_write_com(0x80+0x40+7); //液晶写字

符后光标自动向右移动一位,把光标左移一位 }

}

while(count==2); break;

case 2:do {

lcd_write_com(0x80+0x40+4); key_up_down();

if(flag_up || flag_down) { flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x82,key_bcd(fen));

ds1302_write(0x8e,0x80);

write_time2(3,fen);

lcd_write_com(0x80+0x40+4);

}

}

while(count==3);

break; case 3:do { lcd_write_com(0x80+0x40+1); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00); ds1302_write(0x84,key_bcd(shi));

ds1302_write(0x8e,0x80); write_time2(0,shi);

lcd_write_com(0x80+0x40+1); }

}

while(count==4); break;

case 4: do {

lcd_write_com(0x80+0x0e); key_up_down(); if(flag_up || flag_down)

{

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x8a,key_bcd(week));

ds1302_write(0x8e,0x80); write_week(week); lcd_write_com(0x80+0x0e); }

}

while(count==5);

break; case 5:do {

lcd_write_com(0x80+9); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x86,key_bcd(ri)); ds1302_write(0x8e,0x80); write_time1(8,ri);

lcd_write_com(0x80+9);

} }

while(count==6); break;

case 6:do {

lcd_write_com(0x80+6); key_up_down(); if(flag_up || flag_down) {

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x88,key_bcd(yue)); ds1302_write(0x8e,0x80);

write_time1(5,yue); lcd_write_com(0x80+6);

}

基于单片机电子万年历设计30

}

while(count==7); break;

case 7: lcd_write_com(0x80+3); key_up_down();

if(flag_up || flag_down)

{

flag_up=0;

flag_down=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x8c,key_bcd(nian)); ds1302_write(0x8e,0x80);

write_time1(2,nian); lcd_write_com(0x80+3); }

break; case 8:

lcd_write_com(0x0c);

//调整结束,关闭显示光标 flag=1; done=0; count=0;

ds1302_write(0x8e,0x00);

ds1302_write(0x80,key_bcd(miao)&0x7f);

//BIT7为0,晶振开始工作 ds1302_write(0x8e,0x80); break;

default:break;

}

}

if(alarm_count!=0) //闹钟按键扫描 {

switch(alarm_count)

{

lcd_write_com(0x80+0x40+15);

if(up==0) {

delay(2); if(up==0) {

while(!up); alarm_on=1;

lcd_write_com(0x80+0x40+13); lcd_write_date(' '); lcd_write_date('O'); lcd_write_date('N'); c02_write_add(4,alarm_on); delay(200);

lcd_write_com(0x80+0x40+15); }

} if(down==0) {

if(down==0); {

while(!down); alarm_on=0;

lcd_write_com(0x80+0x40+13);

lcd_write_date('O');

lcd_write_date('F');

lcd_write_date('F');

c02_write_add(4,alarm_on); delay(200);

lcd_write_com(0x80+0x40+15);

}

break;

case 2:

lcd_write_com(0x80+0x40+11); if(up==0 || down==0) { delay(2);

if(up==0)

{ while(!up); alarm_miao++; if(alarm_miao>59) alarm_miao=0;

} if(down==0)

{

while(!down); alarm_miao--;

if(alarm_miao==255) alarm_miao=59;

}

write_time2(10,alarm_miao); lcd_write_com(0x80+0x40+11); c02_write_add(3,alarm_miao); delay(200);

} break;

case 3:

lcd_write_com(0x80+0x40+8);

if(up==0 || down==0) {

delay(2);

if(up==0)

31

while(!up);

alarm_fen++; if(alarm_fen>59) alarm_fen=0;

}

if(down==0) {

while(!down); alarm_fen--; if(alarm_fen==255) alarm_fen=59;

}

write_time2(7,alarm_fen); lcd_write_com(0x80+0x40+8); c02_write_add(2,alarm_fen); delay(200);

}

break; case 4: lcd_write_com(0x80+0x40+5); if(up==0 || down==0) { delay(2); if(up==0) {

while(!up); alarm_shi++;

if(alarm_shi>23)

alarm_shi=0;

}

if(down==0)

{

alarm_shi--;

if(alarm_shi==255)

alarm_shi=23;

}

write_time2(4,alarm_shi);

lcd_write_com(0x80+0x40+5); c02_write_add(1,alarm_shi);

delay(200);

}

break; case 5:

alarm_count=0; lcd1602_init(); flag=1; done=0;

break;

} }

}

void xianshi() {

//读秒分时,日月年,星期

miao=bcd_decimal(ds1302_read(0x81)); fen =bcd_decimal(ds1302_read(0x83)); shi =bcd_decimal(ds1302_read(0x85));

ri =bcd_decimal(ds1302_read(0x87)); yue =bcd_decimal(ds1302_read(0x89)); nian=bcd_decimal(ds1302_read(0x8d));

week=bcd_decimal(ds1302_read(0x8b));

//送液晶显示

write_time2(6,miao);

32

write_time2(3,fen); write_time2(0,shi); write_time1(8,ri); write_time1(5,yue); write_time1(2,nian);

write_week(week);

//读温度

wendu=read_wendu();

//温度显示 wendu_decimal(wendu);

} main() { lcd1602_init();

ds18b20_init(); ds1302_init(); c02_init(); while(1) { if(done==1) {

keyjpress();

}

if(done==0) {

xianshi(); //取得并显示日历和时间 key_set_alarm(); alarm_ring(); }

}

}

//闹钟设置时间存储AT2402子程序: #ifndef _24c02

#define _24c02

#define uchar unsigned char #define uint unsigned int

/***********DS18B20管脚配置********/

sbit sda = P1^4;//24c02数据输入输出 sbit scl = P1^5; //24c02时钟

void c02_delay() { ;; }

void start() //开始信号 {

sda=1; c02_delay(); scl=1; c02_delay(); sda=0; c02_delay();

}

void stop() //停止 { sda=0; c02_delay(); scl=1; c02_delay(); sda=1; c02_delay();

}

void respons() //应答 { uchar i;

scl=1;

33

c02_delay();

while((sda==1)&&(i

//如sda=0或i>250,,跳出

scl=0; c02_delay();

}

void c_init() { sda=1; c02_delay(); scl=1; c02_delay();

}

void c02_write_byte(uchar date) //写一字节{ uchar i,temp; temp=date; for(i=0;i

scl=0;

c02_delay(); sda=CY; c02_delay(); scl=1; c02_delay();

} scl=0; c02_delay(); sda=1; c02_delay();

}

uchar c02_read_byte() //读一字节 { uchar i,k; scl=0; c02_delay(); sda=1; c02_delay(); for(i=0;i

{ scl=1; c02_delay(); k=(k

} return k;

}

void c02_write_add(uchar address,uchar date) //写

{ start();

c02_write_byte(0xa0); respons();

c02_write_byte(address); respons();

c02_write_byte(date); respons(); stop(); }

uchar c02_read_add(uchar address) //读

{ uchar date;

start();

34

c02_write_byte(0xa0); respons();

c02_write_byte(address); respons(); start();

c02_write_byte(0xa1);

}

respons();

date=c02_read_byte(); stop(); return date;

35


相关内容

  • 电工电子实训教学大纲
  • <电工电子实训>教学大纲 课程编号:2131105 课程名称:<电工电子实训> 实训学时: 1.2周(根据各系实训教学需要安排学时) 面向对象:机电工程系.电子信息与电气工程系等各相关专业. 一.本实验课的性质与目的 <电工电子实训>课程要求学生掌握焊接技术的基本 ...

  • 电子信息专业认识实习报告
  • 实 习 报 告 实习名称 专 业 认 识 实 习 专业班级 电子1142 姓 名 学 号 成 绩 评 定 电气与信息工程学院 二0一二年十月 实习纪律要求和成绩考核办法 实习纪律要求和成绩考核办法 1.实习过程必须听从教师和现场工作人员指导,严格遵守安全操作规程.不准违规操作,未经现场工作人员允许不 ...

  • 报建心得+项目前期报建工作总结
  • 项目前期报建工作总结 一.规划方案审批阶段,规划为主办部门,消防.绿化.环保.人防为协办部门实行并联审批.程序为先把方案报规划进行预审,预审通过后由规划向协办部门发协办通知,再将资料报协办部门.由于在报环保之前要请环评单位做环评,历时较长,因此,规划允许报环保可以在不拿协办通知的情况下先进行.最后待 ...

  • 文章格式要求
  • 附件6 失地农民就业影响因素分析研究 --基于苏州市失地农民的调查 系 部: 经贸管理系 学生姓名: 夏 欢 专业班级: 电子商务 学 号: 104642120 指导教师: 赵春燕 2012年 11月 28 日 超级玩乐网网站建设说明书 系 部: 经贸管理系 学生姓名: 施艳贤 专业班级: 电子商务 ...

  • 电子技术课程设计指导
  • 电子技术课程设计指导 长安大学电工电子教学部 目 录 一.课程设计指导 二.数字频率计的设计实例 三.集成直流稳压电源的设计 四.电容数字测量仪的设计 五.多路数据采集系统的设计 附录: 参考文献 软件: word .visio. protel .Pspice.EWB.Multisim等 一.课程设 ...

  • 电子技术课程设计讲义(1)(1)
  • 电子技术课程设计讲义 工电子实验教学中心 电 目 录 第一部分:电子技术课程设计概述 ......................... 1 一.电子技术课程设计的必要性与目的 .......................... 1 二.电子技术课程设计的基本要求 ................ ...

  • 电子商务专业毕业设计(论文)实施方案
  • 电子商务专业毕业设计(论文)实施方案 根据教学计划规定和专业实践教学安排,结合本系的实际情况,特制定珠海电大电子商务专业毕业生毕业设计(论文)实施方案. 一.撰写毕业设计(论文)的目的与意义 毕业设计(论文)是学生整个学习过程中一个极其重要的教学环节,是综合考察学生运用所学知识分析问题.解决问题能力 ...

  • 微电子专业系列课程建设与教学改革总结报告
  • 微电子专业系列课程建设与教学改革 总 结 报 告 近年来国内的集成电路(以下简称:IC)产业迎来了蓬勃发展时期,社会对IC人才在数量和质量两方面都提出了更高的要求.在四川地区,Intel IC封装厂(投资3.7亿美元).乐山菲尼克斯IC生产线(投资2亿美元).美国芯源(MPS)公司的IC研发.设计和 ...

  • 毕业实习报告怎么写
  •   ?这是不少毕业生头痛的问题。下面,我们以电子商务毕业生为例,来向大家讲解一下如何写实习报告。   电子商务? 这是近期电子商务专业的应届毕业生反映最多的问题,很多同学在网上搜集往届毕业生的实习报告,简单的copy一下,就ok,殊不知自己需要的是什么?难道所谓的实习报告纯粹的就是为了做一份只给老师 ...

  • 2011年电子商务毕业设计
  • 电子商务专业顶岗实习计划 系 专 班 教 学 系 主 教 务 别 工商管理系 业 电子商务 级 P08电商.W06电商 部 电子商务教育教学部 任 姚辉波 处 淄博职业学院 2010年10月 16日 电子商务专业学生顶岗实习计划 一.实习目的 顶岗实习是学生完成学业的一个重要环节,是上岗前的&quo ...