当前位置:首页 >> 信息与通信 >>

马伟力AVR笔记:七、基于DS18B20的温度测量实验


AVR 学习笔记七、基于 DS18B20 的温度测量实验 学习笔记七 -------基于 LT_Mini_M16 基于
7.1 基于 DS18B20 的基本测温实验
7.1.1、实例功能 、 传统的温度测量采用热敏电阻,但热敏电阻存在可靠性差,测温准确率低,并且必须 经过专门的接口电路将采集到的模拟量转换为数字量后才能由单片机处理。 DS18B20 是美国 D

ALLAS 公司推出的一款单线数字温度传感器。它具有:体积小,功 耗低,精度高,可靠性好,易于单片机接口等优点,每片 DS18B20 都有唯一的一个可读出 的序列号,同时 DS18B20 还采用了寄生电源技术,可以不用外接电源。综合以上特点, DS18B20 特别适合于多点测温系统。 本节首先介绍 DS18B20 的一些基本知识:特点、结构、原理、控制时序、与单片机的 接口方法等。最后通过一个实例实现最简单的温度测量。 本实例分为三个功能模块,分别描述如下: ● 单片机系统:利用 ATmega16 单片机与 DS18B20 温度传感器通信,控制温度的采集 过程,并将采集到的温度值通过串口发送到计算机。 ● 外围电路:外围电路分两部分:串口电路部分(实现将采集到的温度值发送到计算 机的功能) 、DS18B20 温度采集电路(实现采集环境温度的功能) 。 ● 软件程序:编写软件,实现温度测量和串口发送数据功能。 通过本实例的学习,掌握以下内容: ● 理解 DS18B20 的特点、结构和原理和接口设计方法。 ● 掌握 DS18B20 的控制时序和控制方法流程。 ● 掌握最简单的采集温度指令。 7.1.2 器件和原理 1、DS18B20 介绍 、 DS18B20 主要有以下特点: ●单线接口:DS18B20 与单片机连接时仅需一根 I/O 口线即可实现单片机与 DS18B20 之间的双向通信。 ●实际使用中不需要任何外围元件。 ●可用数据线供电,电压范围 3.0-5.5V。测温范围-55-+125oC。 ●可编程实现 9-12 位的数字读数方式。 ●用户可设定的非易失性(掉电不丢失)的温度上下线报警值。 ●支持多点组网功能,多个 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、温度灵敏 元件、内部存储器和配置寄存器四部分组成。

图 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.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 位转换位数为例:对于正的温度,只要将测到的数值的整数 部分取出,转换为 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,后者存放温度的上下限报警值和配置寄存器。 高速暂存 RAM 以及 EEPROM 的构成如图 7.1.5 所示。 高速暂存 RAM 由 9 个字节组成, 当温度转换命令发出后,经转换获得的温度值以二进制补码形式存放在第 0(LSB)和第一 (MSB)个字节内。单片机通过单线接口 DQ 读出该数据,读取时低位在前,高位在后 读取时低位在前, 读取时低位在前 高位在后。

第二和第三个字节是温度的上(TH)下限(TL)报警值,他们没有小数位,第四个字节是 配置寄存器,主要用以设置工作模式和转换位数。第五、第六和第七字节是保留位,没有实 际意义,第八个字节是前面所有 8 个字节的 CRC 校验码。EEPROM 由 3 个字节构成,用来 存放温度的上下限报警值以及配置寄存器的内容。

图 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 的通信协议,主机控制 DS18B20 完成一次温度转换必须经过 3 个步 骤:

