基于AVR单片机DS18B20的温度测量实验
AVR学习笔记七、基于DS18B20的温度测量实验
7.1 基于DS18B20的基本测温实验
7.1.1、实例功能
传统的温度测量采用热敏电阻,但热敏电阻存在可靠性差,测温准确率低,并且必须
经过专门的接口电路将采集到的模拟量转换为数字量后才能由单片机处理。
DS18B20是美国DALLAS公司推出的一款单线数字温度传感器。它具有:体积小,功耗低,精度高,可靠性好,易于单片机接口等优点,每片DS18B20都有唯一的一个可读出的序列号,同时DS18B20还采用了寄生电源技术,可以不用外接电源。综合以上特点,DS18B20特别适合于多点测温系统。
本节首先介绍DS18B20的一些基本知识:特点、结构、原理、控制时序、与单片机的接口方法等。最后通过一个实例实现最简单的温度测量。
本实例分为三个功能模块,分别描述如下:
● 单片机系统:利用ATmega16单片机与DS18B20温度传感器通信,控制温度的采集过程,并将采集到的温度值通过串口发送到计算机。
● 外围电路:外围电路分两部分:串口电路部分(实现将采集到的温度值发送到计算
机的功能)、DS18B20温度采集电路(实现采集环境温度的功能)
通过本实例的学习,掌握以下内容:●理解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.2DS18B20 的内部结构 DS18B20 的内部结构如图7.1.2。DS18B20的内部结构主要有64位ROM、温度灵敏
元件、内部存储器和配置寄存器四部分组成。
图7.1.2 DS18B20的内部结构
作该DS18B20的地址序列码。每一个DS18B20的64位ROM都不同,这样就可以实现一
● 64 位ROM:64位ROM 的内容是64位序列号,是出厂前用激光刻好的。它可以用
根总线上挂多个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,后者存放温度的上下限报警值和配置寄存器。
当温度转换命令发出后,经转换获得的温度值以二进制补码形式存放在第0(LSB)和第一高速暂存RAM以及EEPROM 的构成如图7.1.5所示。高速暂存RAM 由9个字节组成,
(MSB)个字节内。单片机通过单线接口DQ读出该数据,读取时低位在前,高位在后。
第二和第三个字节是温度的上(TH)下限(TL)报警值,他们没有小数位,第四个字节是配置寄存器,主要用以设置工作模式和转换位数。第五、第六和第七字节是保留位,没有实际意义,第八个字节是前面所有8个字节的CRC校验码。EEPROM由3个字节构成,用来存放温度的上下限报警值以及配置寄存器的内容。
图7.1.5高速暂存RAM以及EEPROM的构成
用于设置DS18B20是工作在测试模式还是工作模式,出厂时默认设置为0,用户不用改动。R1和R0 用来设置温度转换位数。具体设置如图7.1.7所示。配置寄存器的各位意义如图7.1.6所示。第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序列号。
线主机不提供64 位ROM序列号而直接访问RAM,以节省操作时间。5)报警检查(指令码0XECH):此指令与搜索ROM指令基本相同,差别在于只有温度超过
4)跳过ROM(指令码0XCCH):此指令只适合于总线上只有一个节点;该命令通过允许总
设置状态,件选定某一个器件,同时,总线也可以知道总线上挂有有多少,什么样的设备。
2、RAM指令
DS18B20 有六条RAM命令:
1)温度转换(指令码0X44H):启动DS18B20进行温度转换,结果存入内部RAM。 2)读暂存器(指令码0XBEH):读暂存器9个字节内容,此指令从RAM的第1个字节(字节0)开始读取,直到九个字节(字节8,CRC值)被读出为止。如果不需要读出所有字节的内容,那么主机可以在任何时候发出复位信号以中止读操作。
将上下限温度报警值和配置数据写入到RAM的2、3、43)写暂存器(指令码0X4EH):
字节,此命令后跟需要些入到这三个字节的数据。
4)复制暂存器(指令码0X48H):把暂存器的2、3、4字节复制到EEPROM中,用以掉电保存。
5)重新调E2RAM(指令码0XB8H):把EEROM中的温度上下限及配置字节恢复到RAM的2、3、4字节,用以上电后恢复以前保存的报警值及配置字节。
启动DS18B20发送电源供电方式的信号给主CPU。6)读电源供电方式(指令码0XB4H):
对于在此命令送至DS18B20后所发出的第一次读出数据的时间片,的信号。“0”表示寄生电源供电。“1”表示外部电源供电。 器件都会给出其电源方式
7.1.5DS18B20 的操作时序(本人查看数据手册和网上的例程,然后结合实际测试结果) 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”后结束。
2、DS18B20的写操作
(1)数据线先置低电平“0”。
(2)延时确定的时间为2(小于15)微秒。
(3)按从低位到高位的顺序发送字节(一次只发送一位)。
(4)延时时间为62(大于60)微秒。
(5)将数据线拉到高电平,延时2(小于15)微秒。
(1)将数据线拉高“1” 3、DS18B20 的读操作 。 (6)重复上(1)到(6)的操作直到所有的字节全部发送完为止。(7) 最后将数据线拉高。
(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函数说明
本程序多个功能函数,分别是:
●端口初始化函数,设置各端口的初始工作状态。
● 串口通信相关函数:
voidUsart_Init(void); //USART寄存器设置
voidUsart_PutChar(unsigned char cTXData); //字节发送函数voidUsart_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 Delayus(unsigned int lus); void Write_18b20(unsigned char dat); //写18b20,向DS18B20 写1 字节函数。●延时相关函数: //us 延时函数
函数。 3、使用WINAVR 开发环境,使用的是外部12M 的晶振,所以需要将makefile 文件中
的时钟频率修改为12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部12M 晶
振(注意是晶振,不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)。
4、程序说明。在本实例中我们只是要首先了解DS18B20 的原理和特点,至于例程在只要简
单实现利用单片机实现对单个DS18B20 的温度测量即可。所以在程序中我们对温度测量的
处理是:
1)复位(假定复位成功,不检测复位是否成功),
2)发送跳过ROM 指令(我们系统只连接了一个DS18B20,所以可以使用这条指令),
3)发送温度转换命令(我们采用DS18B20 默认的12 位温度转换,所以不用对DS18B20 进
行任何配置,直接指示DS18B20 开始采集温度),
4)延时1S,等待DS18B20 完成温度采集(默认12 位温度转换时,采集一次温度的时间为
750ms,所以至少要延时750ms 以上),
5)复位(每次对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定义
#defineSET_DQ (PORTA) |= (1 << (PA2)) //18b20 高电平
#defineCLR_DQ (PORTA) &=~(1 << (PA2)) //18b20 低电平#defineDQ_IN (PINA) & (1<<(PA2)) //18b20信号输入
#defineSET_OUT (DDRA)|= (1<<(PA2)) //PA2定义成输出#defineSET_IN (DDRA)&=~(1<<(PA2)) //PA2定义成输入
//常量声明
#defineBAUD 9600
//全局变量声明unsigned charTemp_H,Temp_L,OK_Flag; //温度高位,低位,复位成功标志
//函数声明
void Delayms(unsigned int lms); void Port_DS18b20(void); //DS18B20端口配置
voidPort_Init(void); //端口初始化配置
voidUsart_Init(void); //USART 寄存器设置
voidUsart_PutChar(unsigned char cTXData); //字节发送函数
voidUsart_PutString(unsigned char *pcString); //字符串发送函数
unsignedchar DS18B20_Init(void); //DS18B20初始化unsignedchar Read_18b20(void); //读18b20void Write_18b20(unsigned char dat); //写18b20
intmain(void)
{
unsignedchar i;
unsignedint 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 = 0x02;
}
*/
cli(); //关中断
DS18B20_Init(); //初始化DS18B20
Write_18b20(0Xcc); //发送ROM指令,跳过ROM匹配
Write_18b20(0X44); //发送温度转换命令
for(i=0;i<50;i++) //延时1S,等转换完成
{
Delayms(20);
-
}
//初始化DS18B20
DS18B20_Init();
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
}
}
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(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(); //开中断
for(i=0;i<200;i++) { //延时4S,再进行温度转换
Delayms(20);
}
}
}
//端口状态初始化设置函数
voidPort_Init()
{
PORTD= 0X00; //USART的发送接收端口分别为PD0和PD1
DDRD|= (1 << PD1); //PD0为接收端口,置为输入口;PD1为发送端口,置为输出口
PORTB= 0x00;
DDRB= 0xff;
}
voidPort_DS18b20()
{
DDRA&= ~(1 << PA2); // 输入模式(上电时为高电平) PORTA&= ~(1 << PA2); // 输出锁存器写0,以后不再更改}
//USART 寄存器配置函数voidUsart_Init() {
UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 <<TXEN); //发送使能
}
//字节发送函数
voidUsart_PutChar(unsigned char cTXData)
{
while(!(UCSRA & (1 << UDRE)) ); //只有数据寄存器为空时才能发送数据 UDR= cTXData; //发送数据送USARTI/O数据寄存器-UDR}
//接收中断函数
ISR(USART_RXC_vect)
{ | unsigned char Rev; |
|
Rev = UDR; | //从USART I/O 数据寄存器-UDR 中读出数据 |
Usart_PutChar(Rev); //将接收到的数据发送
}
voidUsart_PutString(unsigned char *pcString)
{
while(*pcString)
{
Usart_PutChar(*pcString++);
}
}
//DS18B20初始化
unsignedchar DS18B20_Init()
{
SET_OUT; //PA2设置为输出口(相当于拉低数据线上的电平)
Delayus(490); //延时大于480us
SET_IN;//输入释放数据线(相当于拉高数据线上的电平)
Delayus(68); //延时大于60US,
{
-
OK_Flag = 0;
//
数据线是高?复位失败
}
else
{
OK_Flag= 1; // 数据线是低?复位成功
}
Delayus(422);//有复位应答信号后,应当再延时一段时间(480-68),以等待应答完毕
returnOK_Flag; //返回复位标志
}
//从DS18B20读取一个字节数据
unsignedchar Read_18b20()
{ | unsigned char i; |
|
unsigned char dat = 0; // dat 用于存储读到的数据,先清零
for(i= 0;i < 8;i++) //共读8位数据,构成一个字节
{
SET_OUT; //定义为输出(拉低数据线)
Delayus(2); //拉低2微秒
SET_IN; //定义成输入,读入数据(同时也相当于拉高数据线)
Delayus(4); //延时
dat= dat >> 1; //数据右移,读顺序:先低后高
if(DQ_IN) //读数据,
{
dat|= 0x80; //如果是高,置1,右移数据
}
Delayus(62); //延时大于60us
}
returndat; //返回读到的1字节数据
}
//向DS18B20写1字节数据
voidWrite_18b20(unsigned char dat)
{
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级别的延时函数
voidDelayus(unsigned int lus)
{
while(lus--)
{
_delay_loop_2(3); //_delay_loop_2(1)是延时4个时钟周期,参数为3则延时12 //个时钟周期,本实验用12M晶体,则12个时钟周期为12/12=1us }
}
//ms 级别的延时函数
voidDelayms(unsigned int lms)
{
while(lms--)
{
Delayus(1000); //延时1ms
}
}
7.2.1、实例功能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基本电路连接
加大或者无法进行温度转换的后果。
为了使DS18B20在温度转换期间能够获得足够的电源供应,可以采用以下两种方法: 1)在每个DS18B20节点都单独为其供电,如图7.2.2,但是这种方法需要每个节点 这样寄生电源的优点就无从体现。在实际使用中只作单点测温时可以采用这都有单独电源,
种电路,多点测温基本不采用这种方法。
图7.2.2 节点单独供电的电路连接
2)使用强上拉电路:当进行温度转换或执行复制到EEPROM操作时,用低导通电阻三极管或者MOSFET把数据线直接拉到VCC就可以获得足够的电源,
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 寄存器设置
voidUsart_PutChar(unsigned char cTXData); //字节发送函数voidUsart_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); //获得温度转换结果 // 读取RAM 内容void DS18B20_ReadRAM(void);
void DS18B20_WriteRAM(void); void DS18B20_CopyEEPROM(void); EEPROM
void DS18B20_RecallRAM(void); 复到RAM
//写温度上下限和配置寄存器到RAM
//复制RAM中的温度上下线和配置寄存器到
//把EEPROM中的温度上下线和配置寄存器恢
void Delayus(unsigned int lus); void Delayms(unsigned int lms); 由于WINAVR 自带函数库中的延时函数使用起来很不方便,并且晶振频率不同,延时
●延时相关函数:
函数。振(注意是晶振,不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)。
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的电路部分,●外围电路:外围电路分两部分:串口电路部分(实现将采集到的温度值发送到计算
● 掌握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); //获得温度转换结果 // 读取RAM 内容void DS18B20_ReadRAM(void);
void DS18B20_WriteRAM(void); void DS18B20_CopyEEPROM(void); EEPROM
void DS18B20_RecallRAM(void); 复到RAM
//写温度上下限和配置寄存器到RAM
//复制RAM中的温度上下线和配置寄存器到
//把EEPROM中的温度上下线和配置寄存器恢
void DS18B20_ReadROM(void); //读ROM,当总线上只有一个节点时,可以执行此
操作
void DS18B20_SearchROM(void); //搜索ROM,确定总线上的节点数目和ROM 内容
执行此操作
void DS18B20_SkipROM(void);
void DS18B20_MatchROM(void); //匹配ROM,此命令后紧跟64 位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、
的RAM 的读写,包括读RAM 区的全部9 个字节、写温度上下限报警值和配置寄存器、将程序说明。在本实例中我们不但实现了利用DS18B20 测量温度,同时还实现了对DS18B20
数据复制到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) 理后的数据发送到串口。
5、程序代码