您的当前位置:首页正文

C51单片机技术应用与实践-温度测控

来源:画鸵萌宠网


第3篇 单片机接口应用

任务3 温度测控模块设计

问题的提出:

温度是工业、农业乃至人们日常生活中经常要测量的一个物理量,如:环境控制、设备或过程控制、智能建筑自控系统、测温类消费电子产品等(图3-1为农业大棚温度监测系统,图3-2为汽车自动空调),但是多数的温度传感器的输出时一个变化的模拟量,不能直接与计算机采集系统直接接口,需要先进行转换,才能出入计算机,比较麻烦。数字温度传感器的产生解决了这个问题,它可以直接将温度转变为相应的数字量。目前市场上常见的数字温度传感器有美国Dallas半导体公司的DS18xx系列的数字温度传感器和AD公司的AD74xx数字温度传感器。这里着重介绍一下DS18xx系列的数字温度传感器。

图3-1 农业大棚温度监测系统

图3-2 汽车自动空调

DS18xx系列的数字温度传感器采用的是Dallas的1-wire单总线专项技术,主要包括DS18B20、DS1820、DS1822等,其中DS18B20和DS1822是继DS1820的后续产品,在使用上

与后者兼容,只是在精度上有所差异。DS18B20提供9~12位精度的温度测量,电源供电电压范围3.0~5.5V,测量温度范围为-55℃~+125℃。在-10℃~+85℃范围内,测量精度是±0.5℃,增量值最小可以为0.0625℃,可以分别在93.75ms和750ms内完成9位和12位数字量的转换。DS18B20可以采用信号线寄生供电,不需要额外的外部供电。每个DS18B20有唯一的64位的序列码,这使得可以有多个DS18B20在一条单总线上工作。 3.1 1-Wire单总线的基本原理

1-wire 单总线是Maxim 全资子公司Dallas 的一项专有技术,与目前多数标准串行数据通信方式,如SPI/I2C/MICROWIRE 不同,它采用单根信号线,既传输时钟,又传输数据而且数据传输是双向的。它具有节省I/O 口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。

1-wire 总线由一个总线主节点、一个或多个从节点组成系统,通过一根信号线对从芯片进行数据的读取。每一个符合 1-Wire协议的从芯片都有一个唯一的地址,包括48位的序列号、8位的家族代码和8位的CRC代码。主芯片对各个从芯片的寻址依据这64位的不同来进行。1-Wire总线利用一根线实现双向通信,因此其协议对时序的要求较严格,如应答等时序都有明确的时间要求。基本的时序包括复位及应答时序、写一位时序、读一位时序。 在复位及应答时序中,主器件发出复位信号后,要求从器件在规定的时间内送回应答信号;在位读和位写时序中,主器件要在规定的时间内读回或写出数据。1-wire 单总线适用于单个主机系统,能够控制一个或多个从机设备。主机可以是微控制器,从机可以是单总线器件,它们之间的数据交换只通过一条信号线。当只有一个从机位于总线上时系统可按照单节点 系统操作;而当多个从机位于总线上,时则系统按照多节点系统操作。

为了较为全面地介绍单总线系统将系统分为三个部分讨论:硬件结构,命令序列和信号方式(信号类型和时序)。 3.1.1 硬件结构

图3-3 单总线的硬件接口示意图

顾名思义,单总线只有一根数据线。设备主机或从机通过一个漏极开路或三态端口连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。单总线端口为漏极开路,其内部等效电路如图3-3所示。

单总线要求外接一个约5k 的上拉电阻,这样单总线的闲置状态为高电平,不管什么原因,如果传输过程需要暂时挂起且要求传输过程还能够继续的话,则总线必须处于空闲状态位,传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。如果总线保持低电平超过480µs, 总线上的所有器件将复位。另外,在寄生方式供电时,为了保证单总线器件在某些工作状态下(如温度转换期间、EEPROM 写入等)具有足够的电源电流必须在总线上提供强上拉。 3.1.2 命令序列

1-Wire协议定义了复位脉冲、应答脉冲、写0、读0和读1时序等几种信号类型。所有的单总线命令序列(初始化,ROM命令,功能命令)都是由这些基本的信号类型组成的。在这些信号中,除了应答脉冲外,其他均由主机发出同步信号,并且发送的所有命令和数据都是字节的低位在前。 典型的单总线命令序列如下:

第一步:初始化;第二步:ROM 命令(跟随需要交换的数据);第三步:功能命令(跟随需要交换的数据)。

每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。但是,这个准则对于搜索ROM 命令和报警搜索命令例外,在执行两者中,任何一条命令之后,主机不能执行其后的功能命,令必须返回至第一步。 3.1.3 信号方式