一) 、每次读写之前都要对 DS18B20 进行复位操作 二)、复位成功后发送一条 ROM 指令 三) 、最后发送 RAM 指令,这样才能够对 DS18B20 进行正确的操作。 ● 复位:复位要求主机将数据线拉低最少 480us,然后释放,当 DS18B20 受到信号 后,等待 15-60us,然后把总线拉低 60-240us,主机接收到此信号表示复位成功。 ● ROM 指令: ROM 指令表明了主机寻址一个或多个 DS18B20 中的某个或某几个, 或者 是读取某个 DS18B20 的 64 位序列号。 ● RAM 指令:RAM 指令用于主机对 DS18B20 内部 RAM 的操作(如启动温度转换、读取 温度等) 。 1、ROM 操作命令 DS18B20 采用一线通信接口。 操作命令: 因为一线通信接口, 必须在先完成 ROM 、 设定,否则记忆和控制功能将无法使用。一旦总线检测到从属器件的存在,它便可以发出器 件 ROM 操作指令,所有 ROM 操作指令均为 8 位长度,主要提供以下功能命令: 1 )读 ROM(指令码 0X33H) :当总线上只有一个节点(器件)时,读此节点的 64 位序列号。 如果总线上存在多于一个的节点,则此指令不能使用。 2 )ROM 匹配(指令码 0X55H) :此命令后跟 64 位的 ROM 序列号,总线上只有与此序列号相 同的 DS18B20 才会做出反应;该指令用于选中某个 DS18B20,然后对该 DS18B20 进行读写操 作。 3 )搜索 ROM(指令码 0XF0H) 用于确定接在总线上 DS18B20 的个数和识别所有的 64 位 : ROM 序列号。当系统开始工作,总线主机可能不知道总线上的器件个数或者不知道其 64 位 ROM 序列号,搜索命令用于识别所有连接于总线上的 64 位 ROM 序列号。 4 )跳过 ROM(指令码 0XCCH) 此指令只适合于总线上只有一个节点;该命令通过允许总 : 线主机不提供 64 位 ROM 序列号而直接访问 RAM,以节省操作时间。 5 )报警检查(指令码 0XECH) :此指令与搜索 ROM 指令基本相同,差别在于只有温度超过 设定的上限或者下限值的 DS18B20 才会作出响应。 只要 DS18B20 一上电, 告警条件就保持在 设置状态, 直到另一次温度测量显示出非告警值, 或者改变 TH 或 TL 的设置使得测量值再一 次位于允许的范围之内。储存在 EEPROM 内的触发器用于告警。 这些指令操作作用在每一个器件的 64 位光刻 ROM 序列号,可以在挂在一线上多个器 件选定某一个器件,同时,总线也可以知道总线上挂有有多少,什么样的设备。 2、RAM 指令 DS18B20 有六条 RAM 命令: 1)温度转换(指令码 0X44H):启动 DS18B20 进行温度转换,结果存入内部 RAM。 2)读暂存器(指令码 0XBEH) :读暂存器 9 个字节内容,此指令从 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 字节,用以上电后恢复以前保存的报警值及配置字节。 6)读电源供电方式(指令码 0XB4H) :启动 DS18B20 发送电源供电方式的信号给主 CPU。 对于在此命令送至 DS18B20 后所发出的第一次读出数据的时间片, 器件都会给出其电源方式 的信号。 “0”表示寄生电源供电。 “1”表示外部电源供电。

7.1.5 DS18B20 的操作时序 本人查看数据手册和网上的例程, (本人查看数据手册和网上的例程 然后结合实际测试结果 本人查看数据手册和网上的例程, 然后结合实际测试结果) 1、DS18B20 的初始化 (1) 先将数据线置高电平“1”。 (2) 延时(该时间要求的不是很严格,但是尽可能的短一点) 。 (3) 数据线拉到低电平“0”。 (4) 延时 490 微秒(该时间的时间范围可以从 480 到 960 微秒) 。 (5) 数据线拉到高电平“1”。 (6) 延时等待(如果初始化成功则在 15 到 60 毫秒时间之内产生一个由 DS18B20 所返 回的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然 会使程序进入死循环,所以要进行超时控制) 。 (7) 若 CPU 读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的 高电平算起(第(5)步的时间算起)最少要 480 微秒。 (8) 将数据线再次拉高到高电平“1”后结束。 DS18B20 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)微秒。 (5)将数据线拉高“1”,同时端口应为输入状态。 (6)延时 4(小于 15)微秒。 (7)读数据线的状态得到 1 个状态位,并进行数据处理。 (8)延时 62(大于 60)微秒。 7.1.3、电路和连接 、 串口电路前面已经介绍,本例中不再重复。本例中 DS18B20 与单片机的连接如图 7.1.8 所示, 的数据线要求空闲状态为高电平, 由于 DS18B20 的数据线要求空闲状态为高电平, 所以我在 DS18B20 的数据线与电源 的上拉电阻,如果不想接上拉电阻的话, 线 VCC 之间加了一个 4.7K 的上拉电阻,如果不想接上拉电阻的话,可以使能 PA2 口的内 部上拉功能。从图中可以看出 中可以看出, 外接电源的方式。 部上拉功能。从图中可以看出,本例使用的是给 DS18B20 外接电源的方式。 DS18B20 的数据线 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); //字节发送函数 void 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,读取 DS18B20 发送过来的 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 的晶振,所以需要将 makefile 文件中 、 的时钟频率修改为 12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部 12M 晶 振 注意是晶振, (注意是晶振 不是外部振荡器 一定不要选择错了, 注意是晶振, 不是外部振荡器, 否则会导致单片机不能再烧写程序) 。 4、程序说明 、程序说明。在本实例中我们只是要首先了解 DS18B20 的原理和特点,至于例程在只要简 单实现利用单片机实现对单个 DS18B20 的温度测量即可。所以在程序中我们对温度测量的 在程序中我们对温度测量的 在程序中 处理是: 处理是: 1)复位(假定复位成功,不检测复位是否成功) )复位(假定复位成功,不检测复位是否成功) , 2)发送跳过 ROM 指令(我们系统只连接了一个 DS18B20,所以可以使用这条指令) 指令( ) ,所以可以使用这条指令) , 3)发送温度转换命令(我们采用 DS18B20 默认的 12 位温度转换,所以不用对 DS18B20 温度转换, )发送温度转换命令( 进行任何配置, 开始采集温度) 进行任何配置,直接指示 DS18B20 开始采集温度) , 4)延时 1S,等待 DS18B20 完成温度采集(默认 12 位温度转换时,采集一次温度的时间为 完成温度采集( 位温度转换时, ) , 750ms,所以至少要延时 750ms 以上) 以上) , , 51)复位(每次对 DS18B20 进行操作都要进行复位、ROM 操作、RAM 操作这三个步骤) 进行操作都要进行复位、 操作、 操作这三个步骤) )复位( , 6)发送跳过 ROM 指令 ) 7)发送读内部 RAM 命令(这个指令读取 DS18B20 中 RAM 的全部 9 个字节,而我们只需 命令( 个字节, )发送读内部 要得到温度值就可以了, 的前两个字节里面, 所以我们读取完前两个字 要得到温度值就可以了, 温度值存储在 RAM 的前两个字节里面, 所以我们读取完前两个字 节的内容后可以不必理会后面的内容) 节的内容后可以不必理会后面的内容) ,

