HD7279应用文章——基于单片机的多点温度监测系统设计



作者:戴怀斌

  注意:经我的实验hd7279的耐压性能不是太好,最好不要超过5.5v。
1.1 多点温度监测系统概述
  针对现有温度采集系统结构复杂、温度检测精度不高的特点提出了基于单片机的多点温度监测系统设计方案。设计中采用数字式 温度传感器DS18B20来采 集温度值并用STC89C52RC单片机来进行数据处理并控制相关电路的工作,具有检测方便、灵活性大、精度高等优点。当温 度超过预设温度上下限时,系统 将发出警报并记录相应警报的类型和时间。具有一定的参考价值。
1.2 本设计任务和主要内容
  用C51或汇编语言对多点温度检测系统中单片机编程,实现对多点温度的监测,实时显示监测的温度值。具体要求为:
  1. 多点温度检测,制作2点温度检测线路板,测温范围为-40C—1000C。
2.实时显示2点被测温度值。
  3.用户可设定温度报警阈值,当被测温度值超出阈值范围时,蜂鸣器报警。
4.测温误差<±0.5℃。
  电路设计 本次硬件电路设计采用模块化设计思路,可分为:控制电路模块、温度检测模块、声光报警电路、存储器模块、时钟模块等电路组 成。下面就各部分电路设计作具体 的介绍:
2.1 系统硬件组成
  本系统由温度采集电路、单片机控制电路,键盘显示电路,时钟电路,存储电路及报警电路组成。系统总体原理框图如图2-1 所示。其中,单片机控制电路主 要由STC89C52及与单片机连接的相应的外围电路组成,负责处理数据并控制其它电路的运行。温度采集电路主要由温度传感 器DS18B20及其外围器件 组成,负责温度的采集。键盘显示电路由专用管理芯片HD7279及八位数码管、按键构成。时钟芯片DS12887及存储芯片 AT24C16将为系统提供实 时时间及报警信息存储的功能。报警电路将在温度超限时提供声光报警。

img2_1
图2-1 系统总体原理框图
2.2 控制电路设计
  该部分电路是系统的控制和数据处理的核心,而作为控制核心的单片机种类很多,如PIC等等。根据任务书的要求以及系统实 际的需要,采用 STC89C52RC作为系统的微控制器芯片。
  本次设计最小系统是由单片机STC89C52RC、6MHZ的晶振、复位电路所构成。单片机最小系统电路如图2-2所 示。

img2_2
图2-2 最小系统电路
2.3温度测量电路设计
  温度测量模块由DS18B20与单片机构成,在设计时,选择温度传感器十分重要。考虑到对课题的测温要求:-400C— 1000C,因此选择 DS18B20温度传感器来采集温度,因为此传感器的测量范围满足设计要求,且测温误差<±0.5℃。DS18B20 智能温度传感器采用单总线接 口,即只需一根DQ数据线接入P1口,这样使得温度测量电路的设计变得非常简单。温度采集电路原理图如图2-3所示。

img2_3
图2-3 温度采集电路原理图
2.4 键盘及显示电路设计
  HD7279A和微处理器之间采用串行接口,其接口电路和外围电路简单,占用口线也较少,而且此电路不仅提供了显示输出 功能,还提供了键盘输入电路, 能达到本电路模块的基本要求,加之它具有较高的性能价格比,并且因此,本设计选择了此方案。键盘显示电路如图2-4所示。

img2_4
图2-4 键盘显示电路
2.5 时钟电路设计
  由于本系统需记录温度报警的发生结束时间,因而需设计时钟电路。时钟电路的实现方案有许多,例如可运用时钟芯片 HT1380等。此类芯片为串行工作方 式,虽电路连接较为简单,但需要配置特定频率的晶振,其走时的准确性与晶振的频率准确性密切相关。除此之外,还需设计掉电保 护电路,并配置备用电池。这都 将进一步增加电路的复杂程度。因此本次设计采用了内置晶振和锂电池的实时时钟芯片DS12887。其原理图如图2-5所示。

img2_5
图2-5 DS12887时钟电路原理图
2.6 存储器电路设计
  在存储芯片选择上,目前的种类有很多,大体上可分为RAM和ROM两大类,RAM芯片在掉电后不能保存数据,对本次设计 没有意义。ROM芯片也有串行 和并行两类,在容量、存取速度也有很大差别。本次设计主要是存取环境温度的报警代码和时间信息,要求存储芯片具有较好的稳定 性与读写速度,所以采用串行的 E PROM芯片AT24C16。其原理图如图2-6所示。