单总线通信协议中存在两种写时隙:写0写1。主机采用写1时隙向从机写入1,而写0时隙向从机写入0。所有写时隙至少要60µs,且在两次独立的写时隙之间至少要1µs的恢复时间。两种写时隙均起始于主机拉低数据总线。产生1时隙的方式:主机拉低总线后,接着必须在15µs之内释放总线,由上拉电阻将总线拉至高电平;产生写0时隙的方式为在主机拉低后,只需要在整个时隙间保持低电平即可(至少60µs)。在写时隙开始后15~60µs期间,单总线器件采样总电平状态。如果在此期间采样值为高电平,则逻辑1被写入器件;如果为0,写入逻辑0。图3-4为写时隙(包括1和0)时序图,图中黑色实线代表系统主机拉低总线,黑色虚线代表上拉电阻将总线拉高。

图3-4 单总线通信协议中写时隙时序图

对于读时隙,单总线器件仅在主机发出读时隙时,才向主机传输数据。所有主机发出读数据命令后,必须马上产生读时隙,以便从机能够传输数据。所有读时隙至少需要60µs,且在两次独立的读时隙之间至少需要1µs恢复时间。每个读时隙都由主机发起,至少拉低总线1µs。在主机发出读时隙后,单总线器件才开始在总线上发送1或0。若从机发送1,则保持总线为高电平;若发出0,则拉低总线。

当发送0时,从机在读时隙结束后释放总线,由上拉电阻将总线拉回至空闲高电平状态。从机发出的数据在起始时隙之后,保持有效时间15µs,因此主机在读时隙期间必须释放总线,并且在时隙起始后的15µs之内采样总线状态。图3-5给出读时隙(包括0或1)时序,图中黑色实线代表系统主机拉低总线,灰色实线代表总局拉低总线,而黑色的虚线则代表上拉电阻总线拉高。

图3-5 单总线通信协议中写时隙时序图

单总线上所有的通信都是以初始化序列开始的,初始化序列包括主机发出的复位脉冲及从机的应答脉冲,这一过程如图3-6所示,黑色实线代表系统主机拉低总线,灰色实线代表从机拉低总线,而黑色的虚线则代表上拉电阻将总线拉高。

系统主设备发送端发出的复位脉冲是一个480~960µs的低电平,然后释放总线进入接收状态。此时系统总线通过4.7K的上拉电阻接至VCC高电平,时间约为15~60µs,接在接

受端的设备就开始检测I/O引脚上的下降沿以及监视在脉冲的到来。主设备处于这种状态下的时间至少480µs。

图3-6 初始化过程中的复位与应答脉冲

作为从设备在接收到系统主设备发出的复位脉冲之后,向总线发出一个应答脉冲,表示从设备已准备好,可根据各种命令发送或接收数据。通常情况下,器件等待15~60µs即可发送应答脉冲。 3.2 器件DS18B20

1) 特性和引脚介绍

DS18B20数字温度计以9~12位数字量的形式反映器件的温度值。DS18B20通过一个单线接口发送或接收信息,因此在中央微处理器和DS18B20之间仅需一条连接线(加上地线)。用于读写和温度转换的电源可以从数据线本身获得,无需外部电源。因为每个DS18B20都有一个独特的片序列号,所以多只DS18B20可以同时连在一根单线总线上,这样就可以把温度传感器放在许多不同的地方。这一特性在HVAC环境控制、探测建筑物、仪器或机器的温度以及过程监测和控制等方面非常有用。引脚排列如图3-7所示:

引脚 GND DQ 说明 地 数据I/O 可选的VDD 空脚 图3-7 DS18B20引脚排列及说明 2) DS18B20的主要部件及测温原理介绍

DS18B20有三个主要数字部件:(1)

VDD NC 64位激光

ROM,(2)温度传感器,(3)非易失性温度报警触发器TH和TL,主要内部框图如图3-8所示。器件用如下方式从单线通讯线上汲取能量:在信号线处于高电平期间把能量储存在内部电容里,在信号线处于低电平期间消耗电容上的电能工作,直到高电平到来再给寄生电源(电容)充电。DS18B20也可用外部5V电源供电。

图3-8 DS18B20内部方框图

(1)64位(激)光刻ROM

光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码。64位光刻ROM的排列是:开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。64位光刻ROM见图3-9所示。

图3-9 64位光刻ROM

DS18B20中有8位CRC存储在64位ROM的最高有效字节中。总线控制器可以用64位ROM中的前56位计算出一个CRC值,再用这个和存储在DS18B20中的值进行比较,以确定ROM数据是否被总线控制器接收无误。CRC计算等式如下:

CRC=X8+X5+X4+1