8)将采集到的温度值进行处理(判断温度的正负,分离温度的整数位和小数位 ,然后将处 )将采集到的温度值进行处理 判断温度的正负 分离温度的整数位和小数位),然后将处 判断温度的正负, 理后的数据发送到串口。 理后的数据发送到串口。 9)延时 4S,然后跳到步骤 1) 重复步骤 1)-8),完成下一次温度测量 ,重复步骤 ) ,然后跳到步骤 ) , 完成下一次温度测量 5、程序代码 、 #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h>

//中断函数头文件

//××××××××××××引脚宏定义××××××××××××× //18B20 定义 #define SET_DQ (PORTA) |= (1 << (PA2)) // 18b20 高电平 #define CLR_DQ (PORTA) &=~(1 << (PA2)) // 18b20 低电平 #define DQ_IN (PINA) & (1<<(PA2)) // 18b20 信号输入 #define SET_OUT (DDRA)|= (1<<(PA2)) #define SET_IN (DDRA)&=~(1<<(PA2)) //常量声明 #define BAUD 9600 //全局变量声明 unsigned char Temp_H,Temp_L,OK_Flag; //PA2 定义成输出 //PA2 定义成输入

//温度高位,低位,复位成功标志

//函数声明 void Delayus(unsigned int lus); //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); //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; //分别存储温度小数值,小数值的千,百,十,个位

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 复位是否成功 { PORTB = 0x01; } else { PORTB = 0x02; } */ cli(); //关中断 DS18B20_Init(); //初始化 DS18B20

Write_18b20(0Xcc); //发送 ROM 指令,跳过 ROM 匹配 Write_18b20(0X44); //发送温度转换命令 for(i=0;i<50;i++) { Delayms(20); } DS18B20_Init(); //延时 1S,等转换完成

//初始化 DS18B20

Write_18b20(0Xcc); //发送 ROM 指令,跳过 ROM 匹配 Write_18b20(0Xbe); //发送读取暂存器指令 Temp_L = Read_18b20(); //获得温度的低位 Temp_H = Read_18b20(); //获得温度的高位 if(Temp_H & 0x08) //判断温度的正负 { Temp_H = ~Temp_H; //负温度。取反加 1 Temp_L = ~Temp_L; // SREG |= ~(1 << SREG_C); //清零进位位标志 Temp_L++; //温度低字节加 1 if(SREG & (1 << SREG_C)) //有进位吗? { Temp_H++; //有进位,则温度高字节加 1 } } tempint = ((Temp_H << 4) & 0x70) | (Temp_L >> 4); tempint1 = tempint / 1000; tempint2 = tempint % 1000 / 100; tempint3 = tempint % 100 / 10; tempint4 = tempint % 10; //千位 //百位 //十位 //个位 //获得温度的整数位

temppoint = Temp_L & 0x0f; //取出温度的小数位 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(' '); //千位 //百位 //十位 //个位 //发送温度值到上位机

//高位为零,则不显示

if(!(tempint2)) { Usart_PutChar(' '); } else { Usart_PutChar(tempint2 + 0x30); } if(!(tempint3)) { Usart_PutChar(' '); } else { Usart_PutChar(tempint3 + 0x30); } //Usart_PutChar(tempint4 + 0x30); } else { Usart_PutChar(tempint1 + 0x30); Usart_PutChar(tempint2 + 0x30); Usart_PutChar(tempint3 + 0x30); } Usart_PutChar(tempint4 + 0x30); Usart_PutChar('.'); Usart_PutChar(temppoint1 + 0x30); Usart_PutChar(temppoint2 + 0x30); Usart_PutChar(temppoint3 + 0x30); Usart_PutChar(temppoint4 + 0x30);

//显示小数点 //显示小数位

Usart_PutChar(' '); //不显示,空一格 Usart_PutChar('o'); //显示温度的符号。由于实在找不到温度那个再上面的小 o, Usart_PutChar('C'); //只好用普通的小写 o 来代替了。 Usart_PutChar(0x0D); Usart_PutChar(0x0A); //结尾发送回车换行 sei(); //开中断 //延时 4S,再进行温度转换