img2_6
图2-6 AT24C16存储电路原理图
2.7 声光报警电路设计
  当外界温度超过预设温度上下限时,为更加有效的引起用户的注意,及时关注温度的变化,本系统设计了声光报警电路。该电路 由发光二极管及蜂鸣器组成,具 体电路如图2-7所示。

img2_7
图2-7 声光报警电路
2.8 硬件资源分配
本系统硬件电路分配如表2-1所示。
表2-1 外围芯片资源分配表:

img2_1
系统软件设计
  在现代智能仪器系统中,硬件必须在软件的配合下,才能实现它强大的功能。好的软件设计,甚至能够弥补硬件设计上的一些缺 陷。所以软件设计思想,是整个 设计中较为重要的一部分。在本系统中,软件设计要力求做到以下几点:
(1) 软件结构清晰,简捷,流程合理。
  (2) 各功能程序实现模块化,子程序化。这样即便于调试,链接,又便于移植与修改。
  (3) 程序存储区,数据存储区要合理规划,既能节约内存容量,又使操作方便。
  本次软件设计主要实现多点温度监测系统的程序设计,其主要功能为测量温度并将测量到的温度数据实时显示与发送给系统。设 计采用模块化方式,由温度采集 模块、键盘显示模块、时钟模块、存储模块、报警模块等组成。
  单片机编程语言常用的有两种,一种是汇编语言,另一种是C51 语言。汇编语言的机器代码生成效率很高,但是可读性并不强,复杂一点的程序就更难读懂,而C51语言在大多数情况下其机器代 码生成效率和汇编语言相当,但 可读性和可移植性却远远超过了汇编语言,而且C51语言还可以嵌入汇编来解决高实效性的代码编写问题。对于开发周期来 说,C51
  语言的开发周期通常小于汇编语言很多。因此本次设计采用C51语言来编程。
3.1主程序设计
  主程序主要实现对系统的初始化设置,超限温度值设定、键盘的扫描及温度数据的存储、判断、温度的显示等功能。
其流程图如图3-1所示。

img3_1
 图3-1主程序流程图
3.2 温度采样子程序
  DS18B20只有一根线进行数据传输,所以特别的注意其工作时序。工作时序包括:初始化时序、写时序和读时序。每种工 作时序都有相应的要求,这在进 行DS18B20接口程序设计时必须足够重视。
3.2.1 DSl8B20初始化时序
   主机使用时间隙(time slots)来读写DSl8B20的数据位和写命令字的位。初始化时主机总线to时刻发送一复位脉冲(最短为480us的低 电平信号)接着在tl时刻释放 总线并进入接收状态DSl820在检测到总线的上升沿之后等待15-60us接着DS1820在t2时刻发出存在脉冲(低电 平持续60-240 us)如图中虚线所示以下子程序在MCS51仿真机上通过其晶振为6M.初始化时序如图3-2所示:

img3_2
3.2.2 DSl8B20读写时序
  CPU对DS18B20的访问流程是:先对DS18B20初始化,再进行ROM操作命令,最后才能对存储器操作,数据操 作。DS18B20每一步操作 都要遵循严格的工作时序和通信协议。如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三 个步骤:每一次读写之前都要对 DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。读 写时序如图3-3与3-4所 示。

img3_56
  DS18B20温度传感器接口模块,分为初始化子程序,写入子程序及读取子程序,转换子程序等部分组成,温度采集程序与 温度转化程序流程图如图3-5 与3-6所示。设计时由于每一个单片机上一个端口只挂了一个DS18B20所以不需读DS18B20的序列号,可直接将采集 温度值送显。

img3_56
图3-5 温度测量流程图 图3-6 温度转换流程图
3.3 HD7279键盘显示子程序
  本系统键盘显示电路采用专用管理芯片HD7279,HD7279的控制指令分为二大类——纯指令和带有数据的指令。前者 有复位、左移和右移指令,后者 在本次设计中采用了下载数据但不译码方式,此指令灵活,通过造字行表,可以显示用户所需的字符。本设计运用查询方式显示数字 及字符,方便简单。
此处采用的带数据的控制指令如表3-1所示:

img3_1
表3-1 控制指令表

 表中,a2,a1,a0为位地址,A-G和DP为显示数据,分别对应7段LED数码管的各段。
