1、AVR 学习笔记 七、基于 DS18B20 的温度测量实验 7.1 基于 DS18B20 的基本测温实验 7.1.1、 实例功能 传统的温度测量采用热敏电阻,但热敏电阻存在可靠性差,测温准确率低,并且必须经过专门的接口电路将 采集到的模拟量转换为数字量后才能由单片机处理 。 DS18B20 是美国 DALLAS 公司推出的一款单线数字温度传感器。 它具有:体积小,功耗低,精度高,可靠性好,易于单片机接口等优点, 每片 DS18B20 都有唯一的一个可读出的序列号,同时 DS18B20 还采用了寄生电源技术,可以不用外接电源 。综合以上特点,DS18B20 特别适合于多点测温系统。 本节 首先
2、介绍 DS18B20 的一些基本知识 :特点、结构、原理、控制时序、与单片机的接口方法等。最后通过一个实例实现最简单的温度测量。 本实例分为三个功能模块,分别描述如下: 单片机系统: 利用 ATmega16 单片机与 DS18B20 温度传感器通信,控制温度的 采集过程,并将采集到的温度值通过串口发送到计算机 。 外围 电路: 外围电路分两部分:串口电路部分 (实现将采集到的温度值发送到计算机的功能)、 DS18B20 温度采集电路(实现采集环境温度的功能)。 软件程序: 编写软 件,实现 温度测量和串口发送数据功能。 通过本实例的学习,掌握以下内容: 理解 DS18B20 的特点、结构和原理
3、 和接口设计方法 。 掌握 DS18B20 的控制时序和控制方法流程。 掌握最简单的采集温度指令。 7.1.2 器件和原理 1、 DS18B20 介绍 DS18B20 主要有以下特点: 单线接口: DS18B20 与单片机连接时仅需一根 I/O 口线即可实现单片机与 DS18B20之间的双向通信。 实际使用中不需要任何外围元件。 可用数据线供电,电压范围 3.0-5.5V。测温范围 -55-+125oC。 可编程实现 9-12 位的数字读数方式。 用户可设定的非易失性(掉电不丢失)的温度上下线报警值。 支持多点组网功能,多个 DS18B20 可并联在唯一的三总线上,实现多点温度测量。 负压特性
4、:电源极性接反时不会烧坏 DS18B20,但是也不能正常工作 DS18B20 的外形级封装如图 7.1.1, 引脚说明: NC 空引脚,不连接外部信号。 VDD 电源引脚,电压范围 3.0-5.5V。 GND 接地引脚。 DQ 数据引脚, 传递数据的输入和输出。该引脚常态下为开漏输出,输出高电平。 图 7.1.1 DS18B20 的外形级封装 7.1.2DS18B20 的内部结构 DS18B20 的内部结构如图 7.1.2。 DS18B20 的内部结构主要有 64 位 ROM、温度灵敏元件、内部存储器和配置寄存器四部分组成。 图 7.1.2 DS18B20 的内部结构 64 位 ROM: 64
5、 位 ROM 的内容是 64 位序列号,是出厂前 用激光刻好的。它可以用作该 DS18B20 的地址序列码。每一个 DS18B20 的 64 位 ROM 都不同,这样就可以实现一根总线上挂多个 DS18B20 的目的 。这 64 位 ROM 的排列是:开始 8 位是产品类型号,接着的 48 位是该 DS18B20 的自身的序列号,最后 8 位是前面 56 位的 循环冗余( CRC,CRC=X8+X5+X4+1)校验码。 温度灵敏元件 :温度灵敏元件完成对温度的测量,测量后的结果存储在两个 8 位 的寄存器中,这两个寄存器定义如图 7.1.3。温度寄存器高字节的高 5 位是符号位,温度为负时这
6、5 位为 1;温度为正时,这 5 位为 0。高字节寄存器的低 3 位与低字节寄存器的高 4 位 组成温度的整数部分,低字节寄存器的低 4 位是温度的小数部分。当温度大于 0 时,温度值以原码存放。而当 温度小于 0 时,以二进制补码形式存放 。 当转换位数为 12 位时,温度的精度为 1/16( 4 位小数位,所以为 16) =0.0625 度 。同理,当转换位数为 11 位时,精度为 1/8=0.125 度。 对于温度的计算,以 12 位转换位数为例:对于正的温度,只要将 测到的数值的整数部分取出,转换为 10 进制, 再将 小数部分 乘以 0.0625 就可以得到 10 进制的小数位的温度
7、值了。而对于负的温度,则 需要将采集到的数值取反加 1,即可得到实际温度的 16 进制表示。再按照正温度的计算方法就可以得出 10 进制的负的温度了。 图 7.1.3 DS18B20 温度寄存器格式 图 7.1.4 所示是在 12 位转换位数情况下的温度转换值和温度对照表 图 7.1.4 12 位转换位数的温度转换值和温度对照表 7.1.3 DS18B20 的内部存储器 DS18B20 的内部存储器包括一个告诉暂存 RAM 和一个非易失性的可电擦除的EEPROM,后者存放 温度的上下限报警值和配置寄存器。 高速暂存 RAM 以及 EEPROM 的构成 如图 7.1.5 所示。高速暂存 RAM
8、由 9 个字节组成,当温度转换命令发出后,经转换 获得的温度值以二进制补码形式存放在第 0( LSB) 和第一( MSB) 个字节内。单片机通过单线接口 DQ 读出该数据, 读取时低位在前,高位在后 。第二和第三个字节是温度的上( TH)下限( TL)报警值 ,他们没有小数位,第四个字节是配置寄存器 ,主要用以设置工作模式和转换位数。第五、第六和第七字节是保留位,没有实际意义,第八个字节是前面 所有 8 个字节的 CRC 校验码。 EEPROM 由 3 个字节 构成 ,用来存放温度的上下限报警值以及配置寄存器的内容。 图 7.1.5 高速暂存 RAM 以及 EEPROM 的构成 配置寄存器的各
9、位 意义如图 7.1.6 所示。 低五位 的读出值总是为 1,第 7 位是测试模式位,用于设置 DS18B20 是工作在测试模式还是工作模式 ,出厂时默认设置为 0,用户不用改动。R1 和 R0 用来设置温度转换位数。 具体设置如图 7.1.7 所示。 图 7.1.6 配置寄存器结构 图 7.1.7 温度值转换位数设置表 7.1.4 DS18B20 控制流程 再由 DS18B20 构成的单总线系统中, DS18B20 只能作为从机,单片机或者其 它部件作为主机。 根据 DS18B20 的通信协议,主机控制 DS18B20 完成一次温度转换必须经过 3 个步骤: 一)、每次读写之前都要对 DS1
10、8B20 进行复位操作 二 )、复位成功后发送一条 ROM 指令 三)、最后发送 RAM 指令,这样才能够对 DS18B20 进行正确的操作。 复位:复位要求主机将数据线拉低最少 480us,然后释放,当 DS18B20 受到信号后,等待 15-60us,然后把总线拉低 60-240us,主机接收到此信号表示复位成功。 ROM 指令: ROM 指令表明了主机寻址一个或多个 DS18B20 中的某个或某几个,或者是读取某个 DS18B20 的 64 位序列号。 RAM 指令: RAM 指令用于主机对 DS18B20 内部 RAM 的操作(如启动温度转换、读取温度等)。 1、 ROM 操作命令 :
11、 DS18B20 采用一线通信接口。因为一线通信接口,必须在先完成 ROM设定,否则记忆和控制功能将无法使用。 一旦总线检测到从属器件的存在,它便可以发出器件 ROM 操作指令,所有 ROM 操作指令均为 8 位长度, 主要提供以下功能命令: 1 )读 ROM(指令码 0X33H):当总线上只有一个 节点(器件)时,读此节点的 64 位序列号。如果总线上存在多于一个的节点,则此指令不能使用。 2 ) ROM 匹配 (指令码 0X55H):此命令后跟 64 位的 ROM 序列号,总线上只有与此序列号相同的 DS18B20 才会做出反应 ;该指令用于选中某个 DS18B20,然后对该 DS18B2
12、0 进行读写操作。 3 )搜索 ROM(指令码 0XF0H): 用于确定接在总线上 DS18B20 的个数和识别所有的 64 位ROM 序列号。当系统开始工作,总线主机可能不知道总线上的器件个数或者不知道其 64 位ROM 序列号,搜索命令用于识别所有连接于总线上 的 64 位 ROM 序列号。 4 )跳过 ROM(指令码 0XCCH) : 此指令只适合于总线上只有一个节点;该命令通过允许总线主机不提供 64 位 ROM 序列号而直接访问 RAM,以节省操作时间。 5 )报警检查 (指令码 0XECH) : 此指令与搜索 ROM 指令基本相同,差别在于只有温度超过设定的上限或者下限值的 DS1
13、8B20 才会作出响应。只要 DS18B20 一上电,告警条件就保持在设置状态,直到另一次温度测量显示出非告警值,或者改变 TH或 TL 的设置使得测量值再一次位于允许的范围之内。储存在 EEPROM 内的触发器用于告警。 这些指令 操作作用在 每 一个器件的 64 位光刻 ROM 序列号,可以在挂在一线上多个器件选定某一个器件,同时,总线也可以知道总线上挂有有多少,什么样的设备。 2、 RAM 指令 DS18B20 有六条 RAM 命令: 1)温度转换 (指令码 0X44H) :启动 DS18B20 进行温度转换 ,结果存入内部 RAM。 2)读暂存器 (指令码 0XBEH): 读暂存器 9
14、 个字节内容 ,此指令从 RAM 的第 1 个字节(字节 0)开始读取,直到九个字节(字节 8, CRC 值)被读出为止。如果不需要读出所有字节的内容,那么主机可以在任何时候发出复位信号 以中止读操作。 3)写暂存器 (指令码 0X4EH): 将 上下限温度报警值和配置数据写入到 RAM 的 2、 3、 4字节,此命令后跟需要些入到这三个字节的数据。 4)复制暂存器 (指令码 0X48H): 把暂存器的 2、 3、 4 字节 复制到 EEPROM 中 ,用以掉电保存。 5)重新调 E2RAM(指令码 0XB8H): 把 EEROM 中的 温度上下限及配置字节恢复到 RAM 的 2、3、 4 字
15、节,用以上电后恢复以前保存的报警值及配置字节。 6)读电源供电方式 (指令码 0XB4H): 启动 DS18B20 发送电源供电方式的信号给主 CPU。对于 在此命令送至 DS18B20 后所发出的第一次读出数据的时间片,器件都会给出其电源方式的信号。“ 0”表示寄生电源供电。“ 1”表示外部电源供电。 7.1.5 DS18B20 的操作时序 ( 本人查看数据手册和网上的例程,然后结合实际测试结果 ) 1、 DS18B20 的初始化 ( 1) 先将数据线置高电平 “1” 。 ( 2) 延时(该时间要求的不是很严格,但是尽可能的短一点) 。 ( 3) 数据线拉到低电平 “0” 。 ( 4) 延时
16、 490 微秒(该时间的时间范围可以从 480 到 960 微秒)。 ( 5) 数据线拉到高电平 “1” 。 ( 6) 延时等待(如果初始化成功则在 15到 60 毫秒时间之内产生一个由 DS18B20 所返回的低电平 “0” 。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。 ( 7) 若 CPU 读到了数据线上的低电平 “0” 后,还要做延时,其延时的时间从发出的高电平算起(第( 5)步的时间算起)最少要 480 微秒。 ( 8) 将数据线再次拉高到高电平 “1” 后结束。 2、 DS18B20 的写操作 ( 1) 数据线先置低电平
17、“0” 。 ( 2) 延时确定的时 间为 2(小于 15)微秒。 ( 3) 按从低位到高位的顺序发送字节(一次只发送一位)。 ( 4) 延时时间为 62( 大于 60) 微秒。 ( 5) 将数据线拉到高电平 ,延时 2(小于 15)微秒 。 ( 6) 重复上( 1)到( 6)的操作直到所有的字节全部发送完为止。 ( 7) 最后将数据线拉高。 3、 DS18B20 的读操作 ( 1)将数据线拉高 “1” 。 ( 2)延时 2 微秒。 ( 3)将数据线拉低 “0” 。 ( 4)延时 2(小于 15) 微秒。 ( 5)将数据线拉高 “1” ,同时端口应为输入状态 。 ( 6)延时 4(小于 15)
18、微秒。 ( 7)读数据线的状态得到 1 个状态位,并进行数据处理。 ( 8)延时 62(大于 60) 微秒。 7.1.3、电路和连接 串口电路前面已经介绍,本例中不再重复。本例中 DS18B20 与单片机的连接如图 7.1.8所示, 由于 DS18B20 的数据线要求空闲状态为高电平,所以我在 DS18B20 的数据线与电源线 VCC 之间加了一个 4.7K的上拉电阻,如果不想接上拉电阻的话,可以使能 PA2 口的内部上拉功能。 从图中可以看出,本例使用的是给 DS18B20 外接电源的方式。 DS18B20 的数 据线 DQ 连到单片机的 PA2 口。单片机通过控制 PA2 口实现对 DS1
19、8B20的操作 。 图 7.1.8 DS18B20 电路 7.1.4、程序设计 1、程序功能 程序的功能是使用单片机的 PA2 口的 实现对 DS18B20 的操作 ,然后将读出的温度值通过串口发送到计算机 。 2 函数说明 本程序 多个功能函数 ,分别是: 端口初始化函数 ,设置 各端口的初始工作状态 。 串口通信相关函数: void Usart_Init(void); /USART 寄存器设置 void Usart_PutChar(unsigned char cTXData); /字节发送函数 void Usart_PutString(unsigned char *pcString); /
20、字符串发送函数 这些函数已经在前面的实例中做过介绍,在此不再重复 。 DS18B20 操作相关函数: void Port_DS18b20(void); /DS18B20 端口配置 ,配置 DS18B20 端口的初始状态。 unsigned char DS18B20_Init(void); /DS18B20 初始化 ,主机发送复位脉冲信号,DS18B20 接收到复位信号后发出应答信号,单片机检测复位是否成功。 unsigned char Read_18b20(void); /读 18b20,读取 DS18B20 发送过来的 1 字节数据。 void Write_18b20(unsigned ch
21、ar dat); /写 18b20,向 DS18B20 写 1 字节函数。 延时相关函数: void Delayus(unsigned int lus); /us 延时函数 void Delayms(unsigned int lms); /ms 延时函数 由于 WINAVR 自带函数库中的延时函数使用起来很不方便,并且晶振频率不同,延时时间也有区别,而对 DS18B20 的操作时序要求比较严格,所以本实例中 自己写了两个延时函数。 3、 使用 WINAVR 开发环境,使用的是外部 12M 的晶振,所以需要将 makefile 文件中的时钟频率修改为 12M。另外在程序烧录到单片机的时候,熔丝位
22、也要选择为外部 12M 晶振( 注意是晶振,不是外部振荡器 ,一定不要选择错了,否则会导致单片机不能再烧写程序)。 4、程序说明 。在本实例中我们只是要首先了解 DS18B20 的原理和特点,至于例程在只要简单实现 利用单片机实现对单个 DS18B20 的温度测量即可。所以 在程序中 我们对温度测量的处理是: 1) 复位(假定复位成功,不检测复位是否成功), 2) 发送跳过 ROM 指令(我们系统只连接了一个 DS18B20,所以可以使用这条指令 ) , 3)发送温度转换命令( 我们采用 DS18B20 默认的 12 位 温度转换,所以不用对 DS18B20进行任何配置,直接指示 DS18B2
23、0 开始采集温度 ) , 4)延时 1S,等待 DS18B20 完成温度采集 (默认 12 位温度转换时,采集一次温度的时间为750ms,所以至少要延时 750ms 以上 ) , 5)复位( 每次对 DS18B20 进行操作都要进行 复位 、 ROM 操作、 RAM 操作 这三个步骤 ), 6) 发送跳过 ROM 指令 7)发送 读内部 RAM 命令( 这个指令读取 DS18B20 中 RAM 的全部 9 个字节,而我们只需要得到温度值就可以了 ,温度值存储在 RAM 的前两个字节里面 ,所以我们读取 完前两个字节的内容后可以不必理会后面的内容 ), 8) 将采集到的温度值进行处理 (判断温度
24、的正负,分离温度的整数位和小数位 ),然后将处理后的数据发送到串口。 9)延时 4S,然后 跳到步骤 1),重复步骤 1)-8),完成下一次温度测量 5、程序代码 #include #include #include /中断函数头文件 /引脚宏定义 /18B20 定义 #define SET_DQ (PORTA) |= (1 4); /获得温度的整数位 tempint1 = tempint / 1000; /千位 tempint2 = tempint % 1000 / 100; /百位 tempint3 = tempint % 100 / 10; /十位 tempint4 = tempint
25、% 10; /个位 temppoint = Temp_L /取出温度的小数位 temppoint = (temppoint * 625); /小数位乘以 0.625 得出温度的小数位值,在此扩大 /10000 倍,得出温度的 4 位小数位,显示的时候加小数点 temppoint1 = temppoint / 1000; /千位 temppoint2 = temppoint % 1000 / 100; /百位 temppoint3 = temppoint % 100 / 10; /十位 temppoint4 = temppoint % 10; /个位 Usart_PutString(“当前环境温度为: “); /发送温度值到上位机 if(!(tempint1) /高位为零, 则不显示 Usart_PutChar( );