for(i=0;i<200;i++) { Delayms(20);

} } } //端口状态初始化设置函数 void Port_Init() { PORTD = 0X00; //USART 的发送接收端口分别为 PD0 和 PD1 DDRD |= (1 << PD1); //PD0 为接收端口,置为输入口;PD1 为发送端口,置为输出口 PORTB = 0x00; DDRB = 0xff; } void Port_DS18b20() { DDRA &= ~(1 << PA2); // 输入模式(上电时为高电平) PORTA &= ~(1 << PA2); // 输出锁存器写 0,以后不再更改 } //USART 寄存器配置函数 void Usart_Init() { UCSRA = 0X00; UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //异步,数据格式 8,N,1 //写 UCSRC 时, URSEL 应设置为 1。 UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率设置 UBRRH = (F_CPU / BAUD / 16 - 1) / 256; UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //发送使能 } //字节发送函数 void Usart_PutChar(unsigned char cTXData) { while( !(UCSRA & (1 << UDRE)) ); //只有数据寄存器为空时才能发送数据 UDR = cTXData; //发送数据送 USART I/O 数据寄存器-UDR } //接收中断函数 ISR(USART_RXC_vect ) { unsigned char Rev; Rev = UDR;

//从 USART I/O 数据寄存器-UDR 中读出数据

Usart_PutChar(Rev); }

//将接收到的数据发送

void Usart_PutString(unsigned char *pcString) { while (*pcString) { Usart_PutChar(*pcString++); } } //DS18B20 初始化 unsigned char DS18B20_Init() { SET_OUT; //PA2 设置为输出口(相当于拉低数据线上的电平) Delayus(490); //延时大于 480us SET_IN; //输入 释放数据线(相当于拉高数据线上的电平)

Delayus(68); //延时大于 60US, //while(DQ_IN);//可以用两个 while()死循环来判断复位是否成功,当数据线被拉低,说 //while(!(DQ_IN)); //明 18b20 开始复位应答,当数据线变高,说明应答完毕 if(DQ_IN) //判断 DS18B20 是否拉低数据线 { OK_Flag = 0; // 数据线是高?复位失败 } else { OK_Flag = 1; // 数据线是低?复位成功 } Delayus(422); //有复位应答信号后,应当再延时一段时间(480-68) ,以等待应答完毕 return OK_Flag; } //从 DS18B20 读取一个字节数据 unsigned char Read_18b20() { unsigned char i; unsigned char dat = 0; // dat 用于存储读到的数据,先清零 //返回复位标志

for(i = 0;i < 8;i++) { SET_OUT; Delayus(2); SET_IN;

//共读 8 位数据,构成一个字节 //定义为输出(拉低数据线) //拉低 2 微秒 //定义成输入,读入数据(同时也相当于拉高数据线) //延时 //数据右移,读顺序:先低后高 //读数据, //如果是高,置 1,右移数据 //延时大于 60us

Delayus(4); dat = dat >> 1; if(DQ_IN) { dat |= 0x80; } Delayus(62); } return dat; }

//返回读到的 1 字节数据

//向 DS18B20 写 1 字节数据 void Write_18b20(unsigned char dat) { unsigned char i; for(i = 0;i < 8;i++) //写 8 次,一次写 1 位,先写低字节 { SET_OUT; //拉低数据线 2us,开始写数据 Delayus(2); // if(dat & 0x01) //写数据 { SET_IN; //写 1 } else { SET_OUT; //写 0 } dat >>= 1; //数据右移 1 位,先写低位 Delayus(62); //延时大于 60us SET_IN; Delayus(2); //拉高数据线 //写两位数据的时间间隔

} } //us 级别的延时函数 void Delayus(unsigned int lus) { while(lus--) { _delay_loop_2(3); //_delay_loop_2(1)是延时 4 个时钟周期, 参数为 3 则延时 12 //个时钟周期,本实验用 12M 晶体,则 12 个时钟周期为 12/12=1us } } //ms 级别的延时函数 void Delayms(unsigned int lms) { while(lms--) { Delayus(1000); } }

//延时 1ms

7.2 基于寄生电源的 DS18B20 的温度测量
7.2.1、实例功能 、 完成了利用 DS18B20 实现最简单的温度测量后, 我们再接再厉, 继续深入研究 DS18B20.。 在上一实例中我们提到,DS18B20 可以采用内部寄生电源供电,在本实例中我们就试着使 用这一方法来实现不用给 DS18B20 加外接电源,利用寄生电源实现温度采集,同时我们也 试着实现对 DS18B20 的 RAM 实现更多的操作, 实现将温度上下限报警值写到 RAM 中, 并 复制到 EEPROM 中。 本实例包括三个功能模块,分别介绍如下: ● 单片机系统:利用 ATmega16 单片机与 DS18B20 温度传感器通信,控制温度的采集 过程,并将采集到的温度值通过串口发送到计算机。 ● 外围电路:外围电路分两部分:串口电路部分(实现将采集到的温度值发送到计算 机的功能) DS18B20 温度采集电路 、 (实现采集环境温度的功能) 在 DS18B20 的电路部分, , 我们断开 VCC 与 DS18B20 的连接。 ● 软件程序:编写软件,实现温度测量和串口发送数据功能。 通过本实例的学习,掌握以下内容: ● 理解 DS18B20 的特点、结构和原理和接口设计方法。 ● 掌握 DS18B20 的控制时序和控制方法流程。 ● 掌握 DS1820 的 RAM 指令操作,以及操作 EEPROM。 7.2.2 器件和原理

