数字温度传感器(DS18B20)

DS18B20是一款常用的高精度的单总线数字温度测量芯片。具有体积小,硬件开销低,抗干扰能力强,精度高的特点。

传感器参数

  • 测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°

  • 返回16位二进制温度数值

  • 主机和从机通信使用单总线,即使用单线进行数据的发送和接收

  • 在使用中不需要任何外围元件,独立芯片即可完成工作。

  • 掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。

  • 每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值

  • 宽电压供电,电压2.5V~5.5V

  • DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。

传感器引脚及原理图

DS18B20传感器的引脚及封装图如下:


DS18B20一共有三个引脚,分别是:

  • GND:电源地线
  • DQ:数字信号输入/输出端。
  • VDD:外接供电电源输入端。

单个DS18B20接线方式: VDD接到电源,DQ接单片机引脚,同时外加上拉电阻,GND接地

注意这个上拉电阻是必须的,就是DQ引脚必须要一个上拉电阻

DS18B20上拉电阻

首先我们要知道什么是漏极开路

首先看一下 场效应管(MOSFET)

场效应管 是电压控制型元器件,只要对栅极施加一定电压,DS就会导通。

漏极开路:MOS管的栅极G和输入连接,源极S接公共端,漏极D悬空(开路)什么也没有接,直接输出 ,这时只能输出低电平和高阻态,不能输出高电平

那么这个时候会出现三种情况:

  1. 图a为正常输出(内有上拉电阻):场效应管导通时,输出低电位输出低电位,截止时输出高电位。

  2. 图b为漏极开路输出,外接上拉电阻:场效应管导通时,驱动电流是从外部的VCC流经电阻通过MOSFET到GND,输出低电位,截止时输出高电位。

  3. 图c为漏极开路输出,无外接上拉电阻:场效应管导通时输出低电位,截止呈高阻态(断开)。

总结:

开漏输出只能输出低电平,不能输出高电平。漏极开路输出高电平时必须在输出端与正电源(VCC)间外接一个上拉电阻。否则只能输出高阻态。

DS18B20 是单线通信,即接收和发送都是这个通信脚进行的。 其接收数据时为高电阻输入,其发送数据时是开漏输出,本身不具有输出高电平的能力,即输出0时通过MOS下拉为低电平,而输出1时,则为高阻,需要外接上拉电阻将其拉为高电平。 因此,需要外接上拉电阻,否则无法输出1。

外接上拉电阻阻值:

DS18B20的工作电流约为1mA,VCC一般为5V,则电阻R=5V/1mA=5KΩ,

所以正常选择4.7K电阻,或者相近的电阻值。

DS18B20寄生电源

DSl8B20的另一个特点是不需要再外部供电下即可工作。当总线高电平时能量由单线上拉电阻经过DQ引脚获得。高电平同时充电一个内部电容,当总线低电平时由此电容供应能量。这种供电方法被称为“寄生电源”。另外一种选择是DSl8B20由接在VDD的外部电源供电

DS18B20内部构成

主要由以下3部分组成: 64 位ROM,高速暂存器,存储器

64 位ROM存储独有的序列号

ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。这样就可以实现一根总线上挂接多个DS18B20的目的。

高速暂存器包含:

  • 温度传感器
  • 一个字节的温度上限和温度下限报警触发器(TH和TL)
  • 配置寄存器允许用户设定9位,10位,11位和12位的温度分辨率,分别对应着温度的分辨率为:0.5°C,0.25°C,0.125°C,0.0625°C,默认为12位分辨率,

存储器:由一个高速的RAM和一个可擦除的EEPROM组成,EEPROM存储高温和低温触发器(TH和TL)以及配置寄存器的值,(就是存储低温和高温报警值以及温度分辨率)

DS18B20高速缓存器

高速暂存器由9个字节组成

  • 字节0~1 是温度存储器,用来存储转换好的温度。第0个字节存储温度低8位,第一个字节存储温度高8位
  • 字节2~3 是用户用来设置最高报警和最低报警值(TH和TL)。
  • 字节4 是配置寄存器,用来配置转换精度,可以设置为9~12 位。
  • 字节5~7 保留位。芯片内部使用
  • 字节8 CRC校验位。是64位ROM中的前56位编码的校验码。由CRC发生器产生。