DS18B20同样用上面的公式产生一个8位CRC值,把这个值提供给总线控制器用来校验传输的数据。在任何使用CRC进行数据传输校验的情况下,总线控制器必须用上面的公式计算出一个CRC值,和存储在DS18B20的64位ROM中的值或DS18B20内部计算出的8位CRC值(当读暂存器时,做为第9个字节读出来)进行比较。CRC值的比较以及是否进行下一步

操作完全由总线控制器决定。

单线CRC可以用一个由移位寄存器和XOR门构成的多项式发生器来产生,如图3-10所示。

图3-10 CRC编码

移位寄存器的各位都被初始化为0。然后从系列编号的最低有效位开始,一次一位移入寄存器,8位系列编码都进入以后,序列号再进入,48位序列号都进入后,移位寄存器中就存储了CRC值。移入8位CRC会使移位寄存器复0。

(2)温度传感器

DS18B20通过一种片上温度测量技术来测量温度。温度测量电路方框图如图3-11所示。

斜率累加器预置低温度系数振荡器减法计数器1计数比较器预置增加减到0温度寄存器停止高温度系数振荡器减法计数器2减到0

图3-11 温度测量电路方框图

DS18B20是这样测温的:用一个高温度系数的振荡器确定一个门周期,内部计数器在这个门周期内对一个低温度系数的振荡器的脉冲进行计数来得到温度值。计数器被预置到对应于-55℃的一个值。如果计数器在门周期结束前到达0,则温度寄存器(同样被预置到-55℃)的值增加,表明所测温度大于-55℃。同时,计数器被复位到一个值,这个值由斜坡式累加器电路确定,斜坡式累加器电路用来补偿感温振荡器的抛物线特性。然后计数器又开始计数直到0,如果门周期仍未结束,将重复这一过程。

斜坡式累加器用来补偿感温振荡器的非线性,以期在测温时获得比较高的分辨力。这是通过改变计数器对温度每增加一度所需计数的的值来实现的。因此,要想获得所需的分辨力,必须同时知道在给定温度下计数器的值和每一度的计数值。DS18B20内部对此计算的结果可提供0.5℃的分辨力。温度以16bit带符号位扩展的二进制补码形式读出,表3-1给出了温

度值和输出数据的关系。数据通过单线接口以串行方式传输。

表3-1 温度/数据关系

温度℃ +125 +25 +1/2 0 -1/2 -25 -55 数据输出(二进制) 00000000 11111010 00000000 00110010 00000000 00000001 00000000 00000000 11111111 11111111 11111111 11001110 11111111 10010010 数据输出(十六进制) 00FA 0032 0001 0000 FFFF FFCE FF92 DS18B20测温范围-55℃~+125℃,以0.5℃递增。如用于华氏温度,必须要用一个转换因子查找表。注意DS18B20内温度表示值为1/2℃LSB,如下图3-12所示9bit格式:

图3-12 温度所示9bit格式

最高有效(符号)位被复制充满存储器中两字节温度寄存器的高MSB位,由这种“符号位扩展”产生出了示于表3-1的16bit温度读数。 (3)存储器

暂存器温度LSB温度MSBTH/ 用户字节 1TL/ 用户字节 2保留保留COUNT REMAINCOUNT PER ℃CRC字节012345678E2RAMTH/ 用户字节 1TL/ 用户字节 2

图3-13 DS8B20存储器结构示意图

DS18B20的存储器结构如图3-13所示 。由一个暂存RAM和一个存储高低温报警触发值TH和TL的非易失性电可擦除(E2)RAM组成。当在单线总线上通讯时,暂存器帮助确保数据的完整性。数据先被写入暂存器,这里的数据可被读回。数据经过校验后,用一个拷贝暂存器命令会把数据传到非易性(E2)RAM中。这一过程确保更改存储器时数据的完整性。

暂存器的结构为8个字节的存储器。头两个字节包含测得的温度信息。第三和第四字节是TH和TL的拷贝,是易失性的,每次上电复位时被刷新。下面两个字节没有使用,但是在读回数据时,它们全部表现为逻辑1。它们可以被用来获得更高的温度分辨力。还有一个第九字节,可以用读暂存器命令读出。这个字节是以上八个字节的CRC码。 3)、DS18B20工作过程

单线总线系统包括一个总线控制器和一个或多个从机,DS18B20是从机。关于这种总线要考虑以下三个方面:硬件结构、执行序列和单线信号(信号类型和时序)。

单线总线只有一条定义的信号线;重要的是每一个挂在总线上的器件都能在适当的时间驱动它。为此每一个总线上的器件都必须是漏极开路或三态输出。DS18B20的单总线端口(I/O引脚)是漏极开路式的,内部等效电路见图3-14所示。一个多点总线由一个单线总线和多个挂于其上的从机构成。单线总线需要一个约5KΩ的上拉电阻。