上一示例中我们已经对 DS18B20 的特点、原理进行了了解,并且通过控制时序实现了 对 DS18B20 的读写, 本实例中我们略过这些介绍, 重点研究 DS18B20 的寄生电源供电方式。 1、DS18B20 寄生电源供电方式的两种电路连接 DS18B20 最基本电路连接如图 7.2.1 所示,图中 DS18B20 工作在寄生电源供电方式, 它从数据线上获得能量, 在信号线 DQ 处于高电平期间把能量储存在内部电容里,在信号线 处于低电平期间消耗电容上储存的电能来使 DS18B20 工作,直到数据线变为高电平再给电 容充电。 使用寄生电源供电有两个好处: ● 进行远距离测温时,无需本地电源; ● 电路更加简单,仅用一根 I/O 口线实现温度测量。

图 7.2.1 DS18B20 基本电路连接 上面的电路在总线上只连接 1 个 DS18B20 的情况下能满足测温要求,但是要想使 DS18B20 测温精确,或者总线上挂有多个 DS18B20,上面的电路就很难满足要求了。因为 每个 DS18B20 在温度转换期间的工作电流最大可达 1.5mA, 当多个 DS18B20 都挂在同一根 I/O 口线上进行多点测温时,只靠 4.7K 的上拉电阻无法提供足够的能量,会造成温度误差 加大或者无法进行温度转换的后果。 为了使 DS18B20 在温度转换期间能够获得足够的电源供应, 可以采用以下两种方法: 1)在每个 DS18B20 节点都单独为其供电,如图 7.2.2,但是这种方法需要每个节点 都有单独电源, 这样寄生电源的优点就无从体现。 在实际使用中只作单点测温时可以采用这 种电路,多点测温基本不采用这种方法。

图 7.2.2 节点单独供电的电路连接 2)使用强上拉电路:当进行温度转换或执行复制到 EEPROM 操作时,用低导通电 阻三极管或者 MOSFET 把数据线直接拉到 VCC 就可以获得足够的电源,

7.2.3 使用强上拉的电路连接 注意使用寄生电源供电方式的时候, 都要连接到地。 注意使用寄生电源供电方式的时候,DS18B20 的 VCC 和 GND 都要连接到地。 7.2.3、电路连接 、 限于学习板的实际情况,在本实例中我们使用节点单独供电的方法。具体实现方法是: 焊掉(上一实例中焊接的上拉电阻保留) 。用 将学习板上的 DS18B20 焊掉(上一实例中焊接的上拉电阻保留) 用 3 根导线分别连接 。 DS18B20 的 3 个引脚,把其中连接 DS18B20 的 VCC 和 GND 都连接到学习板的地线上, 个引脚, 都连接到学习板的地线上, 把连接 DS18B20 的 DQ 引脚的那根导线连接到单片机的 PA2 口。 至于电路的串口部分就不再说了。 至于电路的串口部分就不再说了。 7.3 利用 DS18B20 实现多点温度测量 1、程序功能 、 程序的功能是使用单片机的 PA2 口的实现对 DS18B20 的操作,然后将读出的温度值通 过串口发送到计算机。 2 函数说明 本程序多个功能函数,分别是: ● 端口初始化函数,设置各端口的初始工作状态。 ● 串口通信相关函数: void Usart_Init(void); //USART 寄存器设置

void Usart_PutChar(unsigned char cTXData); //字节发送函数 void 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,读取 DS18B20 发送过来的 1 字节 数据。 void Write_18b20(unsigned char dat); //写 18b20,向 DS18B20 写 1 字节函数。 void DS18B20_StartConvert(void); //启动温度转换 void DS18B20_GetConvert(void); //获得温度转换结果 void DS18B20_ReadRAM(void); // 读取 RAM 内容 void DS18B20_WriteRAM(void); //写温度上下限和配置寄存器到 RAM void DS18B20_CopyEEPROM(void); //复制 RAM 中的温度上下线和配置寄存器到 EEPROM void DS18B20_RecallRAM(void); //把 EEPROM 中的温度上下线和配置寄存器恢 复到 RAM ● 延时相关函数: void Delayus(unsigned int lus); //us 延时函数 void Delayms(unsigned int lms); //ms 延时函数 由于 WINAVR 自带函数库中的延时函数使用起来很不方便,并且晶振频率不同,延时 时间也有区别,而对 DS18B20 的操作时序要求比较严格,所以本实例中自己写了两个延时 函数。 3、使用 WINAVR 开发环境,使用的是外部 12M 的晶振,所以需要将 makefile 文件中 、 的时钟频率修改为 12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部 12M 晶 振 注意是晶振, (注意是晶振 不是外部振荡器 一定不要选择错了, 注意是晶振, 不是外部振荡器, 否则会导致单片机不能再烧写程序) 。 4、 程序说明。 同时还实现了对 DS18B20 、 程序说明 在本实例中我们不但实现了利用 DS18B20 测量温度, 的 RAM 的读写,包括读 RAM 区的全部 9 个字节、写温度上下限报警值和配置寄存器、将 数据复制到 EEPROM、从 EEPROM 中恢复数据等, 操作的程序, 在主程序的开始部分有一段对 RAM 操作的程序, 我们如果想要观察对 RAM 的读写效果的 只需将这段程序的屏蔽去掉,就可以在串口助手上利用十六进制显示的功能观察数据。 话,只需将这段程序的屏蔽去掉,就可以在串口助手上利用十六进制显示的功能观察数据。 在程序中我们对温度测量的处理是: 在程序中我们对温度测量的处理是: 1)复位(假定复位成功,不检测复位是否成功) )复位(假定复位成功,不检测复位是否成功) , 2)发送跳过 ROM 指令(我们系统只连接了一个 DS18B20,所以可以使用这条指令) 指令( ) ,所以可以使用这条指令) , 3)发送温度转换命令(我们采用 DS18B20 默认的 12 位温度转换,所以不用对 DS18B20 位温度转换, )发送温度转换命令( 进行任何配置, 开始采集温度) 进行任何配置,直接指示 DS18B20 开始采集温度) , 4)延时 1S,等待 DS18B20 完成温度采集(默认 12 位温度转换时,采集一次温度的时间为 完成温度采集( 位温度转换时, ) , 750ms,所以至少要延时 750ms 以上) 以上) , , 51)复位(每次对 DS18B20 进行操作都要进行复位、ROM 操作、RAM 操作这三个步骤) 进行操作都要进行复位、 操作、 操作这三个步骤) )复位( , 6)发送跳过 ROM 指令 )