DS18B20温度读取与计算

DS18B20采用16位补码的形式来存储温度数据温度是摄氏度。当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。

高字节的五个S为符号位,温度为正值时S=1,温度为负值时S=0

剩下的11位为温度数据位,对于12位分辨率,所有位全部有效,对于11位分辨率,位0(bit0)无定义,对于10位分辨率,位0和位1无定义,对于9位分辨率,位0,位1,和位2无定义

对应的温度计算:


当五个符号位S=0时,温度为正值,直接将后面的11位二进制转换为十进制,再乘以0.0625(12位分辨率),就可以得到温度值;

当五个符号位S=1时,温度为负值,先将后面的11位二进制补码变为原码(符号位不变,数值位取反后加1),再计算十进制值。再乘以0.0625(12位分辨率),就可以得到温度值;

例如:

+125℃的数字输出07D0(00000111 11010000)
 
转换成10进制是2000,对应摄氏度:0.0625x2000=125°C

-55℃的数字输出为 FC90。
  
首先取反,然后+1,转换成原码为:11111011 01101111
数值位转换成10进制是870,对应摄氏度:-0.0625x870=-55°C


代码:

unsigned int Templ,Temp2,Temperature;  //Templ低八位,Temp2高八位
unsigned char Minus Flag=0;  //负温度标志位if(Tenp2&0xFC)//判断符号位是否为1
{Minus Flag=l; //负温度标志位置1Temperature=((Temp2<<8)|Temp1); //高八位第八位进行整合Temperature=((Temperature)+1); //讲补码转换为原码,求反,补1Temperature*=0.0625;//求出十进制
}
else   //温度为正值
{Minus Flag=0;  //负温度标志位置0Temperature =((Temp2<<8) |Temp1)*0.0625;
}

配置寄存器

在配置寄存器中,我们可以通过R0和R1设置DS18B20的转换分辨率,DS18B20在上电后默认R0=1和R1=1(12分辨率),寄存器中的第7位和第0位到4位保留给设备内部使用。

单总线系统

在每个DS18B20内部都有一个唯一的64位长的序列号,这个序列号值就存在DS18B20内部的ROM中。开始的8位是产品类型编码(DS18B20是28H),接着的48位是每个器件唯一的序号,最后的8位是CRC校验码。

一线总线系统使用单总线主控来控制一个或多个从机设备。每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值。

DS18B20工作步骤

DS18B20的工作步骤可以分为三步:

1.初始化DS18B20
2.执行ROM指令
3.执行DS18B20功能指令

其中第二步执行ROM指令,也就是访问每个DS18B20,搜索64位序列号,读取匹配的序列号值,然后匹配对应的DS18B20,如果我们仅仅使用单个DS18B20,可以直接跳过ROM指令。而跳过ROM指令的字节是0xCC。

1.初始化DS18B20

任何器件想要使用,首先就是需要初始化,对于DS18B20单总线设备,首先初始化单总线为高电平,然后总线开始也需要检测这条总线上是否存在DS18B20这个器件。如果这条总线上存在DS18B20,总线会根据时序要求返回一个低电平脉冲,如果不存在的话,也就不会返回脉冲,即总线保持为高电平。

初始化具体时序步骤如下:

  • 1.单片机拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平)。
  • 2.这时DS8B20检测到请求之后,会拉低信号,大约60~240us表示应答。
  • 3.DS8B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示初始化成功
  • 4.DS18B20拉低电平60~240us之后,会释放总线。

    代码如下:
/*****初始化DS18B20*****/
unsigned int Init_DS18B20(void)
{unsigned int x=0;DQ = 1;      //DQ复位delay(4);    //稍做延时DQ = 0;      //单片机将DQ拉低delay(60);   //精确延时,大于480usDQ = 1;      //拉高总线delay(8);x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败delay(4);return x;
}

2.写时序

总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写DS18B20中。每次只传输1位数据

