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