7)发送读内部 RAM 命令(这个指令读取 DS18B20 中 RAM 的全部 9 个字节,而我们只需 ) 命令( 个字节, 要得到温度值就可以了, 的前两个字节里面, 要得到温度值就可以了, 温度值存储在 RAM 的前两个字节里面, 所以我们读取完前两个字 节的内容后可以不必理会后面的内容) 节的内容后可以不必理会后面的内容) , 8)将采集到的温度值进行处理 判断温度的正负,分离温度的整数位和小数位 ,然后将处 判断温度的正负, 的整数位和小数位), )将采集到的温度值进行处理(判断温度的正负 分离温度的整数位和小数位 理后的数据发送到串口。 理后的数据发送到串口。 9)延时 4S,然后跳到步骤 1) 重复步骤 1)-8),完成下一次温度测量 ,重复步骤 ) , ) , 完成下一次温度测量 5、程序代码 、 由于本实例的程序量比较大,这里就不再列出了,直接放在附件里面。

7.3 基于 DS18B20 的多点温度测量 多点温度测量
7.2.1、实例功能 、 完成了利用 DS18B20 实现最简单的温度测量后以及对 DS18B20 的 RAM 区进行读写 之后,我们再接再厉,继续深入研究 DS18B20.。在前面实例中我们提到,利用 DS18B20 可 以很方便的实现多点测温,那么在本实例中我们就试着实现多点测温。 本实例包括三个功能模块,分别介绍如下: ● 单片机系统:利用 ATmega16 单片机与 DS18B20 温度传感器通信,通过对指定的 DS18B20 进行读取温度的操作,并将采集到的温度值通过串口发送到计算机。 ● 外围电路:外围电路分两部分:串口电路部分(实现将采集到的温度值发送到计算 机的功能) DS18B20 温度采集电路 、 (实现采集环境温度的功能) 在 DS18B20 的电路部分, , 我们并接两个 DS18B20(如果没有条件一个 DS18B20 也可以) 。 ● 软件程序:编写软件,实现对指定 DS18B20 进行温度测量和串口发送数据功能。 通过本实例的学习,掌握以下内容: ● 理解 DS18B20 的特点、结构和原理和接口设计方法。 ● 掌握 DS18B20 的多点测温的基本原理和方法。 ● 掌握 DS1820 的 ROM 指令操作,以及操作 ROM。 7.2.2 器件和原理 前面的实例中我们已经实现了利用 DS18B20 的进行温度测量, 并且完成了对 DS18B20 的 RAM 区的读写操作,还实现了利用寄生电源对 DS18B20 的供电方式。 本实例中我们实现对并接在同一总线上的两个 DS18B20 的其中一个进行温度读取。 1、DS18B20 的 ROM 操作指令 在前面利用 DS18B20 实现简单测温的例子中我们已经了解了 DS18B20 的相关 ROM 操作指令。 其中的“搜索 ROM”指令可以让我们在不知道总线上连接了多少数目的 DS18B20 的 情况下搜索出来总线上共连接了几个 DS18B20,以及每个 DS18B20 的 ROM 序列号。 “匹配 ROM”指令可以让我们对指定的某一个 DS18B20 进行操作。 “报警搜索 ROM” 指令可以实现对超过温度报警值的一个或数个 DS18B20 进行操作。 2、 “搜索 ROM” 指令比较复杂, 在此我们就不用了, 等以后再研究, “报警搜索 ROM” 指令在实际应用中有不同的意义,我们也掠过不学。在这里我们重点“匹配 ROM”指令。