单片机想要给DS18B20写入一个0时,需要将单片机引脚拉低,保持低电平时间要在60~120us之间,然后释放总线
单片机想要给DS18B20写入一个1时,需要将单片机引脚拉低,拉低时间需要大于1us,然后在15us内拉高总线.

在写时序起始后15μs到60μs期间,DS18B20处于采样单总线电平状态。如果在此期间总线为高电平,则向DS18B20写入1;如果总线为低电平,则向DSl8B20写入0。

注意:2次写周期之间至少间隔1us

/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;  //与1按位与运算,dat最低位为1时DQ总线为1,dat最低位为0时DQ总线为0delay(4);DQ = 1;dat>>=1;}delay(4);
}

DS18B20写入的功能命令:

ROM指令:

采用多个DS18B20时,需要写ROM指令来控制总线上的某个DS18B20
如果是单个DS18B20,直接写跳过ROM指令0xCC即可

RAM指令,DS18B20的一些功能指令

常用的是:

温度转换 0x44

开启温度读取转换,读取好的温度会存储在高速暂存器的第0个和第一个字节中

读取温度 0xBE
读取高速暂存器存储的数据

读时序

读时隙由主机拉低总线电平至少1μs然后再释放总线,读取DS18B20发送过来的1或者0

DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。若要送出1则释放总线为高电平。


注意:所有读时隙必须至少需要60us,且在两次独立的时隙之间至少需要1ps的恢复时间

同时注意:主机只有在发送读暂存器命令(0xBE)或读电源类型命令(0xB4)后,立即生成读时隙指令,DS18B20才能向主机传送数据。 也就是先发读取指令,再发送读时隙

最后一点: 写时序注意是先写命令的低字节,比如写入跳过ROM指令0xCC(11001100),写的顺序是“零、零、壹、壹、零、零、壹、壹”,

读时序时是先读低字节,在读高字节,也就是先读取高速暂存器的第0个字节(温度的低8位),在读取高速暂存器的第1个字节(温度的高8位) 我们正常使用DS18B20读取温度读取两个温度字节即可

51例程

sbit DQ=P1^0;   //定义DS18b20的管脚/*****延时子程序*****/
void delay(unsigned int t)
{for(;t>0;t--);
}/*****初始化DS18B20*****/
unsigned char Init_DS18B20(void)
{unsigned char x=0;DQ = 1;      //DQ复位delay(8);    //稍做延时DQ = 0;      //单片机将DQ拉低delay(80);   //精确延时,大于480usDQ = 1;      //拉高总线delay(8);x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败delay(4);return x;
}/*****读一个字节*****/
unsigned char ReadOneChar(void)
{unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0;     // 给脉冲信号dat>>=1;DQ = 1;     // 给脉冲信号if(DQ)dat|=0x80;delay(4);}return(dat);
}/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(4);DQ = 1;dat>>=1;}delay(4);
}/*****读取温度*****/
int ReadTemperature(void)
{unsigned char a=0;unsigned char b=0;unsigned int t=0;t=Init_DS18B20();if(t) return Real_temp;WriteOneChar(0xCC);  //跳过读序号列号的操作WriteOneChar(0x44);  //启动温度转换t=Init_DS18B20();if(t) return Real_temp;WriteOneChar(0xCC);  //跳过读序号列号的操作WriteOneChar(0xBE);  //读取温度寄存器a=ReadOneChar();     //读低8位b=ReadOneChar();     //读高8位t=b;t<<=8;t=t|a;if(t<=0||t>0x900) return Real_temp;t=t*0.625+0.5;return(t);
}

STM32例程

DS18B20.C

