1、DS18B20 单线数字温度传感器,即“一线器件”,其具有独特的优点:
2、DS18B20内部结构:
DS18B20内部主要包括,64位ROM、2字节温度输出寄存器、1字节上下警报寄存器(TH和TL)和1字节配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同,这样就可以实现一根总线挂接多个DS18B20的目的。配置寄存器允许用户将温度 - 数字转换的分辨率设置为9,10,11或12位。DS18B20控制引脚需要一个上拉电阻,并通过开漏模式连接到总线。DS18B20无需外部电源也可运行,当总线为高电平时,通过DQ引脚提高电源,并将电存储在Cpp电容中,在总线处于低电平时为器件供电,这种方法称为“寄生电源”。另外DS18B20也可通过VDD供电。结构图如下:
3、DS18B20内部构成:
高速暂存存储器由9个字节组成,分为温度的低八位数据0、温度的高8位数据1、高温阈值2、低温阈值3、配置寄存器4、保留5、保留6、保留7和CRC校验8。器件断电时,EEPROM寄存器中的数据保留,上电后,EEPROM数据被重新加载到相应的寄存器位置,也可以使用命令随时将数据从EEPROM重新加载到暂存器中。
4、温度寄存器数据格式:
DS18B20中的温度传感器数据用16位二进制形式提供,其中S为符号位(正数S=0,负数S=1)。温度传感器的分辨率可由用户配置为9、10、11或12位,分别对应0.5℃、0.25 ℃、0.125℃和0.0625℃的增量。开机时的默认分辨率是12位。如果DS18B20配置为12位分辨率,那么温度寄存器中的所有位都将包含有效数据。对于11位分辨率,0位没有定义。对于10位分辨率,位1和0没有定义,对于9位分辨率,位2、位1和位0没有定义。
5、TH和TL报警寄存器格式:
TH和TL寄存器存储温度报警触发值,符号位S表示值是正还是负,对于正数,S=0,对于负数,S=1。DS18B20执行温度转换后,将温度值与用户定义的两个报警触发值进行比较,由于TH和TL是8位寄存器,因此在比较TH和TL时只使用温度寄存器的第11位到第4位,如果被测温度低于或等于TL值,或高于或等于TH值,则在DS18B20内部存在报警条件,并设置报警标志。主设备可以通过发出一个[EC]命令来检查总线上所有DS18B20的报警标志状态。TH和TL寄存器是非易失性的(EEPROM),当设备断电时,它们将保留数据。可以通过内存部分暂存器的字节2和字节3访问TH和TL。
6、配置寄存器数据格式:
在配置寄存器中,我们可以通过R0和R1设置DS18B20的转换分辨率,DS18B20在上电后默认R0=1和R1=1(12分辨率),寄存器中的第7位和第0位到4位保留给设备内部使用。
7、 初始化时序:
主机首先发出一个最少480微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。
做为从器件的DS18B20在一上电后就一直在检测总线上是否有至少480微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。
8、写操作时序:
写周期最少为60微秒,最长不超过120微秒。若主机想写0,则把总线拉低电平最少60微秒直至写周期结束。若主机想写1,则一开始主机先把总线拉低1微秒表示写周期开始,1微秒后就释放总线为高电平,一直到写周期结束。做为从机的DS18B20则在检测到总线被拉底后等待15微秒然后从15us到45us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。
9、读操作时序:
对于读数据操作时序也分为读0时序和读1时序两个过程。读时序是从主机把单总线拉低之后,在1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。若要送出1则释放总线为高电平。主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。采样期内总线为高电平则确认为1。完成一个读时序过程,至少需要60us才能完成。
10、DS18B20 单线通信功能是分时完成的,他有严格的时序概念,如果出现序列混乱, 1-WIRE 器件将不响应主机,因此读写时序很重要。系统对 DS18B20 的各种操作必须按协议进行。根据 DS18B20 的协议规定,微控制器控制 DS18B20 完成温度的转换必须经过以下 3个步骤 :
1、每次读写前对 DS18B20 进行复位初始化。复位要求主 CPU 将数据线下拉 500us ,然后释放, DS18B20 收到信号后等待 16us~60us 左右,然后发出60us~240us 的存在低脉冲,主 CPU 收到此信号后表示复位成功。
2、发送一条 ROM 指令。
11、 Sensor_Temp.c
#include "sensor_temperature.h"
#include "bsp_systick.h"
// 传感器复位函数
void DS18B20_Reset(void)
{
DS18B20_DQ_OUT_L;
SYSTICK_DelayUs(480);
DS18B20_DQ_OUT_H;
SYSTICK_DelayUs(15);
}
// 等待传感器响应函数
bool DS18B20_Check(void)
{
uint8_t retry = 0;
while(DS18B20_DQ_IN) { if(retry++ > 60) { return false;} else { SYSTICK_DelayUs(1); } }
retry = 0;
while(!DS18B20_DQ_IN) { if(retry++ > 240){ return false;} else { SYSTICK_DelayUs(1); } }
return true;
}
// 传感器初始化
bool DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(DS18B20_RCC_ClockCmd , ENABLE);
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_Pin_x;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(DS18B20_GPIOx, &GPIO_InitStructure);
DS18B20_Reset(); // 传感器复位
return DS18B20_Check();
}
// 向传感器写数据
void DS18B20_Write(uint8_t data)
{
for (uint8_t i=0; i<8; i++)
{
if(data&0x01)
{
DS18B20_DQ_OUT_L;
SYSTICK_DelayUs(2);
DS18B20_DQ_OUT_H;
SYSTICK_DelayUs(60);
}
else
{
DS18B20_DQ_OUT_L;
SYSTICK_DelayUs(60);
DS18B20_DQ_OUT_H;
SYSTICK_DelayUs(2);
}
data >>= 1;
}
}
// 从传感器读取一个Bit数据
uint8_t DS18B20_Read_Bit(void)
{
uint8_t data;
DS18B20_DQ_OUT_L;
DS18B20_DELAY_2US();
DS18B20_DQ_OUT_H;
DS18B20_DELAY_2US();
data = DS18B20_DQ_IN;
SYSTICK_DelayUs(50);
return data;
}
// 从传感器中读取一个字节数据
uint8_t DS18B20_Read_Byte(void)
{
uint8_t data = 0;
for(uint8_t i=0; i<8; i++)
{
data >>= 1;
if(DS18B20_Read_Bit())
{
data |= 0x80;
}
}
return data;
}
// 向传感器发送指令,测量温度
void DS18B20_Start(void)
{
DS18B20_Reset();
DS18B20_Check();
DS18B20_Write(0xCC); // 忽略ROM地址,直接发送命令
DS18B20_Write(0x44); // 启动DS18B20单个温度转换
}
float data;
// 读取传感器的值
float DS18B20_Get_Temp(void)
{
DS18B20_Start();
DS18B20_Reset();
DS18B20_Check();
DS18B20_Write(0xCC); // 忽略ROM地址,直接发送命令
DS18B20_Write(0xBE); // 读取暂存器中9字节数据
data = ((uint16_t)DS18B20_Read_Byte() | DS18B20_Read_Byte() << 8) * 0.0625f;
return data;
}
8、Sensor_Temp.h
#ifndef _BSP_TEMPERATURE_H_
#define _BSP_TEMPERATURE_H_
#include "stm32f0xx.h"
#include
#define DS18B20_RCC_ClockCmd RCC_AHBPeriph_GPIOA
#define DS18B20_GPIO_Pin_x GPIO_Pin_0
#define DS18B20_GPIO_NUMBER 0
#define DS18B20_GPIOx GPIOA
#define DS18B20_DQ_OUT_H GPIO_SetBits(DS18B20_GPIOx, DS18B20_GPIO_Pin_x)
#define DS18B20_DQ_OUT_L GPIO_ResetBits(DS18B20_GPIOx, DS18B20_GPIO_Pin_x)
#define DS18B20_DQ_IN GPIO_ReadInputDataBit(DS18B20_GPIOx, DS18B20_GPIO_Pin_x)
// 定义内联延时函数
static inline void DS18B20_DELAY_2US(void)
{
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();
}
void DS18B20_Reset(void);
bool DS18B20_Check(void);
bool DS18B20_Init(void);
uint8_t DS18B20_Read_Bit(void);
uint8_t DS18B20_Read_Byte(void);
void DS18B20_Write_Byte(uint8_t dat);
void DS18B20_Start(void);
float DS18B20_Get_Temp(void);
#endif
9、主函数
int main()
{
SYSTICK_Init(1); // 滴答定时器初始化
DS18B20_Init(); // 传感器初始化
USART1_Init(); // 串口初始化
while(1)
{
printf("Temperature is: %f\r\n",DS18B20_Get_Temp());
SYSTICK_DelayMs(800);
}
}
参考资料地址:http://www.21ic.com/jichuzhishi/datasheet/DS18B20/data/187578.html