如图 7.3.1 所示是利用“匹配 ROM”指令实现对指定 DS18B20 的操作。其中的存在脉 冲是 DS18B20 对复位信号发出的应答脉冲。在我们的程序中,在 DS18B20 初始化函数里面 已经包含了复位脉冲和存在脉冲。 从图中可以看出,当需要对指定的 DS18B20 进行操作的时候,需要先对 DS18B20 进 行复位初始化操作,然后发送“匹配 ROM”指令,后面紧跟着就要发送指定 DS18B20 的 ROM 序列号,DS18B20 对收到的 ROM 序列号进行比较,如果与自己的相同,则执行下面 的指令,如果不同,则不再执行后面指令。

图 7.3.1 对指定 DS18B20 进行操作的控制流程 7.2.3、电路连接 、 限于学习板的实际情况,在本实例中我们使用外接电源供电的方法。具体实现方法是: 焊掉(上一实例中焊接的上拉电阻保留) 。用 根导线分别连接两 将学习板上的 DS18B20 焊掉(上一实例中焊接的上拉电阻保留) 用 3 根导线分别连接两 。 个也可以) 个引脚, 连接到学习 个(1 个也可以)DS18B20 的 3 个引脚,把其中连接 DS18B20 的 VCC 和 GND 连接到学习 板的电源和地线上, 电源和地线上 板的电源和地线上,把连接 DS18B20 的 DQ 引脚的那根导线连接到单片机的 PA2 口。 至于电路的串口部分就不再说了。 至于电路的串口部分就不再说了。 1、程序功能 、 程序的功能是使用单片机的 PA2 口的实现对两个 DS18B20 的操作,然后将读出的指定 的 DS18B20 的温度值通过串口发送到计算机。 2 函数说明 本程序多个功能函数,分别是: ● 端口初始化函数,设置各端口的初始工作状态。 ● 串口通信相关函数: void Usart_Init(void); //USART 寄存器设置 void Usart_PutChar(unsigned char cTXData); //字节发送函数 void 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,读取 DS18B20 发送过来的 1 字节 数据。 void Write_18b20(unsigned char dat); //写 18b20,向 DS18B20 写 1 字节函数。 void DS18B20_StartConvert(void); //启动温度转换 void DS18B20_GetConvert(void); //获得温度转换结果 void DS18B20_ReadRAM(void); // 读取 RAM 内容 void DS18B20_WriteRAM(void); //写温度上下限和配置寄存器到 RAM void DS18B20_CopyEEPROM(void); //复制 RAM 中的温度上下线和配置寄存器到 EEPROM void DS18B20_RecallRAM(void); //把 EEPROM 中的温度上下线和配置寄存器恢 复到 RAM void DS18B20_ReadROM(void); //读 ROM,当总线上只有一个节点时,可以执行此 操作 void DS18B20_SearchROM(void); //搜索 ROM,确定总线上的节点数目和 ROM 内容 void DS18B20_SkipROM(void); // 跳过 ROM, 当总线上只有一个节点时, 可以 执行此操作 void DS18B20_MatchROM(void); //匹配 ROM, 此命令后紧跟 64 位 ROM 序列号, 匹 配的节点可以读写 void DS18B20_AlarmROM(void); //报警搜索 ROM,只有温度超过设定值的才能响 应 //带 ROM 匹配的函数 void DS18B20_StartConvert1(void); //启动温度转换 void DS18B20_GetConvert1(void); //获得温度转换结果 其中有些函数虽然列出来了, 注:其中有些函数虽然列出来了,但是并没有具体的程序内容,这主要是为了以后扩展 其中有些函数虽然列出来了 但是并没有具体的程序内容,这主要是为了以后扩展 需要。 需要。 ● 延时相关函数: void Delayus(unsigned int lus); //us 延时函数 void Delayms(unsigned int lms); //ms 延时函数 由于 WINAVR 自带函数库中的延时函数使用起来很不方便,并且晶振频率不同,延时 时间也有区别,而对 DS18B20 的操作时序要求比较严格,所以本实例中自己写了两个延时 函数。 3、使用 WINAVR 开发环境,使用的是外部 12M 的晶振,所以需要将 makefile 文件中 、 的时钟频率修改为 12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部 12M 晶 振 注意是晶振, (注意是晶振 不是外部振荡器 一定不要选择错了, 注意是晶振, 不是外部振荡器, 否则会导致单片机不能再烧写程序) 。 4、 程序说明。 同时还实现了对 DS18B20 、 程序说明 在本实例中我们不但实现了利用 DS18B20 测量温度, 的 RAM 的读写,包括读 RAM 区的全部 9 个字节、写温度上下限报警值和配置寄存器、将 数据复制到 EEPROM、从 EEPROM 中恢复数据等,

