小鹏STEM
首页
主题
课程
课件
创作
赛事
资源
文章
登录
注册
DS18B20数字温度传感器
在嵌入式系统的应用中,经常需要对温度进行测量。测温的方法有很多,例如可以使用热敏元件配合高精度A/D转换的方式来实现。数字温度传感器的出现改变了传统的测温方式,它可以自动将温度值转化为数字量并储存在传感器内部的存储器中,控制器通过读取存储的温度值即可得到高精度的测温结果。本章介绍的DS18B20就是数字温度传感器中颇具代表性的一种。
19.1
DS18B20的功能介绍
DS18B20是美国Dallas半导体公司(现在改名为MAXIM)生产的“一线总线”接口的数字化温度传感器,全部传感元件及转换电路集成在形如一只三极管的集成电路内,具有体积小巧、测温精度高、适用电压范围宽、可组网等诸多优点,得到了广泛的应用。
19.1.1
DS18B20的特点
DS18B20数字温度传感器具有以下特点:
1)单一总线接口。在与微处理器连接时仅需要一条数据线即可实现与DS18B20的双向通信。
2)适应电压范围更宽。供电电压在3.0~5.5V之间芯片均可正常工作,在寄生电源供电方式下还可由数据线供电。
3)测温精度高。温度测量范围为-55~125℃,在-10~85℃时测量精度可达±0.5℃。
4)转换速度快。12位分辨率下温度转换时间仅需要750ms。
5)外围电路简单。DS18B20在使用中不需要外接任何元件即可正常工作。
6)支持多点组网功能。多个DS18B20可以并联在唯一的数据总线上,实现多点组网测温。
DS18B20数字温度传感器的外观如图19-1所示。
19.1.2
DS18B20的引脚定义
DS18B20有两种封装形式,一种是TO-92封装,一种是8脚SOIC封装,具体封装形式如图19-2所示。
TO-92封装的DS18B20引脚定义如下:
·GND:电源地。
·DQ:数字信号输入/输出端。
·VDD:外接供电电源输入端(在寄生电源供电方式时接地)。
19.1.3
DS18B20的内部结构
DS18B20内部结构主要由64位光刻ROM、存储器、配置寄存器、温度传感器以及高低温触发器等部分构成。具体结构如图19-3所示。
1.64位光刻ROM DS18B20的ROM中保存有64位的编码,该编码是在器件出厂前被光刻好的。编码的前8位是产品类型标识号,之后的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码。光刻ROM的作用是让每一个DS18B20有唯一的编号,当总线上挂接多个DS18B20时,64位的光刻代码可以用作对器件的寻址。
2.存储器
DS18B20的存储器包括一个8字节的高速暂存器SRAM和一个3字节的非易失性可电擦除的E 高速暂存器的存储空间为8字节,其中第0、1字节用于存放测得的温度信息,当温度转换命令执行后,经转换所得的温度值存放在这两个字节中。第2、3、4字节存放的是右面E E 3.配置寄存器
配置寄存器位于E TM位是测试模式位,用于设置DS18B20是处于工作模式还是测试模式。DS18B20出厂时已将该位设置为0,即工作模式,此位无需用户更改。
R1和R0位用来设置分辨率,具体如表19-1所示。DS18B20在出厂时的默认设置为12位的分辨率。配置寄存器的低五位固定为1。
19.1.4
温度值的存储方式
DS18B20在出厂时默认设置为12位的温度分辨率,其存储使用了16位符号扩展的二进制补码方式,分辨率为0.0625℃/LSB。具体如图19-5所示。
温度值经过转化后得到12位数据,分别存储在TH/USER BYTE1和TL/USER BYTE2的两个字节的SRAM中。BYTE 1中的高5位(S位)是符号位,低三位以及BYTE 0中的8位是温度值的二进制存储位。
当温度值大于或等于0时,BYTE1中的前5个符号位为0,这时我们读取这两个温度寄存器上的温度值,将其合并后转化为十进制数,再乘以0.0625即可得到实际温度值;当温度值小于0时,BYTE1中的前5个符号位为1,这时需要将读取的温度值按位取反并加1后,转化为十进制数,再乘以0.0625即可得到实际温度值,不过要注意这时的温度值已经是负数了。为了进一步说明温度值在DS18B20暂存器上的存储方式,我们将一些有代表性的温度值及对应的转化结果列出,详见表19-2。
19.2
DS18B20的读写方式
DS18B20需要严格的读写时序以确保数据的正确性,这些时序主要有初始化时序、写时序和读时序3种。
19.2.1
DS18B20的初始化时序
初始化时序是MCU与DS18B20通信的开始。控制器首先将总线接低480~960μs,产生复位脉冲,DS18B20接收到复位脉冲后会等待15~60μs,之后将总线拉低并保持60~240μs,产生存在脉冲,这表明DS18B20已经初始化完成,准备开始接收或发送数据。DS18B20初始化过程如图19-6所示。
19.2.2
DS18B20的写时序
DS18B20的写入是由控制器产生写时序完成的,写时序分为写“0”时序和写“1”时序,具体如图19-7所示。
1)控制器写“0”时序。控制器首先将总线拉低并保持超过1μs后,如果写“0”,控制器就继续拉低总线,再保持至少60μs,但不会多于120μs的时间。DS18B20会在总线被拉低后的15~60μs的时间段内对总线进行采样,它会检测到总线的低电平,从而完成向DS18B20写“0”的操作。
2)控制器写“1”时序。控制器首先将总线拉低并保持超过1μs后,如果写“1”,控制器就释放总线,并保持至少60μs,但不会多于120μs的时间。DS18B20会在总线被拉低后的第15~60μs的时间段内对总线进行采样,它会检测到总线的高电平,从而完成向DS18B20写“1”的操作。
需要注意的是,DS18B20的两个写周期之间至少要保持1μs的时间间隔。
19.2.3
DS18B20的读时序
从DS18B20中读取数据也是由控制器产生读时序完成的,具体如图19-8所示。当控制器读数据时,首先将总线拉低并保持超过1μs后释放总线,DS18B20检测到这一操作后,迅速将要输出的数据放到总线上。控制器会在拉低总线后的1~15μs时间段内对总线进行采样,如果检测到低电平,就是从DS18B20中读出了“0”,如果检测到高电平,就是从DS18B20中读出了“1”。
19.3
DS18B20的通信协议
控制器对DS18B20的访问是通过通信协议实现的,要使DS18B20完成温度转换,必须经过三个步骤:即在每一次读写之前都要对DS18B20进行复位操作,复位成功后控制器发送一条ROM指令,最后发送RAM指令,这样才能实现对DS18B20的预定操作。DS18B20的指令包括ROM指令和RAM指令两种。
19.3.1
ROM指令
ROM指令用于对DS18B20温度传感器中ROM存储器的相关操作,具体指令如下:
1)Read ROM[33H]:读ROM命令。该命令用于读取DS18B20温度传感器ROM中的编码,即64位的光刻代码。只有在总线上存在单只DS18B20时才能使用此命令。
2)Match ROM[55H]:匹配ROM命令。发出此命令之后,接着发出64位ROM编码,访问单总线上与该编码相对应的DS18B20并使之作出响应,为下一步对该DS18B20的读写做准备。
3)Search ROM[F0H]:搜索ROM命令。该命令用于确定挂接在同一总线上DS18B20的个数,并且识别64位ROM的地址,为操作多个器件做准备。
4)Skip ROM[CCH]:跳过ROM命令。这条命令用于忽略64位ROM地址,直接向DS18B20发送温度转换命令,以节省时间简化过程,适用于总线上只挂接单只DS18B20的情况。
5)Alarm Search[ECH]:告警搜索命令。该命令执行后只有温度超过设定值上限或下限的传感器才能做出响应。
19.3.2
RAM指令
RAM指令用于实现对DS18B20温度传感器的控制以及对高速暂存器SRAM的相关操作,具体指令如下:
1)Convert T[44H]:开始温度转换命令。用于启动DS18B20的温度转换,当温度转换为12位时,转换时间最长为750ms,9位时为93.75ms,温度转换完成后会存放在暂存器SRAM中。
2)Read Scratchpad[BEH]:读暂存器命令。用于读取DS18B20内部SRAM中9字节的数据。其中开始两个字节是温度值。如果不想全部读取9字节,控制器可以在任何时间内发出复位命令来终止读取。
3)Write Scratchpad[4EH]:写暂存器命令。用于发出向内部SRAM的BYTE2、BYTE3字节写上、下限温度数据命令。
4)Copy Scratchpad[48H]:复制暂存器命令。该命令用于将SRAM中BYTE2、BYTE3字节的内容复制到E2PROM中。
5)Recall E2[B8H]:重调E2PROM命令。作用是将E2PROM中的内容恢复到SRAM中的BYTE2、BYTE3字节。这种复制操作在每次上电后都会自动执行,使器件在上电后暂存器中就存有有效数据。
6)Read Power Supply[B4H]:读供电方式命令。作用是判断DS18B20的供电模式。寄生供电时DS18B20会发送“0”,外接电源供电时DS18B20会发送“1”。
19.4
DS18B20的应用
19.4.1
DS18B20的供电方式
1.外部电源供电方式
外部电源供电方式是DS18B20最基础的工作方式,DS18B20电源由VDD引脚接入,DQ端连接单片机I/O口,并用4.7kΩ电阻上拉到Vcc。在外部电源供电方式下,DS18B20供电充足,工作稳定可靠,抗干扰能力强,转换精度高。外部电源供电电路如图19-9所示。
2.外部电源供电方式(多点测温)
在采用外部电源供电时,总线上允许挂接多个DS18B20传感器,组成多点测温系统,如图19-10所示。值得注意的是,为了保障转换精度,当总线上挂接多个DS18B20时,上拉电阻的阻值需要适当减小。
3.寄生电源供电方式
在寄生电源供电方式下,DS18B20从数据总线上汲取能量,在DQ端处于高电平期间,DS18B20把能量储存在片内的电容里,在信号线的低电平期间依靠电容上储存的电能工作。寄生电源供电方式的电路如图19-11所示。
4.寄生电源强上拉供电方式
在寄生电源供电方式下,由于4.7kΩ的上拉电阻只能为总线上提供最多1mA的供电电流,这会导致DS18B20因供电不足而不能正确完成温度转换。改进的寄生电源供电方式如图19-12所示,在这种强上拉的供电方式下可以解决供电不足的问题,但需要多占用一个I/O口进行强上拉控制。
19.4.2
DS18B20的编程向导
当总线上只挂接一只DS18B20时,可以参考以下步骤启动温度转换。
1)开始DS18B20初始化,主器件发送复位信号,并检测DS18B20发出的存在脉冲。
2)向DS18B20发送Skip ROM命令(CCH),跳过检测ROM地址。
3)向DS18B20发送Convert T命令(44H),开始温度转换。
4)再次将DS18B20初始化,主器件发送复位信号,并检测DS18B20发出的存在脉冲。
5)向DS18B20发送Skip ROM命令(CCH),跳过检测ROM地址。
6)向DS18B20发送Read Scratchpad命令(BEH),读整个暂存器及CRC数据。其中最先读出的两个字节就是转换后的温度值。
19.4.3
DS18B20的使用要点
在使用DS18B20进行测温时应当注意以下几点:
1)DS18B20使用单一总线,极大地简化了外围电路,但由于单一总线对时序要求较高,在对DS18B20进行编程时,必须严格地保证读写时序,否则将无法正确启动温度转换。
2)当单总线上挂接多个DS18B20时,需要适当减小上拉电阻阻值,以增强总线的驱动能力。
3)在实际应用中,连接DS18B20的电缆超过一定长度后,会因分布电容的影响使信号波形产生畸变,造成转换失败,采用屏蔽双绞线可以使最大电缆长度得以延长。
4)如果总线上只有单个DS18B20,可以不用读取芯片的ROM编码以及发送匹配ROM的指令,仅使用跳过ROM指令即可。但如果总线上挂接有多个DS18B20,就需要先执行读ROM指令,读出每一个温度传感器的序列号,再发送匹配ROM指令,才能进行温度转换。
19.4.4
DS18B20编程实例
接下来我们要写程序来驱动DS18B20,将温度值显示在四位的数码管上。按照图19-8所示电路将DS18B20与AVR系统板相连接,使用PD7端口作为总线驱动端,经上拉电阻与DS18B20的DQ端相连。
在给DS18B20开发程序时,要特别注意保证其对时序的要求,必要时可以使用软件调试功能作为辅助开发。在Atmel Studio 6.1集成开发环境里,新建名为“DS18B20”的项目,保存在chapter19文件夹下,软件会自动将名为DS18B20.c的源文件添加到新建的项目中。编辑DS18B20.c源文件,编写代码详见代码清单19-1。
代码清单19-1
DS18B20数字温度计
/*
*
DS18B20.c *
PD7
连接DQ 端
*
Created: 2013/10/26
14:29:24
*
Author: GAO */
#include
//
包含AVR 头文件
#include
//
包含AVR 中断控制头文件
#define F_CPU 16000000UL //
定义系统时钟
#include
//
包含延时函数头文件
#define DQ_SET (PORTD|=0x80)
//
置位PD7
(DQ 端)
#define DQ_CLR (PORTD&=0x7F)
//
清零PD7
const unsigned char table0[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f }; //
共阴无点
const unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6, 0xed,0xfd,0x87,0xff,0xef }; //
共阴有点
const unsigned char table2[]=
{
0x40
}; //
这是一个负号,const 在这里是定义一个常量的数组
unsigned char T=0; //
定义全局变量保存温度值
void display(unsigned int NUM); //
数码管显示函数声明
void init_ds18b20(void); //DS18B20
初始化函数
unsigned char read_onechar(void); //
读一个字节函数
void write_onechar(unsigned char dat); //
写一个字节函数
unsigned char read_temperature(void); //
读取温度值函数
int main(void)
{
DDRA|=0xFF; //
设数码管段驱动端为输出
DDRB|=0xF0; //
设数码管位驱动端为输出
while(1)
{
T=read_temperature(); //
读取温度值
display(T); //
显示读取的温度值
}
}
/**********
数码管显示函数**********/
void display(unsigned int NUM)
{
unsigned char NUM3,NUM2,NUM1; if(T<100)
{
NUM1=T%10; NUM2=T%100/10; NUM3=T%1000/100; PORTA=table0[NUM1]; PORTB|=0x10; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xEF; _delay_ms(1); //
延时1ms PORTA=table0[NUM2]; PORTB|=0x20; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xDF; _delay_ms(1); //
延时1ms }
if((T>=100)&&(T<200))
{
NUM1=T%10; NUM2=T%100/10; NUM3=T%1000/100; PORTA=table0[NUM1]; PORTB|=0x10; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xEF; _delay_ms(1); //
延时1ms PORTA=table0[NUM2]; PORTB|=0x20; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xDF; _delay_ms(1); //
延时1ms PORTA=table0[NUM3]; PORTB|=0x40; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xBF; _delay_ms(1); //
延时1ms }
if(T>=200)
{
NUM1=(256-T)%10; NUM2=(256-T)%100/10; NUM3=T%1000/100; PORTA=table0[NUM1]; PORTB|=0x10; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xEF; _delay_ms(1); //
延时1ms PORTA=table0[NUM2]; PORTB|=0x20; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xDF; _delay_ms(1); //
延时1ms PORTA=table2[0]; PORTB|=0x40; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB&=0xBF; _delay_ms(1); //
延时1ms }
}
/**********
初始化18B20
函数**********/
void init_ds18B20(void)
{
DDRD|=0x80; //PD7
为输出
DQ_SET; //DQ 复位
_delay_us(100); //
延时
DQ_CLR; //
单片机将DQ 拉低
_delay_us(680); //
精确延时大于
480us DQ_SET; //
拉高总线
_delay_us(400); //
延时
}
/**********
读一个字节函数**********/
unsigned char read_onechar(void)
{
unsigned char i=0; unsigned char dat=0; for (i=8;i>0;i--)
{
DDRD|=0x80; //PD7
为输出
DQ_CLR; //
给脉冲信号
_delay_us(1); //
延时
dat=dat>>1; DQ_SET; //
给脉冲信号
_delay_us(1); //
延时
DDRD&=0x7F; //PD7
为输入
if((PIND&0x80)==0x80)
//
如果DQ 为1
,则在高位上或1
{
dat=dat|0x80; }
_delay_us(80); //
延时
}
return(dat); //
将读取的数据返回
}
/**********
写一个字节函数**********/
void write_onechar(unsigned char dat)
{
unsigned char i=0; for (i=8; i>0; i--)
{
DDRD|=0x80; //PD7
为输出
DQ_CLR; //
给脉冲信号
_delay_us(1); //
延时
if((dat&0x01)==1)
//
取dat 的最低位
{
DQ_SET; }
else {
DQ_CLR; }
_delay_us(80); //
延时
DQ_SET; dat=dat>>1; }
_delay_us(80); //
延时
}
/**********
读取温度值函数**********/
unsigned char read_temperature(void)
{
unsigned char a=0; unsigned char b=0; unsigned char t=0; init_ds18B20(); //
初始化DS18B20
write_onechar(0xCC); //
跳过读序列号的操作
write_onechar(0x44); //
启动温度转换
init_ds18B20(); //
初始化DS18B20
write_onechar(0xCC); //
跳过读序列号的操作
write_onechar(0xBE); //
连续读取温度寄存器等(共可读9
个寄存器)
a=read_onechar(); //
读取温度LSB b=read_onechar(); //
读取温度MSB t=(b<<4)|(a>>4); //
将a 的高四位和b 的低四位合并成一个完整的温度值
//
温度值小于200
是正温度,温度大于200
是负数
return(t); }
/**********
结束**********/
以上代码经成功编译后下载到AVR系统板中,程序运行后会将当前的温度值显示在数码管上,具体如图19-13所示。
DS18B20广泛用于现场测温,使用数字温度传感器,能解决开发过程中大部分涉及温度的问题,可以说一只DS18B20在手,温度问题从此无忧,这一点相信你会在今后的开发过程中有越来越深的体会。
上一节
红外线解码及发射
下一节
DHT11数字温湿度传感器
微信分享
评论
评论:
提交
AVR单片机应用实例
作者:高显生 共7讲
阅读模式
课程
步进电机的驱动
DS1302实时时钟
红外线解码及发射
DS18B20数字温度传感器
DHT11数字温湿度传感器
1602字符型液晶显示器
12864点阵型液晶显示器
推荐文章
用积木拼出时间?乐高还是太全面了!
在STEM(科学、技术、工程和数学)教育中推进AI辅助计算思维(Act-STEM)
乐高机械组42215 沃尔沃 EC500 混动挖掘机
Codeblocks 快速入门
树莓派Build HAT
乐高WEDO打印机搭建分享
《2024素质教育行业发展趋势报告》:“AI+素质教育”逐步落地
2025年少儿编程行业五大预测:少儿编程正站在一个新的起点上
乐高反重力悬浮?
Scratch 3.0连接EV3
推荐资源
深圳市义务教育人工智能课程纲要(2024年版)
乐高教育 2023 产品解决方案指南
FLL机器人挑战赛2024-2025赛季 SUBMERGED 资料
小学科学课程标准
EV3 Classroom程序创意设计第一部分
技术运用于教育:谁来做主?
乐高教育 WeDo 2.0 计算思维-教师指南
2023中小学阶段的人工智能课程调研报告
Python神经网络编程
微信分享
×
登录
×
手机号:
密码:
忘记密码?
微信扫码登录
×