图3-14 DS18B20总线硬件结构

单线总线的空闲状态是高电平。无论任何理由需要暂停某一执行过程时,如果还想恢复执行的话,总线必必须停留在空闲状态。在恢复期间,如果单线总线处于非活动(高电平)状态,位与位间的恢复时间可以无限长。如果总线停留在低电平超过480μs,总线上的所有器件都将被复位。

通过单线总线端口访问DS18B20的协议如下: • 初始化 • ROM 操作命令 • 存储器操作命令 • 执行/数据 ① 初始化

通过单线总线的所有执行(处理)都从一个初始化序列开始。初始化序列包括一个由总线控制器发出的复位脉冲和跟有其后由从机发出的存在脉冲。存在脉冲让总线控制器知道DS18B20在总线上且已准备好操作。

② ROM操作命令

总线主机检测到DSl8B20的存在,便可以发出ROM操作命令之一,这些命令如: Read ROM(读ROM) [33H] :这个命令允许总线控制器读到DS18B20的8位系列编码、唯一的序列号和8位CRC码。只有在总线上存在单只DS18B20的时候才能使用这个命令。如果总上有不止一个从机,当所有从机试图同时传送信号时就会发生数据冲突(漏极开路连在一起开成相与的效果)。

Match ROM(匹配ROM)[55H]:匹配ROM命令,后跟64位ROM序列,让总线控制器在多点总线上定位一只特定的DS18B20。只有和64位ROM序列完全匹配的DS18B20才能响应随后的存储器操作命令。所有和64位ROM序列不匹配的从机都将等待复位脉冲。这条命令在总线上有单个或多个器件时都可以使用。

Skip ROM(跳过ROM)[CCH]:这条命令允许总线控制器不用提供64位ROM编码就使用存储器操作命令,在单点总线情况下可以节省时间。如果总线上不止一个从机,在Skip ROM命令之后跟着发一条读命令,由于多个从机同时传送信号,总线上就会发生数据冲突(漏极开路下拉效果相当于相与)。

Search ROM(搜索ROM)[F0H]:当一个系统初次启动时,总线控制器可能并不知道单线总线上有多少器件或它们的64位ROM编码。搜索ROM命令允许总线控制器用排除法识别总线上的所有从机的64位编码。

Alarm search(报警搜索)[ECH]:这条命令的流程和Search ROM相同。然而,只有在最近一次测温后遇到符合报警条件的情况,DS18B20才会响应这条命令。报警条件定义为温度高于TH或低于TL。只要DS18B20不掉电,报警状态将一直保持,直到再一次测得的温度值达不到报警条件。

③ 存储器操作命令

Write Scratchpad [4EH]:这个命令向DS18B20的暂存器中写入数据,开始位置在地址2。接下来写入的两个字节将被存到暂存器中的地址位置2和3。可以在任何时刻发出复位命令来中止写入。

Read Scratchpad[BEH]:这个命令读取暂存器的内容。读取将从字节0开始,一直进行下去,直到第9(字节8,CRC)字节读完。如果不想读完所有字节,控制器可以在任何时间发出复位命令来中止读取。

Copy Scratchpad [48H]:这条命令把暂存器的内容拷贝到DS18B20的E2存储器里,即把温度报警触发字节存入非易失性存储器里。如果总线控制器在这条命令之后跟着发出读时间隙,而DS18B20又正在忙于把暂存器拷贝到E2存储器,DS18B20就会输出一个“0”,如果拷贝结束的话,DS18B20则输出“1”。如果使用寄生电源,总线控制器必须在这条命令发出后立即起动强上拉并最少保持10ms。

Convert T [44H]:这条命令启动一次温度转换而无需其他数据。温度转换命令被执行,而后DS18B20保持等待状态。如果总线控制器在这条命令之后跟着发出读时间隙,而DS18B20又忙于做时间转换的话,DS18B20将在总线上输出“0”,若温度转换完成,则输出“1”。如果使用寄生电源,总线控制器必须在发出这条命令后立即起动强上拉,并保持500ms。

Recall E2[B8H]:这条命令把报警触发器里的值拷回暂存器。这种拷回操作在 DS18B20 上电时自动执行,这样器件一上电暂存器里马上就存在有效的数据了。若在这条命令发出之后发出读时间隙,器件会输出温度转换忙的标识:“0”=忙,“1”=完成。

Read Power Supply[B4H]:若把这条命令发给 DS18B20 后发出读时间隙,器件会返回它的电源模式:“0”=寄生电源,“1”=外部电源。

④ I/O信号