操作的程序, 在主程序的开始部分有一段对 ROM 和 RAM 操作的程序,我们如果想要观察对 ROM 和 RAM 的读写效果的话,只需将这段程序的屏蔽去掉,就可以在串口助手上利用十六进制显 的读写效果的话,只需将这段程序的屏蔽去掉, 示的功能观察数据。 示的功能观察数据。 在程序中我们对指定 操作的步骤是是 在程序中我们对指定 DS18B20 操作的步骤是是: 1)复位(假定复位成功,不检测复位是否成功) )复位(假定复位成功,不检测复位是否成功) , 2)发送跳过 ROM 指令(我们系统使用外接电源供电,所以可以让总线上的所有 DS18B20 指令(我们系统使用外接电源供电 所以可以让总线上的所有 使用外接电源供电, ) 同时进行温度转换,当然这里最好也用“ 同时进行温度转换,当然这里最好也用“匹配 ROM”指令) ”指令) , 3)发送温度转换命令(我们采用 DS18B20 默认的 12 位温度转换,所以不用对 DS18B20 位温度转换, )发送温度转换命令( 进行任何配置, 开始采集温度) 进行任何配置,直接指示 DS18B20 开始采集温度) , 4)延时 1S,等待 DS18B20 完成温度采集(默认 12 位温度转换时,采集一次温度的时间为 完成温度采集( 位温度转换时, ) , 750ms,所以至少要延时 750ms 以上) 以上) , , 51)复位(每次对 DS18B20 进行操作都要进行复位、ROM 操作、RAM 操作这三个步骤) 进行操作都要进行复位、 操作、 操作这三个步骤) )复位( , 6)发送“匹配 ROM”指令 )发送“ ” 7)发送指定 ROM 的 64 位序列号。 位序列号 列号。 ) 7)发送读内部 RAM 命令(这个指令读取指定 DS18B20 中 RAM 的全部 9 个字节,而我们 命令(这个指令读取指定 个字节, ) 只需要得到温度值就可以了, 的前两个字节里面, 只需要得到温度值就可以了, 温度值存储在 RAM 的前两个字节里面, 所以我们读取完前两 个字节的内容后可以不必理会后面的内容) 个字节的内容后可以不必理会后面的内容) , 8)将采集到的温度值进行处理 判断温度的正负,分离温度的整数位和小数位 ,然后将处 判断温度的正负, )将采集到的温度值进行处理(判断温度的正负 分离温度的整数位和小数位), 理后的数据发送到串口。 理后的数据发送到串口。 9)延时 4S,然后跳到步骤 1) 重复步骤 1)-8),完成下一次温度测量 ,重复步骤 ) , ) , 完成下一次温度测量 5、程序代码 、 由于本实例的程序量比较大,这里就不再列出了,直接放在附件里面。


相关文章:
马伟力AVR笔记:七、基于DS18B20的温度测量实验
AVR 学习笔记七基于 DS18B20 的温度测量实验 学习笔记七 ---基于 LT_Mini_M16 基于 7.1 基于 DS18B20 的基本测温实验 7.1.1、实例功能 、 传统的温度测...
DS18B20实时温度检测实验 DS18B20
DS18B20温度测量与控制实验... 13页 1财富值 马伟力AVR笔记:七基于D... ...课题DS18B20 实时温度检测实验 1、 熟悉 LCD1602 的编程方法 2、 熟悉 PIC 单...
马伟力AVR笔记:八、基于DS1302的实时时钟实验
马伟力AVR笔记:八、基于DS1302的实时时钟实验_IT/计算机_专业资料。AVR今日推荐 89份文档 爆笑大撞脸 超爆笑笑话 有趣及爆笑图片汇集 绝对经典搞笑照片68份文档 新...
DS18B20应用笔记
温度传感器DS18B20使用笔... 3页 免费 马伟力AVR笔记:七基于... 22页 1...在没有示波器、不能在线调试等各种“恶劣”条件下,我们只能靠将最终测量结果通过...
马伟力AVR笔记:六、模拟比较器和ADC实验
马伟力AVR笔记:六、模拟比较器和ADC实验_IT/计算机_专业资料。AVRAVR 学习笔记六、模拟比较器和 ADC 实验 ---基于 LT_Mini_M16 6.1 模拟比较器实验 6.1.1...
马伟力AVR笔记:三、定时记数器0实验
马伟力AVR笔记:三、定时记数器0实验_信息与通信_...基于 LT_Mini_M16 基于 3.1 定时 计数器 0 的...(2)定时计数器中断屏蔽寄存器—TIMSK 位 7 6 5 ...
马伟力AVR笔记:五、异步串行通信(USART)实验
马伟力AVR笔记:五、异步串行通信(USART)实验_信息与...( ) ---基于 LT_Mini_M16 基于 5.1 USART ...在 5,6,7 位字长模式下,未使用的高位被发送器...
DS1302实时时钟实验
马伟力AVR笔记:八、基于D... 11页 2财富值 实时...51+DS1302+DS18B20+LCD160... 28页 免费 DS1302...1.7 ;DS1302 的 JP83 用一条 4PIN 线连接 P1...
AVR学习笔记十四、模块化程序设计2
DS18B20 温度检测、 DS1302 实时时钟等经常用到的...AVR学习笔记十、基于数码... AVR学习笔记十一、AVR...马伟力AVR笔记:十四、模... 8页 2下载券 第14章...
第10章 模拟比较器和ADC接口
马伟力AVR笔记:六、模拟... 17页 1下载券喜欢...硬件电路 利用 AVR-51 多功能实验板,可以实现和完成...而 PA7(ADC7)口作为模拟电压测量的输入口(ADC ...
更多相关标签: