DS18B20介绍
DS18B20是一种常用的数字温度传感器,具有体积小、硬件成本低、抗干扰能力强、精度高等特点。DS18B20数字温度传感器接线方便,包装后可应用于管道、螺纹、磁铁吸附、不锈钢包装、各种型号LTM8877,LTM8874等。外观主要根据不同的应用场合而变化。 封装后的DS18B20可用于各种非极限温度场合,如电缆沟测温、高炉水循环测温、锅炉测温、机房测温、农业温室测温、洁净室测温、弹药库测温等。耐磨耐碰,体积小,使用方便,包装形式多样,适用于各种狭小空间设备的数字测温和控制。
特点
DS18B20 单线数字温度传感器,即一线器件”,其具有独特的优点:
( 1 )采用单总线接口法 微处理器与微处理器连接时,只需一条口线即可实现 DS18B20 双向通信。单总线具有经济性好、抗干扰能力强、现场温度测量适合恶劣环境、使用方便等优点,使用户能够轻松构建传感器网络,为测量系统的构建引入新的概念。
( 2 )测量温度范围宽,测量精度高 DS18B20 测量范围为 -55 ℃ ~ 125 ℃ ; 在 -10~ 85°C精度在范围内 ± 0.5°C 。可编程的分辨率为9~12位,对应的可分辨温度为0.5℃、0.25℃、0.125℃和0.0625℃(默认出厂12位)
( 3 )使用中不需要任何外围元件。
( 4 )持有多点组网功能 多个 DS18B20 可并联在唯一的单线上,实现多点测温。
( 5 )灵活的供电方式 DS18B20 通过内部寄生电路从数据线上获取电源。因此,当数据线上的时间顺序满足一定要求时,可以不连接外部电源,使系统结构更简单、更可靠。
( 6 )可配置测量参数 DS18B20 通过程序设置测量分辨率 9~12 位。
( 7 )当负压特性电源极性反转时,温度计不会因发热而燃烧,但不能正常工作。
( 8 )掉电保护功能 DS18B20 内部含有 EEPROM ,系统断电后,仍能保存分辨率和报警温度的设定值。
??? 内部结构图
1. GND为电源地;
2. DQ输入/输出数字信号;
3. VDD外部供电电源输入端(寄生电源接接地)
内部构成
??DS18B20温度传感器的存储器DS18B20温度传感器的内部存储器包括一个高速暂存RAM非易失性可电擦除EEPRAM,后者储存高温和低温触发器TH、TL并配置寄存器。
它由9个字节组成。当温度转换命令发布时,转换获得的温度值以二字节补码的形式存储在高速临时存储器的第0和第1个字节中。单片机可以通过单线接口读取数据。读取时,相应的温度计算:当符号位置时S=0时,二进制位直接转换为十进制;当S=一、先将补码变成原码,再计算十进制值。
温度低位 | 温度高位 | TH | TL | 配置 | 保留 | 保留 | 保留 | 8位CRC |
---|
???
共9个字节,从左到右0-1-2-3-4-5-6-7-8。 0位----------->低温八位数据 1位----------->温度的高八位数据 2位----------->高温阀值 3位----------->低温阀值 4位----------->配置寄存器 5位----------->保留 6位----------->保留 7位----------->保留 8位----------->CRC
- S是符号位。
以12位转换为例: 12位转换后获得的12位数据存储在18位B20两个8比特RAM二进制前五位是符号位,
- 如果温度大于0,?这5位为0,只要将测到的数值乘于0.0625可获得实际温度;
- 如果温度小于0,则5位为1,测量值需要取反加1乘以0.0625可获得实际温度。
例如 125℃07的数字输出D0H, 25.0625℃0191H,-25.0625℃数字输出为FF6FH,-55℃数字输出为FC90H?。
温度/℃ | 数字输出(二进制) | 数字量输出(Hex) |
---|---|---|
125 | 0000 0111 1101 0000 | 0x07D0 |
85 | 0000 0101 0101 0000 | 0x0550 |
25.0625 | 0000 0001 1001 0001 | 0x0191 |
10.125 | 0000 0000 1010 0010 | 0x00A2 |
0.5 | 0000 0000 0000 1000 | 0x0008 |
0 | 0000 0000 0000 0000 | 0x0000 |
-0.5 | 1111 1111 1111 1000 | 0xFFF8 |
-10.125 | 1111 1111 0101 1110 | 0xFF5E |
-25.0625 | 1111 1110 0110 1111 | 0xFE6F |
-55 | 1111 1100 1001 0000 | 0xFC90 |
打开时,温度寄存器的默认值为 85℃
- TH和TL寄存器
,字节的意义如下
TM | R1 | R0 | 1 | 1 | 1 | 1 | 1 |
---|
低五位一直都是"1",TM用于设置测试模式位DS18B工作模式还是测试模式。DS18B20出厂时,该位置设置为0,用户不得更改。R1和R0用于设置分辨率,如下表所示:(DS18B20出厂时设置为12位。
table> R1 R0 分辨率 温度最大转换时间 0 0 9位 93.75ms 0 1 10位 187.5ms 1 0 11位 375ms 1 1 12位 750ms与主机通信
根据DS18B20的通讯协议,主机(单片机)控制DS18B20完成温度转换必须经过三个步骤:
- 每一次读写之前都要对DS18B20进行复位操作
- 复位成功后发送一条ROM指令
- 最后发送RAM指令
复位要求主CPU将数据线下拉500微秒,然后释放,当DS18B20收到信号后等待16~60微秒左右,后发出60~240微秒的存在低脉冲,主CPU收到此信号表示复位成功。
指令 | 约定代码 | 功能 |
---|---|---|
读ROM | 33H | 读DS18B20温度传感器ROM中的编码(即64位地址) |
符合ROM | 55H | 发出此命后,接着发出64位ROM编码,访问单总线上与该编码相对应的DS18B20使之作出响应,为下一步对该DS18B20的读写做好准备 |
搜索ROM | 0F0H | 用于确认挂接在同一总线上的DS18B20的个数和识别64位ROM地址。为操作各器件做好准备 |
跳过ROM | 0CCH | 忽略64位ROM地址,直接向DS18B20发出温度变换指令。适用于单片工作 |
告警搜索命令 | 0ECH | 执行后只有温度超过设定上限或下限的片子才做出响应 |
这些都不怎么能用到,是用来组网控制的指令,重要的是接下来的
指令 | 约定代码 | 功能 |
---|---|---|
DS18B20的复位时序如下: 1.单片机拉低引脚480-950us,然后再释放总线 2.上拉电阻拉高,等待15-60us后,DS18B20会拉低信号维持60-240us,表示应答 3.DS18B20拉低电平的60-240us之间,单片机读取总线的电平,如果是低电平,那么代表复位成功 4.DS18B20拉低电平的60-240us之后,会释放总线
//IO操作
#define DS18B20_Port GPIO_PIN_8 //数据端口PE8
//GPIO mode 选择
#define DS18B20_IO_IN() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;} //PE8模拟输入
#define DS18B20_IO_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} //PE8通常输出模式
void delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD = 9*nus;
SysTick->VAL=0X00;//清空计数器
SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
do
{
temp=SysTick->CTRL;//读取当前倒计数值
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void DS18B20_Rst() //复位DS18B20
{
DS18B20_IO_OUT(); //设置为输出模式
HAL_GPIO_WritePin(GPIOE, DS18B20_Port, GPIO_PIN_RESET);
//拉低DQ
delay_us(750); //拉低750us(至少480us)
HAL_GPIO_WritePin(GPIOE, DS18B20_Port, GPIO_PIN_SET);
//DQ=1拉高释放总线
delay_us(15); //15US
//进入接受模式,等待应答信号。
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在 返回0:存在
uint8_t DS18B20_Check()
{
uint8_t retry=0;
DS18B20_IO_IN();//SET PE8 INPUT
while (HAL_GPIO_ReadPin(GPIOE,DS18B20_Port)&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while (!HAL_GPIO_ReadPin(GPIOE,DS18B20_Port)&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。 所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。
典型的读时序过程为:
//返回值:1/0
u8 DS18B20_Read_Bit(void) // read one bit
{
u8 data;
DS18B20_IO_OUT();//设置为输出
DS18B20_DQ_OUT=0; //输出低电平2us
delay_us(2);
DS18B20_DQ_OUT=1; //拉高释放总线
DS18B20_IO_IN();//设置为输入
delay_us(12);//延时12us
if(DS18B20_DQ_IN)data=1;//读取总线数据
else data=0;
delay_us(50); //延时50us
return data;
}
//从DS18B20读取一个字节 //返回值:读到的数据
u8 DS18B20_Read_Byte(void) // read one byte
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
- 写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT();//设置PA0为输出
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb) //输出高
{
DS18B20_DQ_OUT=0;// 主机输出低电平
delay_us(2); //延时2us
DS18B20_DQ_OUT=1;//释放总线
delay_us(60); //延时60us
}
else //输出低
{
DS18B20_DQ_OUT=0;//主机输出低电平
delay_us(60); //延时60us
DS18B20_DQ_OUT=1;//释放总线
delay_us(2); //延时2us
}
}
}
典型DS18B20温度读取过程
- 复位
- 发送SKIP ROM命令 0xCC
- 发开始转换命令 0x44
- 复位
- 发送SKIP ROM指令 0xCC
- 发读取存储器命令 0xBE
- 连续读出两个字节数据
- 结束
//开始温度转换
void DS18B20_Start()
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0x44);// convert
}
//初始化 DS18B20 的 IO 口 DQ 同时检测 DS 的存在
//返回 1:不存在
//返回 0:存在
uint8_t DS18B20_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = DS18B20_Port;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;//普通输出模式
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;//50MHz
GPIO_InitStructure.Pull = GPIO_PULLUP;//上拉
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
DS18B20_Rst();
return DS18B20_Check();
}
//从 ds18b20 得到温度值
//精度: 0.1C
//返回值:温度值 ( -550~1250)
short DS18B20_Get_Temp()
{
uint8_t temp;
uint8_t TL,TH;
short tem;
DS18B20_Start();// ds1820 start convert
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_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=(double)tem*0.625;//转换*10倍
if(temp)
{
return tem; //返回温度值
}
else
{
return -tem;
}
}