资源描述
电气工程学院
传感器课程设计报告
班 级: 电132
姓 名: 袁吉收
学 号: 1312021047
设计题目: 智能家居监控系统设计
设计时间: 2015.12.22~12.28
评定成绩:
评定教师:
摘要
本文设计的智能家居系统以AT89C51单片机为核心控制单元,实时获取DS18B20温度传感器、TGS813气敏传感器、UD-02感烟传感器数据.并通过LCD1602来显示当前的状态。
关键字:AT89c51、DS18B20、TGS813、UD-02、LCD1602
43
目 录
一、题目要求
1.1 题目介绍
1.2 模块分解
二、 方案设计
2.1 方案介绍
三、硬件设计
3.1硬件原理图
四、软件设计
4.1时序图
五、设计总结
六、参考文献
附件:程序代码
一、题目要求
1.1智能家居监控系统设计
以提高家居生活的安全性、舒适度、人性化为目的,设计智能家居监控系统。利用所学的传感器与检测技术知识,实现家居温度、煤气泄漏、外人闯入、火灾(烟雾)的检测(以上检测项目必做。在此基础上增加检测项目并具有可行性,加分。除环境监测项目外,也可增加人体信号检测等。)。各检测节点可通过无线方式连接到主机,检测到危险信号后,主机可采用声光报警或远程报警。
智能化家居中的传感器
活动物体 传感器
烟雾传感器
二氧化碳 传感器
温度传感器
火焰传感器
总 线
终端
控制对象
要求(1)用Protel画出设计原理图;
(2)采用Quaters II、Maxplus II、multisim(EWB)、pspice、Proteus中的一种或几种软件,完成系统电路图部分或全部仿真,在设计说明书中体现仿真结果;
(3)写设计说明书;
1.2模块分解
1. 温度检测:采用DS18B20温度传感器。
2. 煤气泄漏检测:气敏传感器TGS813来检测空气中的可燃性气体。
3. 烟雾检测:UD-02离子感烟传感器检测空气中烟雾。
二、方案设计
2.1方案设计及选择
在实际设计中我们要考虑的因素有很多,比如成本最低、性价比最高、性能最优、功能最强、界面最友好等等。而本次课设我采用了性价比最高的方案(首先能实现基本功能)。选用了DS18B20、TGS813、UD-02、LCD1602模块实现本次设计。
基于AT89c51的智能家居系统设计
智能家居是人们的一种居住环境,其以住宅为平台安装有智能家居系统,实现家庭生活更加安全,节能,智能,便利和舒适。以住宅为平台,利用综合布线技术、网络通信技术、 智能家居-系统设计方案安全防范技术、自动控制技术、音视频技术将家居生活有关的设施集成,构建高效的住宅设施与家庭日程事务的管理系统,提升家居安全性、便利性、舒适性、艺术性,并实现环保节能的居住环境。
又称智能住宅,在国外常用Smart Home表示。与智能家居含义近似的有家庭自动化(Home Automation)、电子家庭(Electronic Home、E-home)、数字家园(Digital Family)、家庭网络(Home Net/Networks for Home)、网络家居(Network Home)、智能家庭/建筑(Intelligent Home/Building),在我国香港和台湾等地区,还有数码家庭、数码家居等称法。
智能家居系统让您轻松享受生活。出门在外,您可以通过电话、电脑来远程遥控您的家居各智能系统,例如在回家的路上提前打开家中的空调和热水器;到家开门时,借助门磁或红外传感器,系统会自动打开过道灯,同时打开电子门锁,安防撤防,开启家中的照明灯具和窗帘迎接您的归来;回到家里,使用遥控器您可以方便地控制房间内各种电器设备,可以通过智能化照明系统选择预设的灯光场景,读书时营造书房舒适的安静;卧室里营造浪漫的灯光氛围……这一切,主人都可以安坐在沙发上从容操作,一个控制器可以遥控家里的一切,比如拉窗帘,给浴池放水并自动加热调节水温,调整窗帘、灯光、音响的状态;厨房配有可视电话,您可以一边做饭,一边接打电话或查看门口的来访者;在公司上班时,家里的情况还可以显示在办公室的电脑或手机上,随时查看;门口机具有拍照留影功能,家中无人时如果有来访者,系统会拍下照片供您回来查询。
2.1.1DS18B20的原理
DS18B20的特点:
DS18B20 单线数字温度传感器,即“一线器件”,其具有独特的优点:
( 1 )采用单总线的接口方式 与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
( 2 )测量温度范围宽,测量精度高 DS18B20 的测量范围为 -55 ℃ ~+ 125 ℃ ; 在 -10~+ 85°C范围内,精度为 ± 0.5°C 。
( 3 )在使用中不需要任何外围元件。
( 4 )持多点组网功能 多个 DS18B20 可以并联在惟一的单线上,实现多点测温。
( 5 )供电方式灵活 DS18B20 可以通过内部寄生电路从数据线上获取电源。因此,当数据线上的时序满足一定的要求时,可以不接外部电源,从而使系统结构更趋简单,可靠性更高。
( 6 )测量参数可配置 DS18B20 的测量分辨率可通过程序设定 9~12 位。
( 7 ) 负压特性电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
( 8 )掉电保护功能 DS18B20 内部含有 EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
DS18B20 具有体积更小、适用电压更宽、更经济、可选更小的封装方式,更宽的电压适用范围,适合于构建自己的经济的测温系统,因此也就被设计者们所青睐。
DS18B20管脚排列:
1. GND为电源地;
2. DQ为数字信号输入/输出端;
3. VDD为外接供电电源输入端(在寄生电源接线方式时接地)
DS18B20 单线通信:
DS18B20 单线通信功能是分时完成的,他有严格的时隙概念,如果出现序列混乱, 1-WIRE 器件将不响应主机,因此读写时序很重要。系统对 DS18B20 的各种操作必须按协议进行。根据 DS18B20 的协议规定,微控制器控制 DS18B20 完成温度的转换必须经过以下 3个步骤 :
(1)每次读写前对 DS18B20 进行复位初始化。复位要求主 CPU 将数据线下拉 500us ,然后释放, DS18B20 收到信号后等待 16us~60us 左右,然后发出60us~240us 的存在低脉冲,主 CPU 收到此信号后表示复位成功。
(2)发送一条 ROM 指令
(3)发送存储器指令
具体操作举例:
现在我们要做的是让DS18B20进行一次温度的转换,那具体的操作就是:
1、主机先作个复位操作,
2、主机再写跳过ROM的操作(CCH)命令,
3、然后主机接着写个转换温度的操作命令,后面释放总线至少一秒,让DS18B20完成转换的操作。在这里要注意的是每个命令字节在写的时候都是低字节先写,例如CCH的二进制为11001100,在写到总线上时要从低位开始写,写的顺序是“零、零、壹、壹、零、零、壹、壹”。整个操作的总线状态如下图。
读取RAM内的温度数据。同样,这个操作也要接照三个步骤。
1、主机发出复位操作并接收DS18B20的应答(存在)脉冲。
2、主机发出跳过对ROM操作的命令(CCH)。
3、主机发出读取RAM的命令(BEH),随后主机依次读取DS18B20发出的从第0一第8,共九个字节的数据。如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可。同样读取数据也是低位在前的。整个操作的总线状态如下图:
2.1.2TGS813的工作原理
下图为TGS813的内部结构,TGS813共有6个引脚,其中引脚1和引脚3短路后接回路电压;引脚4和引脚6短接后接回路电压;引脚4和引脚6短接后作为传感器的信号输出端;引脚2和引脚5为传感器的加热丝的两端,外接加热丝电压。TGS813传感器需要施加两个电压:加热器电压Vh和回路电压Vc。Vh用于维持敏感素子处于与对象气体相适应的特定温度而施加在集成的加热器上。Vc则是用于测定与传感器串联的负载电阻Rl上的两端电压Vrl。只要能满足传感器的电器特性要求,Vc和Vh 可以共用一路电源。为了使敏感素子的功耗 低于15mW的限度值,需要选择适当的RL
向左转|向右转
值。
基于气敏传感器TGS813的家用可燃气体泄漏报警通风装置的方案。该设计的系统利用TGS813对可燃性气体进行监测,当气体浓度超标时,传感器输出的电压信号将大于设定电压,比较器比较之后正向输出,经过功率放大,最后驱动音响报警电路及排气装置。该设计具有线路简单、成本低、操作方便等优点。
为了补偿温度和湿度对传感器特性的影响,同时为了获得更高的精度,故使用热敏电阻或湿敏传感器对电路进行补偿。该设计的传感器电路及温度补偿电路如图3所示。
2.1.3UD-02离子传感器
原理:在20左右的摄氏度条件、清洁空气下,收集电极的平衡电位为5伏到5.6伏;有烟雾是,电位变化可达1.1~1.2V。极间电容4PF,AM241放射源为0.81~0.99uCi;器件重量12g,主要结构材料为不锈钢和塑料。
用电加热器加热到440~480摄氏度时,对不同材料所产生的烟雾,其集电极电位变化1.0V是的灵敏度如表所示:
燃烧材料
烟雾含量mg/
阴暗度%
硅橡胶
26
1.0
乙烯基材料
29
1.1纸烟
纸烟
115
3
2.1.4显示屏的选择
一般来说,应用于显示屏的LED发光材料有以下几种形式:
① LED发光灯(或称单灯) 一般由单个LED晶片,反光杯,金属阳极,金属阴极构成,外包具有透光聚光能力的环氧树脂外壳。可用一个或多个(不同颜色的)单灯构成一个基本像素,由于亮度高,多用于户外显示屏。
② LED点阵模块 由若干晶片构成发光矩阵,用环氧树脂封装于塑料壳内。适合行列扫描驱动,容易构成高密度的显示屏,多用于户内显示屏。
③ 贴片式LED发光灯(或称SMD LED) 就是LED发光灯的贴焊形式的封装,可用于户内全彩色显示屏,可实现单点维护,有效克服马赛克现象。
LED之所以受到广泛重视而得到迅速发展,是与它本身所具有的优点分不开的。这些优点概括起来是:亮度高、工作电压低、功耗小、大型化、寿命长、耐冲击和性能稳定。LED的发展前景极为广阔,正朝着更高亮度、更高耐气候性、更高的发光密度、更高的发光均匀性,可靠性、全色化方向发展。LED显示屏广泛应用[2] 在体育场馆、商业应用、银行、证劵、邮政、码头、商场、车站、邮政、电讯、机关、监控、学校、餐厅、酒店、娱乐、等不同户外场所的广告宣传。
就本次课程设计来说LCD1602、12864、LCD5110都是可以选择的,我们着重比较他们的价格。
芯片
LCD1602
LCD12864
LCD5110
价格(元)
5
23
50+
稳定性
稳定
稳定
稳定
可靠性
可靠
可靠
可靠
这就是选择LCD1602的原因
602采用标准的16脚接口,其中:
第1脚:GND为电源地
第2脚:VCC接5V电源正极
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:RW为读写信号线,高电平(1)时进行读操作,
以51为例的简单原理图
低电平(0)时进行写操作。
第6脚:E(或EN)端为使能(enable)端,高电平(1)时读取信息,负跳
变时执行指令。
第7~14脚:D0~D7为8位双向数据端。第15~16脚:空脚或背灯电
源。15脚背光正极,16脚背光负极。
特性
3.3V或5V工作电压,对比度可调
内含复位电路
提供各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能
有80字节显示数据存储器DDRAM
内建有192个5X7点阵的字型的字符发生器CGROM
8个可由用户自定义的5X7的字符发生器CGRAM
特征应用
微功耗、体积小、显示内容丰富、超薄轻巧,常用在袖珍式仪表和低功耗应用系统中。
操作控制
注:关于E=H脉冲——开始时初始化E为0,然后置E为1。
字符集
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
在单片机编程中还可以用字符型常量或变量赋值,如'A’。因为CGROM储存的字符代码与我们PC中的字符代码是基本一致的,因此我们在向DDRAM写C51字符代码程序时甚至可以直接用P1=‘A’这样的方法。PC在编译时就把'A'先转换为41H代码了。
CGROM中字符码与字符字模关系对照表
字符代码0x00~0x0F为用户自定义的字符图形RAM(对于5X8点阵的字符,可以存放8组,5X10点阵的字符,存放4组),就是CGRAM了。
0x20~0x7F为标准的ASCII码,0xA0~0xFF为日文字符和希腊文字符,其余字符码(0x10~0x1F及0x80~0x9F)没有定义。
以下是1602的16进制ASCII码表地址:读的时候,先读上面那行,再读左边那列,如:感叹号!的ASCII为0x21,字母B的ASCII为0x42(前面加0x表示十六进制)。
指令集
指令码
功能令:
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
说明
清显示
0
0
0
0
0
0
0
0
0
1
将DDRAM填满"20H",并且设定DDRAM的地址计数器(AC)到"00H"
归位
0
0
0
0
0
0
0
0
1
*
设定DDRAM的地址计数器(AC)到"00H",并且将游标移到开头原点位置;这个指令不改变DDRAM 的内容
显示开关控制指令
0
0
0
0
0
0
1
D
C
B
[D=1: 整体显示 ON],[C=1: 游标ON],[B=1:游标位置反白允许]
进入模式设置指令
0
0
0
0
0
0
0
1
I/D
S
I/D=1,光标或闪烁向右移动,AC增加1。I/D=0,光标或闪烁向左移动,AC减少1,S整个显示移动
光标或显示移位指令
0
0
0
0
0
1
S/C
R/L
*
*
光标或显示移位指令可使光标或显示在没有读写数据的情况下,向左或向右移动,指令不改变DDRAM 的内容
功能设定
0
0
0
0
1
DL
N
F
*
*
[DL=0/1:4/8位数据],[N=0/1,单行/双行显示],[F=0/1,5*8/5*10点阵显示模式]
设置CGRAM地址
0
0
0
1
AC5
AC4
AC3
AC2
AC1
AC0
CGRAM地址设置指令设置CGRAM地址指针,
设定DDRAM地址
0
0
1
0
AC5
AC4
AC3
AC2
AC1
AC0
DDRAM地址设置指令设置DDRAM地址。一行地址范围00H~4FH,两行DDRAM地址第一行00H~27H,第二行40H~67H,加上高2位,[一行:80H-A7H],[二行:C0H-E7H]
读忙标志和地址
0
1
BF
AC6
AC5
AC4
AC3
AC2
AC1
AC0
BF:忙标志位,BF=1,模块正在进行内部操作,此时模块不接受任何外部指令和数据。BF=0,模块可以接受外部的指令和数据;同时可以读出地址计数器(AC)的值。
写RAM指令
1
0
D7
D6
D5
D4
D3
D2
D1
D0
将数据D7-D0写入到内部的RAM (DDRAM/CGRAM/IRAM/GRAM),将用户自定义的字符写入CGRAM中,D7~D5为000,D4~D0为5点的字模数据
读RAM指令
1
1
D7
D6
D5
D4
D3
D2
D1
D0
从内部RAM读取数据D7——D0(DDRAM/CGRAM/IRAM/GRAM)
三、硬件设计(protell和proteus仿真)
原理图:温度和感烟部分
pcb板
protues仿真:
四、软件设计
声明:软件设计只实现了温度检测。proteus也只仿真了这部分
4.1LCD部分时序图
LCD1602的时序图解释
不同公司生产的1602液晶的时序图差不多都一样,所以MCU控制程序也差不多,一般都是通用的。下面来看一下它的时序图
五、设计总结
本次传感器课程设计-基于智能家居涵盖了温度检测,燃气泄漏,和火灾报警系统,基本上达到题目要求。
遇到了许多问题:
1. Protell里面好多的封装找不到,我都是自己画的。
2. 好多传感器不了解其用法,也不知道参数的实际选择。
3. 对单片机软件编写不够熟练
当然主要还是学到了很多东西:
1. 了解了各种传感器的应用,更深刻的理解了各种传感器的用法。
2. 了解了智能家居的发展历史和前景。
3. 对传感器参数有了跟进一步的认识和经验。
4. 对单片机系统也有了进一步的掌握。
六、参考文献
【1】Atmel公司AT89C51用户手册
【2】周润景,张丽娜.PROTEUS入门教程.北京:机械工业出版社,2007
【3】Keil Software公司。Keil uvision4用户手册。
【4】张丽娜,刘美玲,姜新华。51系统开发与实践.北京航空航天大学出版社
【5】自动检测技术与仪表控制系统.化学出版社
附件
代码如下
#include <AT89X52.h>
#include <Intrins.h>
#define DATA P1 //1602驱动端口
//ROM操作命令
#define READ_ROM 0x33 //读ROM
#define SKIP_ROM 0xCC //跳过ROM
#define MATCH_ROM 0x55 //匹配ROM
#define SEARCH_ROM 0xF0 //搜索ROM
#define ALARM_SEARCH 0xEC //告警搜索
//存储器操作命令
#define ANEW_MOVE 0xB8 //重新调出E^2数据
#define READ_POWER 0xB4 //读电源
#define TEMP_SWITCH 0x44 //启动温度变换
#define READ_MEMORY 0xBE //读暂存存储器
#define COPY_MEMORY 0x48 //复制暂存存储器
#define WRITE_MEMORY 0x4E //写暂存存储器
//数据存储结构
typedef struct tagTempData
{
unsigned char btThird; //百位数据
unsigned char btSecond; //十位数据
unsigned char btFirst; //个位数据
unsigned char btDecimal; //小数点后一位数据
unsigned char btNegative; //是否为负数
}TEMPDATA;
TEMPDATA m_TempData;
//引脚定义
sbit DQ = P2^7; //数据线端口
sbit RS= P2^0;
sbit RW= P2^1;
sbit E= P2^2;
//DS18B20序列号,通过调用GetROMSequence()函数在P1口读出(读8次)
const unsigned char code ROMData1[8] = {0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7}; //U1
const unsigned char code ROMData2[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E}; //U2
const unsigned char code ROMData3[8] = {0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9}; //U3
const unsigned char code ROMData4[8] = {0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0}; //U4
const unsigned char code ROMData5[8] = {0x28, 0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52}; //U5
const unsigned char code ROMData6[8] = {0x28, 0x35, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x65}; //U6
const unsigned char code ROMData7[8] = {0x28, 0x36, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x3C}; //U7
const unsigned char code ROMData8[8] = {0x28, 0x37, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x0B}; //U8
//判断忙指令
void Busy()
{
DATA = 0xff;
RS = 0;
RW = 1;
while(DATA & 0x80)
{
E = 0;
E = 1;
}
E = 0;
}
//写指令程序
void WriteCommand(unsigned char btCommand)
{
Busy();
RS = 0;
RW = 0;
E = 1;
DATA = btCommand;
E = 0;
}
//写数据程序
void WriteData(unsigned char btData)
{
Busy();
RS = 1;
RW = 0;
E = 1;
DATA = btData;
E = 0;
}
//清屏显示
void Clear()
{
WriteCommand(1);
}
//初始化
void Init()
{
WriteCommand(0x0c); //开显示,无光标显示
WriteCommand(0x06); //文字不动,光标自动右移
WriteCommand(0x38); //设置显示模式:8位2行5x7点阵
}
//显示单个字符
void DisplayOne(bit bRow, unsigned char btColumn, unsigned char btData, bit bIsNumber)
{
if (bRow) WriteCommand(0xc0 + btColumn);
else WriteCommand(0x80 + btColumn);
if (bIsNumber) WriteData(btData + 0x30);
else WriteData(btData);
}
//显示字符串函数
void DisplayString(bit bRow, unsigned char btColumn, unsigned char *pData)
{
while (*pData != '\0')
{
if (bRow) WriteCommand(0xc0 + btColumn); //显示在第1行
else WriteCommand(0x80 + btColumn); //显示在第0行
WriteData(*(pData++)); //要显示的数据
btColumn++; //列数加一
}
}
//延时16us子函数
void Delay16us()
{
unsigned char a;
for (a = 0; a < 4; a++);
}
//延时60us子函数
void Delay60us()
{
unsigned char a;
for (a = 0; a < 18; a++);
}
//延时480us子函数
void Delay480us()
{
unsigned char a;
for (a = 0; a < 158; a++);
}
//延时240us子函数
void Delay240us()
{
unsigned char a;
for (a = 0; a < 78; a++);
}
//延时500ms子函数
void Delay500ms()
{
unsigned char a, b, c;
for (a = 0; a < 250; a++)
for (b = 0; b < 3; b++)
for (c = 0; c < 220; c++);
}
//芯片初始化
void Initialization()
{
while(1)
{
DQ = 0;
Delay480us(); //延时480us
DQ = 1;
Delay60us(); //延时60us
if(!DQ) //收到ds18b20的应答信号
{
DQ = 1;
Delay240us(); //延时240us
break;
}
}
}
//写一个字节(从低位开始写)
void WriteByte(unsigned char btData)
{
unsigned char i, btBuffer;
for (i = 0; i < 8; i++)
{
btBuffer = btData >> i;
if (btBuffer & 1)
{
DQ = 0;
_nop_();
_nop_();
DQ = 1;
Delay60us();
}
else
{
DQ = 0;
Delay60us();
DQ = 1;
}
}
}
//读一个字节(从低位开始读)
unsigned char ReadByte()
{
unsigned char i, btDest;
for (i = 0; i < 8; i++)
{
btDest >>= 1;
DQ = 0;
_nop_();
_nop_();
DQ = 1;
Delay16us();
if (DQ) btDest |= 0x80;
Delay60us();
}
return btDest;
}
//序列号匹配
void MatchROM(const unsigned char *pMatchData)
{
unsigned char i;
Initialization();
WriteByte(MATCH_ROM);
for (i = 0; i < 8; i++) WriteByte(*(pMatchData + i));
}
//得到64位ROM序列(在P1口显示,必须与Proteus联调且在单步调试下才能得到)
/*void GetROMSequence()
{
unsigned char i;
Initialization();
WriteByte(READ_ROM);
for (i = 0; i < 8; i++)
P1 = ReadByte();
}*/
//读取温度值
TEMPDATA ReadTemperature()
{
TEMPDATA TempData;
unsigned int iTempDataH;
unsigned char btDot, iTempDataL;
static unsigned char i = 0;
TempData.btNegative = 0; //为0温度为正
i++;
if (i == 9) i = 1;
Initialization();
WriteByte(SKIP_ROM); //跳过ROM匹配
WriteByte(TEMP_SWITCH); //启动转换
Delay500ms(); //调用一次就行
Delay500ms();
Initialization();
//多个芯片的时候用MatchROM(ROMData)换掉WriteByte(SKIP_ROM)
switch (i)
{
case 1 : MatchROM(ROMData1); break; //匹配1
case 2 : MatchROM(ROMData2); break; //匹配2
case 3 : MatchROM(ROMData3); break; //匹配3
case 4 : MatchROM(ROMData4); break; //匹配4
case 5 : MatchROM(ROMData5); break; //匹配5
case 6 : MatchROM(ROMData6); break; //匹配6
case 7 : MatchROM(ROMData7); break; //匹配7
case 8 : MatchROM(ROMData8); break; //匹配8
}
//WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)
WriteByte(READ_MEMORY); //读数据
iTempDataL = ReadByte();
iTempDataH = ReadByte();
iTempDataH <<= 8;
iTempDataH |= iTempDataL;
if (iTempDataH & 0x8000)
{
TempData.btNegative = 1;
iTempDataH = ~iTempDataH + 1; //负数求补
}
//为了省去浮点运算带来的开销,而采用整数和小数部分分开处理的方法(没有四舍五入)
btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分
iTempDataH >>= 4; //得到整数部分
btDot *= 5; //btDot*10/16得到转换后的小数数据
btDot >>= 3;
//数据处理
TempData.btThird = (unsigned char)iTempDataH / 100;
TempData.btSecond = (unsigned char)iTempDataH % 100 / 10;
TempData.btFirst = (unsigned char)iTempDataH % 10;
TempData.btDecimal = btDot;
return TempData;
}
//数据处理子程序
void DataProcess()
{
m_TempData = ReadTemperature();
if (m_TempData.btNegative) DisplayOne(1, 6, '-', 0);
else DisplayOne(1, 6, m_TempData.btThird, 1);
DisplayOne
展开阅读全文