#include "ds18b20.h"
#include "delay.h"    //复位DS18B20
void DS18B20_Rst(void)
{                 DS18B20_IO_OUT();     //SET PG11 OUTPUTDS18B20_DQ_OUT=0;     //拉低DQdelay_us(750);        //拉低750usDS18B20_DQ_OUT=1;     //DQ=1 delay_us(15);       //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)
{   u8 retry=0;DS18B20_IO_IN();    //SET PG11 INPUT     while (DS18B20_DQ_IN&&retry<200){retry++;delay_us(1);};    if(retry>=200)return 1;else retry=0;while (!DS18B20_DQ_IN&&retry<240){retry++;delay_us(1);};if(retry>=240)return 1;      return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void)
{u8 data;DS18B20_IO_OUT();  //SET PG11 OUTPUTDS18B20_DQ_OUT=0; delay_us(2);DS18B20_DQ_OUT=1; DS18B20_IO_IN(); //SET PG11 INPUTdelay_us(12);if(DS18B20_DQ_IN)data=1;else data=0;  delay_us(50);           return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)
{        u8 i,j,dat;dat=0;for (i=1;i<=8;i++) {j=DS18B20_Read_Bit();dat=(j<<7)|(dat>>1);}                          return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     {             u8 j;u8 testb;DS18B20_IO_OUT();   //SET PG11 OUTPUT;for (j=1;j<=8;j++) {testb=dat&0x01;dat=dat>>1;if (testb) {DS18B20_DQ_OUT=0;   // Write 1delay_us(2);                            DS18B20_DQ_OUT=1;delay_us(60);             }else {DS18B20_DQ_OUT=0; // Write 0delay_us(60);             DS18B20_DQ_OUT=1;delay_us(2);                          }}
}
//开始温度转换
void DS18B20_Start(void)
{                                          DS18B20_Rst();      DS18B20_Check();  DS18B20_Write_Byte(0xcc);  // skip romDS18B20_Write_Byte(0x44);    // convert
} //初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
u8 DS18B20_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);  //使能PORTG口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;               //PORTG.11 推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1DS18B20_Rst();return DS18B20_Check();
}
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void)
{u8 temp;u8 TL,TH;short tem;DS18B20_Start ();           // ds1820 start convertDS18B20_Rst();DS18B20_Check();    DS18B20_Write_Byte(0xcc);  // skip romDS18B20_Write_Byte(0xbe);    // convert      TL=DS18B20_Read_Byte();    // LSB   TH=DS18B20_Read_Byte();   // MSB  if(TH>7){TH=~TH;TL=~TL; temp=0;                   //温度为负  }else temp=1;              //温度为正        tem=TH;                  //获得高八位tem<<=8;    tem+=TL;                    //获得底八位tem=(float)tem*0.625;       //转换     if(temp)return tem;        //返回温度值else return -tem;
}

DS18B20.H

#ifndef __DS18B20_H
#define __DS18B20_H
#include "sys.h"   //IO方向设置
#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
IO操作函数
#define DS18B20_DQ_OUT PGout(11) //数据端口 PA0
#define DS18B20_DQ_IN  PGin(11)  //数据端口 PA0 u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//获取温度
void DS18B20_Start(void);//开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);//读出一个字节
u8 DS18B20_Read_Bit(void);//读出一个位
u8 DS18B20_Check(void);//检测是否存在DS18B20
void DS18B20_Rst(void);//复位DS18B20
#endif


【常用传感器】DS18B20温度传感器原理详解及例程代码相关推荐

  1. DS18B20温度传感器原理详解及例程代码、漏极开路

    [常用传感器]DS18B20温度传感器原理详解及例程代码_Z小旋的博客-CSDN博客_ds18b20温度传感器 传感器引脚及原理图 DS18B20传感器的引脚及封装图如下: DS18B20一共有三个引 ...

  2. 【常用传感器】LCD1602液晶工作原理详解及例程代码

    本文带你详细的了解下LCD1602液晶的工作原理以及代码编写 LCD1602液晶显示屏 LCD1602主要参数 LCD发光原理 LCD屏幕的组成: LCD和OLED区别: LCD1602引脚接线: L ...

  3. 压电加速度传感器的结构原理详解

    压电加速度传感器的结构原理详解 [摘要]简述了压电加速度传感器的结构原理.说明了该传感器灵敏度的线性度问题,分析了其正向反向灵敏度的差异与"饱和现象",以便在生产.鉴定与使用时加以 ...

  4. 视频教程-深度学习原理详解及Python代码实现-深度学习

    深度学习原理详解及Python代码实现 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 白勇 ¥88.0 ...

  5. 计算机组织与结构poc,CPU漏洞原理详解以及POC代码分享

    原标题:CPU漏洞原理详解以及POC代码分享 首先,这个漏洞已经公布近一周时间了,看到各大媒体.公众号到处在宣传,本打算不再发布类似信息,但是发现很多媒体的报道达到了一个目的--几乎所有的CPU都有漏 ...

  6. 随机森林原理详解及python代码实现

    随机森林(RF)算法 1.算法原理 2.对数据的要求(无需规范化) 3.算法的优缺点 4.算法需要注意的点 5.python代码实现(待更......) 导入相关包 读取数据并预处理(必须处理缺失值) ...

  7. 决策树原理详解及python代码实现

    决策树算法(信贷中常用来寻找规则) 1.算法原理 1.1 ID3(多叉树分类) 1.2 C4.5(多叉树分类) 1.3 Cart(二叉树分类+回归) 2.ID3.C4.5与Cart比较 3.算法优缺点 ...

  8. KNN算法原理详解及python代码实现

    KNN算法 算法原理 对数据的要求 算法的优缺点 算法需要注意的点 算法实现(python) 算法原理 计算待测样本与train_data的距离d并保存数组中 对d进行排序,取d最近的k个样本 统计样 ...

  9. VHDL语言编写DS18B20温度传感器程序详解

    网上关于DS18B20的资料很多,但是光有程序,没有讲解,导致身边很多同学即使拿到源码也无从下手,故写此篇文章,一方面接收DB18B20,一方结合原理详细讲解源码的意义. 器件原理: 原理图:     ...

  10. K-Means原理详解与Java代码实现细节

    本文作者:合肥工业大学 管理学院 钱洋 email:1563178220@qq.com 内容可能有不到之处,欢迎交流. 未经本人允许禁止转载. 最近,在使用K-means作为baseline跑数据,不 ...

最新文章

  1. 服务器网页500错误修复工具,HTTP500错误是什么?如何修复
  2. 快速排序 python菜鸟教程-Python菜鸟文本处理4种方法
  3. 【转载】尝试使用GraphicsMagick的缩略图功能
  4. Vue -- element-ui el-table 的合计在第一行显示并可点击
  5. 启用Windows Server 2012的远程桌面
  6. 安装Google Object Detection API
  7. java 保存inputstream_java如何将一个InputStream写入文件啊?
  8. 程序员的十个层次 你属于哪一层?小菜看后
  9. 从集合中查找最值得方法——max(),min(),nlargest(),nsmallest()
  10. switch(封装)
  11. Mac 运行goland出现can‘t load package: package xxxx is not in GOROOT问题排查
  12. 五大软件设计原则学习笔记4——接口隔离原则
  13. Selenium定位多个iframe嵌套中的元素
  14. Win8下用DOSBox编写汇编语言
  15. 网易易盾最新一代Java2c加固究竟有什么厉害之处?
  16. 用 Python 的 selenium扩展 驱动 火狐 谷歌 浏览器
  17. windows socket 网络编程
  18. 随机信号分析学习笔记(6)
  19. iOS开发之获取实时气压、相对高度
  20. VUE中动态改变字体大小

热门文章

  1. scrapy创建爬虫项目
  2. 物体检测学习笔记-3D相机成像原理简介
  3. 【音视频】实操YUV与RGB互转(planar模式 YUV420、YUV422、YUV444与RGB888)
  4. hlw8012电能测量芯片(多组功率电流测量)
  5. 计算机汉字区位码十进制,[计 算 机]汉字区位码\国标码\机内码之间的换算
  6. 【预测模型】基于粒子群算法优化DBN深度置信网络实现数据预测matlab代码
  7. 三菱fx2n64mr说明书_可编程控制器FX2N-64MR-D手册三菱FX2N-64MR-D使用说明书 - 广州凌控...
  8. 【开发环境准备】更新板载ESP8285固件
  9. 嵩天《Python数据分析与展示》实例3:Matplotlib基础图表绘制
  10. 《统计学》第八版贾俊平第十章方差分析知识点总结及课后习题答案