1.HD7279A的时序
  (1)纯指令时序:微处理器发出8个CLK脉冲,向HD7279A传送8位指令。DATA引脚为高阻状态,如图3-7所 示。
图3-7 纯指令时序

img3_7
  (2)带数据指令时序:微处理器发出16个CLK脉冲,前8个向HD7279A传送8位指令;后8个向HD7279A传 送8位数据。DATA引脚为高 阻状态,如图3-8所示。

img3_8
图3-8带数据指令时序
  (3)读键盘指令时序:微处理器发出16个CLK脉冲,前8个向HD7279A传送8位指令, DATA引脚为高阻状态;后8个由HD7279A向微处理器返回8位按键代码,DATA引脚为输出状态。在最后1个CLK脉 冲的下降沿DATA引脚恢复高 阻状态,如图3-9所示。

img3_9
图3-9带数据指令时序
2.HD7279显示流程图

img3_10
3.4时钟子程序
  本设计时钟芯片采用DS12887,其内部存储器地址分布图如3-11所示。

img3_2
图3-11 DS12887内部存储器地址分布图
在实际工作中其实际地址如表3-2所示。

img3_2
表3-2 寄存器实际地址分配
程序开始时,清除以前存储的显示数据。显示提示时间设置,判断是否有键按下,如果没有键按下,返回继续判断。如果有键按下, 判断按键是否正确,如果不正确 继续返回判断按键是否按下。如果正确的话,设置相应位。保存该设置并且提示完成。
  系统工作时可通过改变相应寄存器中的数据值来完成时间的修改及各项功能的设定,其流程图如3-12所示。

img3_12
图3-12时钟程序流程图
3.5设定温度上下限值子程序
  本程序的主要功能为完成温度监测仪的温度上下限值的设定,为防止系统掉电及遭受干扰时温度上下限值数据丢失,因此在 DS12887的用户RAM中开辟 了 2个内存单元分别保存温度的上限值以及下限值。其具体地址温度上限值DF40温度下限值DF42。由于DS12887在没有 外部电源的情况下还是可以正常 工作,因而避免了因为数据值得丢失而造成系统的工作异常。
  程序开始时,数码管清屏并提示设置温度,显示提示现在温度上下限值。按键1设置为上限值数值设置开始,显示提示设置温度 上限,依次设置百十个位,判断 设定值是否超限并提示错误,如果不超限则提示设置成功并保存设置值。按键2设置为下限值数值设置开始,显示提示设置温度下 限,依次设置百十个位,判断设定 值是否超限并提示错误,如果不超限则提示设置成功并保存设置值。当按到其他按键的时候,CPU不做任何处理。
  程序运行时,只需改变2个寄存器中的数据值即可完成对温度上下限的设定。其流程图为3-13。

img3_13
3.6 报警子程序
  报警子程序主要功能是当温度高于设定温度或低于设定温度状态下时,系统将会报警,并显示报警信号。报警程序运行时,通过 将单片机相应端口置为低电平, 点亮报警指示灯。并通过更改DS12887相应工作寄存器中的数据,另其输出方波信号,控制蜂鸣器报警。当前实际温度也将通 过LED数码管闪烁显示。高于 指定温度报警子程序如图3-14所示,低于指定温度子程序如图3-15所示。

img3_1415
  关闭系统报警电路时,程序将单片机相应端口置为高电平,以关闭报警指示灯。并通过更改DS12887相应工作寄存器中的 数据,关闭方波信号输出,停止 蜂鸣器报警。同时清除LED报警显示。其流程图如图3-16所示。

img3_16
图3-16停止报警子程序
3.7清除报警记录子程序
  系统工作时,报警记录存储于外部存储器AT24C16中,所有报警记录按照时间先后顺序存储,因此若要清除报警记录只需 将存储末条报警记录的单元及其 之前的内存单元全部清除。
  程序运行时,首先显示提示等待用户按键,若用户选择清除则再次提示按键确认。完成两次确认后系统将所有报警记录删除。若 用户未按键确认则程序退出。
  AT24C16的字节读写首先需要一个8位的器件地址,这个地址是由硬件连接决定的,当AT24C16收到MCU送来的 地址是将和本芯片的硬件连接地 址比较,如果一样,AT24C16将送出一个低电平的应答信号并锁存地址等待读写,接着AT24C16将接收要读写的数据的 数据地址,AT24C16在收 到数据地址后仍回送低电平应答信号,并等待读写数据。
  写操作:在字节写模式下STC89C52RC发送起始命令和AT24C16器件地址信息(R/W位置零)给 AT24C16。在AT24C16产生应答 信号后,单片机发送AT24C16的字节地址,在收到另一个应答信号后再发送数据到被寻址的存储单元。当AT24C16再次 应答并在STC89C52RC 产生停止信号后开始内部数据的擦写,在内部擦写过程中,AT24C16不再应答主器件的任何请求。用页写AT24C16可一 次写入16个字节数据。数据页 写操作的启动和字节写一样,不同在于传送了一字节数据后并不产生停止信号,主器件被允许发送其余额外的字节,每发送一个字节 数据后产生一个应答信号,并将 字节地址低位加1高位保持不变。接收到最后一个字节数据和主器件发送的停止信号后 AT24C16启动内部写周期将数据写到数据区。所有接收的数据在一个写周期内写入AT24C16。AT24C16的字节写 入时序及页写入时序如图 3-17、3-18