DS18B20需要严格的协议以确保数据的完整性。协议包括几种单线信号类型:复位脉冲、存在脉冲、写0、写1、读0和读1。所有这些信号,除存在脉冲外,都是由总线控制器发出的。

和DS18B20间的任何通讯都需要以初始化序列开始,初始化序列见图3-10。一个复位脉冲跟着一个存在脉冲表明DS18B20已经准备好发送和接收数据(适当的ROM命令和存储器操作命令。)

3.3 DS18B20工作时序 1) 初始化

时序见图3-15主机总线t0时刻发送一复位脉冲(tRSTL最短为480us的低电平信号),接着在t1时刻释放总线并进入接收状态,DSl820在检测到总线的上升沿之后等待15-60us,接着DS18B20在t2时刻发出存在脉冲(tPDLOE低电平持续60-240us)如图3-15中虚线所示,以判断是否有应答信号。

图3-15 初始化过程“复位和存在脉冲”图

2) 读/写时间隙

DS18B20的数据读写是通过时间隙处理位和命令字来确认信息交换。 a、写时间隙

当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。有两种写时间隙:写1时间隙和写0时间隙。所有写时间隙必须最少持续60μs,包括两个写周期间至少1μs的恢复时间。

I/O线电平变低后,DS18B20在一个15μs到60μs的窗口内对I/O线采样。如果线上是高电平,就是写1,如果线上是低电平,就是写0,见图3-16读写时序图。

主机要生成一个写时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15μs内允许数据线拉到高电平。主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60μs。

b、读时间隙