img3_1718img3_18

所示。其流程图如3-19。
img3_29
图3-19 清除报警记录子程序流程图
3.8显示报警记录子程序
  程序运行时,将从外部存储器AT24C16中依次读取报警记录并加以显示。由于报警记录所占用的存储空间一定,因而可通 过固定的算法获得每条报警记录 存储的首地址,继而将所有记录一次显示。每条记录采取滚动显示方式,用户可通过按键控制记录翻页显示。其流程图如3-20所 示。


  读操作:对 AT24C16读操作的初始化方式和写操作时一样,仅把R/W 位置为1。首先通过发送起始信号、器件地址和它想读取的字节数据的地址执行一个伪写操作,在AT24C16应答之后,单片机 重新发送起始信号和器件地址, 此时R/W 位置1,AT24C16响应并发送应答信号,然后输出所要求的一个8 位字节数据,主器件不发送应答信号但产生一个停止信号。连续读操作在启动在AT24C16发送完一个8
  位字节数据后主器件产生一个应答信号来响应告知AT24C16主器件要求更多的数据,对应每个主机产生的应答信号 AT24C16将发送一个8 位数据字节,当主器件不发送应答信号而发送停止位时结束此操作。AT24C16的任意地址数据及当前起始地址数据读时序如图 3-21 及图3-22所示。
img3_20
图3-22显示报警记录子程序流程图

img3_22
3.9 中断服务子程序
  中断服务程序的主要功能是响应外部中断0,其主要功能为完成原始键值到按键编号的转换,系统工作时,键盘显示控制芯片 HD7279的KEY端接与单片 机外部中断0相接,当有按键按下时,KEY端被置为低电平,触发外部中断0服务程序,程序运行时,首先将按键标志位置1,后 通过串行方式从HD7279中 读取按键的原始键值,并将其转换为相应的键值代码以方便其他程序使用。其流程图如3-23。

img3_22
图3-23中断程序流程图
  结束语采用单片机STC89C52RC处理温度数据的多点温度监测系统的设计已基本实现所要求的功能。本系统能够提供直 观的温度数据显示。从那些温度 数据的变化情况,人们可以了解特定环境的温度变化状况。然后,可针对不利环境采取一系列的措施。
  本系统也有一些不完善的地方。例如:可以通过红外无线技术实现远程测温,这样就能够运用到各种密闭的环境中;没有完备的 抗干扰措施防止系统在恶劣环境 下受到干扰。
  通过这次课程设计,我学到了许多东西,我想这对自己今后的学习或者工作都会有很大的帮助,特别是对大四的毕业论文。以前 一直不知道用word写一篇论 文原来
  是这么的不容易,现在对word运用的更熟练了。当然更重要的是进一步消化了课堂里学的一些知识的同时,我对单片机的学 习产生了更加浓厚的兴趣。
  参考文献 1 张迎新.单片微型计算机原理、应用及接口技术. 北京:国防工业出版社,2004
  2 胡伟等. 单片机C语言程序设计及应用实例[M]. 北京:人民邮电出版社,2003
  3 王福瑞等. 单片微机测控系统设计大全[M]. 北京航空航天大学出版社, 2004
  4 吕长飞等. 基于AT89C52智能温度控制器设计[J]. 微计算机信息, 2007.20
  5 张萍等. 基于数字温度计DS18B20的温度测量仪的开发[J]. 自动化仪表, 2007.6
  6 何希才.传感器及其应用[M].北京: 国防工业出版社, 2000
  7 林占江.电子测量技术[M].北京:电子工业出版社, 2003
  8 何立民等. 单片机应用系统设计[M]. 北京:北京航空航天出版社, 1993
  9 张友德. 单片机原理与应用技术. 北京:机械工业出版社, 2004
  10 张鑫,单片机原理及应用.北京:电子工业出版社,2008

附录1:主要程序
/************************************************* ************
函数功能:该函数用来启动时钟芯片工作
************************************************** ***********/
void StartDs12c887(void)
{ chRegA = CMD_START_DS12C887;
} /************************************************* ************
函数功能:该函数用来关闭时钟芯片
************************************************** ***********/
void CloseDs12c887(void)
{ chRegA = CMD_CLOSE_DS12C887;
} void InitDs12c887()
{ StartDs12c887();
chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */
chRegB=(chRegB | MASK_SETB_DM | MASK_SETB_2412 )& MASK_CLR_DSE;
/* 使用BCD码格式、24小时模式、不使用夏令时 */
chCenturyChannel = 0x21; /* 设置为21世纪 */
chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取秒字节
************************************************** ***********/
BYTE GetSeconds(void)
{ return(chSecondsChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取分字节
************************************************** ***********/
BYTE GetMinutes(void)
{ return(chMinutesChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取小时字节
************************************************** ***********/
BYTE GetHours(void)
{ return(chHoursChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取日字节
************************************************** ***********/
BYTE GetDate(void)
{ return(chDateChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取月字节
************************************************** ***********/
BYTE GetMonth(void)
{ return(chMonthChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取年字节
************************************************** ***********/
BYTE GetYear(void)
{ return(chYearChannel);
} /************************************************* ************
函数功能:该函数用来从时钟芯片读取世纪字节
************************************************** ***********/
BYTE GetCentury(void)
{ return(chCenturyChannel);
} /************************************************* ************
函数功能:该函数用来设置时钟芯片的时间
chSeconds、chMinutes、chHours是设定时间的压缩BCD码
************************************************** ***********/
void SetTime(BYTE chSeconds,BYTE chMinutes,BYTE
chHours) { chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */
chSecondsChannel = chSeconds;
chMinutesChannel = chMinutes;
chHoursChannel = chHours;
chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */
} /************************************************* */
函数功能:该函数用来设置时钟芯片的日期
chDate、chMonth、chYear是设定日期的压缩BCD码
************************************************** */
void SetDate(BYTE chDate,BYTE chMonth,BYTE chYear)
{ chRegB = chRegB | MASK_SETB_SET; /* 禁止刷新 */
chDateChannel = chDate;
chMonthChannel = chMonth;
chYearChannel = chYear;
chRegB = chRegB & MASK_CLR_SET; /* 使能刷新 */
} /************************************************* /
void Write_Hd7279(BYTE Command,BYTE Data) /*HD7279写函数*/
{ Send_Byte(Command);
Send_Byte(Data);
} /*************************************************
BYTE Read_Hd7279(BYTE Command) /*HD7279读函数*/
{ Send_Byte(Command);
return(Receive_Byte());
} /*********************************************/
void Send_Byte(BYTE Data_Out) /*HD7279发送字节函数*/
{ BYTE i; delay(0x30);
for(i=0;i<8;i++)
{ if(Data_Out&0x80) Set_Bit(Hd7279_Data);
else Clear_Bit(Hd7279_Data);
Set_Bit(Hd7279_Clk);
delay(8); Clear_Bit(Hd7279_Clk);
delay(8); Data_Out=Data_Out<<1;
} Clear_Bit(Hd7279_Data);
} /*********************************************/
BYTE Receive_Byte(void) /*HD7279接收字节函数*/
{ BYTE i,Data_In;
Set_Bit(Hd7279_Data);
delay(0x30);
for(i=0;i<8;i++)
{ Set_Bit(Hd7279_Clk);
delay(8); Data_In=Data_In<<1;
if(Hd7279_Data) Data_In=Data_In|0x01;
Clear_Bit(Hd7279_Clk);
delay(8); } Clear_Bit(Hd7279_Data);
return(Data_In);
} /**********************************************/
/**********************************************/
/* 24c01-24c16读写驱动程序, */
/**********************************************/
void s24(void)
{ _nop_(); At24C16_Scl=0;
At24C16_Sda=1;
At24C16_Scl=1;
_nop_(); At24C16_Sda=0;
_nop_(); At24C16_Scl=0;
} void p24(void)
{ At24C16_Sda=0;
At24C16_Scl=1;
_nop_(); At24C16_Sda=1;
} BYTE rd24(void)
{ At24C16_Sda=1;
At24C16_Scl=1;a7=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a6=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a5=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a4=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a3=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a2=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a1=At24C16_Sda;At24C16_Scl=0;
At24C16_Scl=1;a0=At24C16_Sda;At24C16_Scl=0;
At24C16_Sda=1;At24C16_Scl=1;At24C16_Scl=0;
return(ACC);
} void wd24(BYTE dd)
{ ACC=dd; At24C16_Sda=a7;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a6;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a5;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a4;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a3;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a2;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a1;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=a0;At24C16_Scl=1;At24C16_Scl=0;
At24C16_Sda=1;At24C16_Scl=1;
} BYTE read(UNIT AT24c16_add)
{ BYTE dd; dd=((AT24c16_add&0x7ff)/256)<<1;
s24(); wd24(0xa0|dd);
At24C16_Scl=0;
wd24(AT24c16_add);
At24C16_Scl=0;
s24(); wd24(0xa1|dd);
At24C16_Scl=0;
dd=rd24(); p24(); return(dd);
} void write(UNIT AT24c16_add,BYTE dd)
{ BYTE ddd; ddd=((AT24c16_add&0x7ff)/256)<<1;
s24(); wd24(0xa0|ddd);
At24C16_Scl=0;
wd24(AT24c16_add);
At24C16_Scl=0;
wd24(dd); At24C16_Scl=0;
  p24(); //time=0; //time为定时器时间参考,time增加1代表1ms,如果没有用定时器,取消该行
while (1) { s24(); wd24(0xa0|ddd);
At24C16_Sda=1;
if (At24C16_Sda==0) break;
//if (time>10) break; //此行防止由于eeprom器件损坏后的死循环
At24C16_Scl=0;
} } static unsigned char Power=0;
unsigned char Temper=0;
/***************************/
/* 功能:10us 级别延时 */
/***************************/
void Delay10us(unsigned char n)
{ while(n--) { NOP_1uS;NOP_1uS;NOP_1uS;
NOP_1uS;NOP_1uS;NOP_1uS;
NOP_1uS; } } /***************************/
/* 功能:写18B20 */
/***************************/
void Write_18B20(unsigned char n)
{ unsigned char i;
for(i=0;i<8;i++)
{ DQ=0; Delay10us(1);//延时13us 左右
DQ=n & 0x01;
n=n>>1; Delay10us(5);//延时50us 以上
DQ=1; } } /***************************/
/* 功能:读取18B20 */
/***************************/
unsigned char Read_18B20(void)
{ unsigned char i;
unsigned char temp;
for(i=0;i<8;i++)
{ temp=temp>>1;
DQ=0; NOP_1uS;//延时1us
DQ=1; NOP_1uS;NOP_1uS;//延时5us
NOP_1uS;NOP_1uS;NOP_1uS;
if(DQ==0) { temp=temp&0x7F;
}else { temp=temp|0x80;
} Delay10us(5);//延时40us
DQ=1; } return temp;
} /***************************/
void Init (void)
{ DQ=0; Delay10us(50);//延时500us
DQ=1; Delay10us(9);//延时90us
if(DQ==1) //0001 1111b=1f
{ Power =0; //失败0
}else { Power++; DQ=1;
} } /***************************/
void Skip(void)
{ Write_18B20(0xcc);
Power++; } /***************************/
void Convert (void)
{ Write_18B20(0x44);
Power++; } /***************************/
void Delay1S (void)
{ static unsigned int i=0;
if (i++==Seck) {i=0;Power++;}
} /***************************/
void ReadDo (void)
{ Write_18B20(0xbe);
Power++; } /***************************/
void ReadTemp (void)
{ union { unsigned char Temp[2]; //单字节温度
int Tt; //2字节温度
}T; T.Temp[1]=Read_18B20(); //读低位
T.Temp[0]=Read_18B20(); //读高位
//-----------------------------------
Power=0; T.Tt <<= 4;
Temper=T.Temp[0];
} void delay(BYTE n)
{ BYTE i; for(i=0;i<n;i++)
{ _nop_(); } }


***敬请使用firefox或chrome浏览器以取得最佳效果***
Copyrigh1999-2011 北京凌志比高科技有限公司 版权所有
电话:(010) 62981567,82895285,82895286,13391571388 传真:82895286
地址:北京市海淀区上地信息路一号国际创业园 1号楼402室(100085)