当从DS18B20读取数据时,主机生成读时间隙。当主机把数据线从高平拉到低电平时,写时间隙开始。数据线必须保持至少1μs;从DS18B20输出`的数据在读时间隙的下降沿出现后15μs内有效。因此,主机在读时间隙开始后必须停止把I/O脚驱动为低电平15μs,以读取I/O脚状态,见图3-16读写时序图。在读时间隙的结尾,I/O引脚将被外部上拉电阻拉到高电平。所有读时间隙必须最少60μs,包括两个读周期间至少1μs的恢复时间。

图3-16 读写时序图

3.4 温度测控模块设计 3.4.1 目标要求

采用DS18B20进行外部温度测量,并通过数码管显示当前的温度测量值,当温度高于100℃,显示为XXX℃;温度低于100℃高于10℃,显示为XX.X℃;温度低于10℃高于0℃,显示为X.X℃;温度低于0℃高于-10℃,显示为-X.X℃;温度低于-10℃,显示为-XX℃。 3.4.2 问题分析

考虑到温度测控模块中采用的是DS18B20单线式温度传感器,所以在程序编写过程中要严格注意其协议以及对时序的要求。 3.4.3 硬件设计

1)仿真原理图

温度测控模块主要电路原理图如图3-17所示。 +5VRP112345678910kP00P01P02P03P04P05P06P07+5VR145k1DQ321U2VCCDQGNDDS18B20+5V24.5U119XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617P20P21P22P23P00P01P02P03P04P05P06P0723456789111U3D0D1D2D3D4D5D6D7LEOE74HC573+5VR6Q0Q1Q2Q3Q4Q5Q6Q71918171615141312P23R51k5kQ4855018XTAL2SEG3SEG2SEG1SEG0R9+5VSEG31009RSTR4P22+5V293031PSENALEEAR31k5kQ38550R10+5VSEG21001234567DQ8R7P20P1.0/T2P1.1/T2EXP1.2P1.3P1.4P1.5P1.6P1.7AT89C52R81k5kQ28550P21SEG0R2R11k5kQ18550R12100R11100SEG1 图3-17 温度测控模块主要电路图 2)温度测控模块的主要元器件清单 温度测控模块主要元件清单见表3-2。

表3-2 温度测控模块主要元件清单

元器件名称 单片机 晶振 电解电容 瓷片电容 温度传感器 二极管 三极管 IC 3.4.4 软件编程 1)端口分配

参数 STC89C52 12MHz 100μF/16V 30pF DS18B20 1N4148 8550 74HC573 数量 1 1 1 2 1 1 4 1 元器件名称 电阻 电阻 电阻 电阻 电阻 排阻 数码管 按钮 参数 100 200 1k 2k 5k1 10k 共阳 - 数量 4 1 1 4 5 1 4 1 温度测控模块主要电路原理图如图3-17所示,DS18B20的数据I/O口与单片机的P1.7口相连,为了证在有效的时钟周期内提供足够的电流,该端口需要加一个5.1kΩ上拉电阻;显示采用4位数码管显示当前温度,最低位显示温度单位“℃”,P0口作为数码管段选,P2口的低4位作为数码管位选。 2) 程序流程

程序中子函数有delaynms(int x) 、Read_Temperature()、Data_Display()、Data_Process()、Error_Display(),其中delaynms(int x)为毫秒级延时子程序、Read_Temperature()为读温度值子程序、Data_Display()为数据显示子程序、Data_Process()为显示数据处理子程序、Error_Display()为DS18B20检测出错显示子程序。

温度测量设计程序主要包括主程序(如图3-18)、温度读取子程序(如图3-19)等,具体如下:

开始DS18B20初始化开始系统初始化N应答信号?Y发跳过ROM命令读DS18B20的值发温度转换命令DS18B20是否正常?Y读取当前温度值并数据转换N延时,等待温度转换完成DS18B20初始化发跳过ROM命令待显示数据处理DS18B20出错显示“Err”读取两个字节温度数据温度数据转换为10进制数据结束显示当前的测量温度 图3-18 主程序流程图 图3-19 温度读取子程序流程图 3) 具体程序

#include //包含单片机寄存器的头文件 #include //包含_nop_()函数定义的头文件 #define uchar unsigned char #define uint unsigned int sbit DQ=P1^7;

//定义P1.7为DS18B20数据端 //传感器正常标志位 //温度值正负标志位

结束

bit DS18B20_IS_OK=1; bit Plus_Minus =0;

bit Point=0; //小数点显示标志位 uchar time;

//用于延时

//温度计算的整数、小数

uchar Number,Decimal;

uchar Temp_Value[]={0,0}; //读取温度值寄存器

uchar Display_Digit[]={0,0,0,0x0c}; //暂存待显示的各温度数位 uchar Error[]={0x86,0xaf,0xaf,0x0ff};

//没有检测到DS18B20.出错、检查

uchar code Num_Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x70}; /************函数功能:延时若干毫秒 入口参数:x ***************/ void delaynms(int x) { }

/********函数功能:初始化DS18B20,返回status,1:不存在、0:存在********/ bit Init_DS18B20( ) {

bit status;

//储DS18B20是否存在的标志,status=0,表示存在;status=1,表示不存在

}

DQ = 1;

//先将数据线拉高

//初始化DS18B20

uchar i; while(x--) for(i=0;i<123;i++);

for(time=0;time<3;time++) //略微延时约6微秒 ;

DQ = 0;

//再将数据线从高拉低,要求保持480~960us

for(time=0;time<150;time++) //略微延时约600微秒 ;

//以向DS18B20发出一持续480~960us的低电平复位脉冲 //释放数据线(将数据线拉高)

DQ = 1; for(time=0;time<15;time++) ;

//延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)

status=DQ; //让单片机检测是否输出了存在脉冲(DQ=0表示存在) for(time=0;time<100;time++) //延时足够长时间,等待存在脉冲输出完毕 ; DQ=1; return status;

/**********函数功能:从DS18B20读取一个字节数据 出口参数:dat************/ unsigned char ReadOnebyte() { }

/***********函数功能:向DS18B20写入一个字节数据 入口参数:dat*************/ uchar WriteOnebyte(uchar dat) {

unsigned char i=0; for (i=0; i<8; i++) {

DQ =1; _nop_();

// 先将数据线拉高 //等待一个机器周期

unsigned char i,dat; for(i=0;i<8;i++) {

DQ =1; _nop_();

// 先将数据线拉高 //等待一个机器周期

//储存读出的一个字节数据

DQ = 0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序 dat>>=1; _nop_();

//等待一个机器周期

DQ = 1; //将数据线\"人为\"拉高,为单片机检测DS18B20的输出电平作准备 for(time=0;time<2;time++) ; if(DQ==1) dat|=0x80; else dat|=0x00;

//如果读到的数据是0,则将0存入dat

//如果读到的数据是1,则将1存入dat

//延时约6us,使主机在15us内采样

for(time=0;time<15;time++) ;

//延时30us,两个读时序之间必须有大于1us的恢复期

} return dat;

//返回读出的十进制数据

DQ=0; DQ=dat&0x01;

//将数据线从高拉低时即启动写时序

//利用与运算取出要写的某位二进制数据,并将其送到数据线上等待DS18B20采样 }

/******************函数功能:做读温度的准备**********************/ void ReadyReadTemp(void) { }

/********函数功能:从DS18B20读取的温度值并转换为十进制数**************/ void Read_Temperature() {

if(Init_DS18B20()==1) DS18B20_IS_OK=0;

//DS18B20不存在

Init_DS18B20(); WriteOnebyte(0xCC); WriteOnebyte(0x44);

//将DS18B20初始化 //跳过读序号列号的操作 //启动温度转换 //温度转换需要一点时间

}

for(time=0;time<15;time++) ;

//稍作延时,给硬件一点反应时间

for(time=0;time<10;time++) ;

//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样

//释放数据线

DQ=1;

for(time=0;time<2;time++) ;

//延时3us,两个写时序间至少需要1us的恢复期 //将dat中的各二进制位数据右移1位

dat>>=1;

for(time=0;time<100;time++) ;

Init_DS18B20(); WriteOnebyte(0xCC);

//将DS18B20初始化 //跳过读序号列号的操作

WriteOnebyte(0xBE); //写读取温度寄存器命令,前两个分别是温度的低位和高位

else {

DS18B20_IS_OK=1; ReadyReadTemp();

//DS18B20存在

//准备读数据

Temp_Value[0]=ReadOnebyte(); //准备读低8位数据 Temp_Value[1]=ReadOnebyte(); //准备读高8位数据 Plus_Minus =0;

if((Temp_Value[1]&0xF8)==0xF8) //判断正负温度,负的 { }

Number=Temp_Value[1]*16+Temp_Value[0]/16;

Plus_Minus =1;

//负温度标志位置1 ,温度值为取反加1

Temp_Value[1]=~Temp_Value[1]; Temp_Value[0]=(~Temp_Value[0])+1; if(Temp_Value[0]==0x00) Temp_Value[1]++;

//实际温度值=(TH*256+TL)/16, 即:TH*16+TL/16,得出的整数部分

Decimal=(Temp_Value[0]%16)*10/16;

//将余数乘以10再除以16取整,得到小数部分的第一位数字(保留1位小数)

}

/***************函数功能:显示前数据处理******************/ void Data_Process() {

if(Plus_Minus ==1) {

Display_Digit[0]=0x0b; if(Number>9) {

Display_Digit[1]=Number/10;

//取十位

//首位显示“-”

//判断整数部分是否大于9?

//判断所读温度数据是否为负温度

}

}

Display_Digit[2]=Number%10; //取个位 Point=0; } else {

Display_Digit[1]=Number; Display_Digit[2]=Decimal; Point=1; }

//整数部分小于10,取整数部分(个位) //取小数部分

//小数点标志位置一,显示

//小数点标志位置零,不显示

else {

//所读温度数据为正

if(Number>99) {

//整数部分大于99

Display_Digit[0]=Number/100; //取百位 Display_Digit[1]=(Number/10)%10; //取十位 Display_Digit[2]=Number%10; Point=0; }

else if(Number>9) {

Display_Digit[0]=Number/10;

//取十位

//整数部分大于9

//取个位

//小数点标志位置零,不显示

Display_Digit[1]=Number%10; //取个位 Display_Digit[2]=Decimal; Point=1; } else {

//整数部分小于9

//取小数部分

//小数点标志位置一,显示

Display_Digit[0]=0x0a; //高位不显示 //取个位

Display_Digit[1]=Number;

}

}

Display_Digit[2]=Decimal; Point=1; }

//取小数部分

//小数点标志位置一,显示

/***************函数功能:数据显示******************/ void Data_Display(void) {

P2=0xf7;

//开第四位数码管

//取第四位要显示数据的代码 //显示延时2ms

P0=Num_Tab[Display_Digit[0]]; delaynms(2); P0=0xff; P2=0xfb;

//开第三位数码管 //判断是不是要显示小数点

if(Point==1) {

P0=Num_Tab[Display_Digit[1]]&0x7f; //取第三位要显示数据的代码,显示小数点 } else {

P0=Num_Tab[Display_Digit[1]]; }

//显示延时2ms

//取第三位要显示数据的代码,不显示小数点

delaynms(2); P0=0xff; P2=0xfd;

//开第二位数码管

//取第二位要显示数据的代码

P0=Num_Tab[Display_Digit[2]]; delaynms(2); P0=0xff; P2=0xfe;

//开第一位数码管

//取第一位要显示数据的代码

P0=Num_Tab[Display_Digit[3]]; delaynms(2);

}

P0=0xff; P2=0xff;

/*********函数功能:检测不到DS18B20,显示“Err” **********/ void Error_Display(void) {

uchar i; P2=0xf7; for(i=0;i<4;i++) {

P0=Error[i]; delaynms(3); P2=P2>>1; } }

/***********函数功能:主函数 ************/ void main(void) {

delaynms(5);

//延时5ms给硬件一点反应时间

while(1) {

Read_Temperature();

//读取的温度值,主要用于判断DS18B20是否正常

//DS18B20是否正常

if(DS18B20_IS_OK==1) {

Read_Temperature(); } else {

Data_Process();

//读取的温度值,并转换成十进制 //显示数据处理

Data_Display(); //显示当前测量温度值

//DS18B20不正常

}

}

Error_Display(); //显示“Err”,表示出错

}

3.4.5 温度测控模块的仿真效果

DS18B20正常测量时的仿真效果如图3-20所示。 +5VRP112345678910kP00P01P02P03P04P05P06P07+5VR145k1DQ321U2VCCDQGNDDS18B2024.5U119XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617P20P21P22P23P00P01P02P03P04P05P06P0723456789111U3D0D1D2D3D4D5D6D7LEOE74HC573Q0Q1Q2Q3Q4Q5Q6Q71918171615141312P23R6R51k5kQ4855018XTAL2SEG3SEG2SEG1SEG0+5VR9+5V100SEG39RSTR4P22+5V293031PSENALEEAR31k5kQ38550R10+5V+5V100SEG21234567DQ8R7P20P1.0/T2P1.1/T2EXP1.2P1.3P1.4P1.5P1.6P1.7AT89C52R81k5kQ28550P21SEG0R2R11k5kQ18550R12100R11100SEG1 图3-20 DS18B20的仿真图 3.5 总结与提高 DS18B20虽然具有测温系统简单、测温精度高、连接方便、占用口线少等优点,但在实际应用中也应注意以下几方面的问题:

1、较小的硬件开销需要相对复杂的软件进行补偿,由于DS18B20与微处理器间采用串行数据传送,因此,在对DS18B20进行读写编程时,必须严格的保证读写时序,否则将无法读取测温结果。

2、在DS18B20的有关资料中均未提及单总线上所挂DS18B20数量问题,容易使人误认为可以挂任意多个DS18B20,在实际应用中并非如此。当单总线上所挂DS18B20超过8个时,就需要解决微处理器的总线驱动问题,这一点在进行多点测温系统设计时要加以注意。

3、连接DS18B20的总线电缆是有长度限制的。试验中,当采用普通信号电缆传输长度超过50m时,读取的测温数据将发生错误。当将总线电缆改为双绞线带屏蔽电缆时,正常通

讯距离可达150m,当采用每米绞合次数更多的双绞线带屏蔽电缆时,正常通讯距离进一步加长。这种情况主要是由总线分布电容使信号波形产生畸变造成的。因此,在用DS18B20进行长距离测温系统设计时要充分考虑总线分布电容和阻抗匹配问题。

4、在DS18B20测温程序设计中,向DS18B20发出温度转换命令后,程序总要等待DS18B20的返回信号,一旦某个DS18B20接触不好或断线,当程序读该DS18B20时,将没有返回信号,程序进入死循环。这一点在进行DS18B20硬件连接和软件设计时也要给予一定的重视。

测温电缆线建议采用屏蔽4芯双绞线,其中一对线接地线与信号线,另一组接VCC和地线,屏蔽层在源端单点接地。

本单元实践练习

任务要求:

按照下列要求完成温度测控模块的设计,可以根据需要设计修改原理图。

1、参照图3-17,设计一温度控制程序,当检测温度低于25℃时,蜂鸣器开始慢速“滴”声报警,并且P1.6口发光二极管点亮(模拟制热);当检测温度高于30℃时,蜂鸣器开始快速“滴”声报警,并且P1.4口控制继电器吸合启动直流电机(模拟制冷)。

2、参照图3-21,采用DS18B20进行外部温度测量,通过按键进行温度的设定,并通过1602液晶显示当前的温度测量值和已设定的温度值;当外部温度大于设定温度值时启动电动机,同时声音报警,正常工作指示灯熄灭;当外部温度大于设定温度值时正常工作指示灯点亮,同时关闭电动机和声音报警。

3、参照图3-21,通过按键设定两个温度值(下限、上限),当测量温度高于上限是电机高速运转;当测量温度低于下限是电机停止运转;当测量温度处于上下限之间是电机低速运转;同时在液晶上显示当前电机的状态。

+5VRP1123456789P00P01P02P03P04P05P06P07+5VVSSVDDVEERSRWE456P27P26P2512310k10k10k10k19设置P00P01P02P03P04P05P06P077891011121314R1R2R3D0D1D2D3D4D5D6D7增大XTAL118减小9+5V293031XTAL2RSTP0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617P00P01P02P03P04P05P06P07R55kP15R41kQ1PNPLS1PSENALEEAP25P26P27+5VSPEAKERR14U226.5VCCDQGND32110kP14P15P1612345678P1.0/T2P1.1/T2EXP1.2P1.3P1.4P1.5P1.6P1.7AT89C52R7P14R81k5kQ2PNPDS18B20U1D1P16LED-GREENR6200+5V+5VRL15V 图3-21 DS18B20温控电路原理图

因篇幅问题不能全部显示,请点此查看更多更全内容

Top