DS18B20 温度传感器
一、传感器概述
1.1 基本特性
DS18B20 是由 Dallas Semiconductor(现 Maxim Integrated)生产的数字温度传感器。该器件采用单总线接口,可直接输出数字温度值,无需外部模数转换电路。
关键参数表:
| 参数类别 | 技术规格 |
|---|---|
| 温度测量范围 | -55℃ 至 +125℃ |
| 测量精度 | ±0.5℃(-10℃ 至 +85℃范围内) |
| 分辨率 | 可编程配置:9、10、11、12 位 |
| 默认分辨率 | 12 位(0.0625℃/LSB) |
| 工作电压 | 3.0V 至 5.5V |
| 转换时间 | 93.75ms(9位)至 750ms(12位) |
| 封装形式 | TO-92、SO-8、µSOP |
1.2 引脚定义
TO-92 封装引脚排列(正视,引脚朝下):

引脚功能说明:
-
引脚1(GND):电源地,连接至系统参考地
-
引脚2(DQ):单总线数据输入/输出引脚
-
引脚3(VDD):电源输入引脚(3.0V-5.5V)
二、单总线通信协议
2.1 协议概述
单总线协议(1-Wire Protocol)采用单根数据线实现双向通信。该协议包含以下关键技术特性:
-
单主多从架构:单总线上可挂接多个从设备
-
寄生供电模式:通过数据线为设备供电,无需独立电源
-
严格的时序要求:所有通信操作都有精确的时序规范
2.2 电气特性
典型应用电路:
VCC (+3.3V-5V)
│
├─[4.7kΩ]─┐
│ │
└─────┐ │
│ │
DS18B20 │
1│ 2│ 3│
GND DQ VDD
│ │
GND ├─→ MCU I/O Pin
│
GND
上拉电阻作用:
-
在总线空闲时提供确定的高电平状态
-
确保信号完整性,减少噪声影响
-
典型值:4.7kΩ ±5%
三、温度数据格式
3.1 温度寄存器结构
DS18B20 输出 16 位二进制补码格式的温度数据:
| 位位置 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 含义 | S | S | S | S | S | 2⁶ | 2⁵ | 2⁴ | 2³ | 2² | 2¹ | 2⁰ | 2⁻¹ | 2⁻² | 2⁻³ | 2⁻⁴ |
说明:
-
位 15-11:符号位(S=1 表示负温度,S=0 表示正温度)
-
位 10-4:整数部分(7 位二进制,范围 0-127)
-
位 3-0:小数部分(4 位二进制)
3.2 分辨率配置
DS18B20 提供四种分辨率设置,通过配置寄存器实现:
| 分辨率位数 | R1 | R0 | 温度精度 | 最大转换时间 |
|---|---|---|---|---|
| 9 位 | 0 | 0 | 0.5℃ | 93.75ms |
| 10 位 | 0 | 1 | 0.25℃ | 187.5ms |
| 11 位 | 1 | 0 | 0.125℃ | 375ms |
| 12 位 | 1 | 1 | 0.0625℃ | 750ms |
默认配置:R1=1, R0=1(12 位分辨率)
四、通信时序详析
4.1 复位脉冲时序
时间参数要求:
-
主机复位脉冲宽度:最小 480μs
-
主机释放总线后延迟:15-60μs
-
从机响应脉冲宽度:60-240μs
-
总线恢复时间:最小 480μs
4.2 写时序规范
写"0"时序:
-
主机将总线拉低至少60us
-
ds18b20在60us内去采样,采到低电平,则代表主机向ds18b20发送了一个bit'0'
-
最后主机将总线拉高
写"1"时序:
-
主机将总线拉低大于1us
-
主机释放总线,将总线拉高
-
主机延时至少45us,确保ds18b20能够采样到一个高电平
写时间槽参数:
-
写"0"低电平时间:60-120μs
-
写"1"低电平时间:1-15μs
-
写周期总时间:最小 60μs,典型 70μs
4.3 读时序规范

读时间槽参数:
-
主机低电平时间:>1μs
-
采样窗口:低电平释放后 15μs 内
-
位周期总时间:最小 60μs
五、驱动程序实现
5.1 硬件抽象层定义
// 引脚操作宏定义
#define DS18B20_PORT P3 // 使用P3端口
#define DS18B20_PIN 7 // 使用P3.7引脚
// 总线操作宏
#define DQ_LOW() (DS18B20_PORT &= ~(1 << DS18B20_PIN))
#define DQ_HIGH() (DS18B20_PORT |= (1 << DS18B20_PIN))
#define DQ_INPUT() (DS18B20_PORT |= (1 << DS18B20_PIN)) // 设置为输入模式
#define DQ_READ() ((DS18B20_PORT & (1 << DS18B20_PIN)) ? 1 : 0)
5.2 精确延时函数
/**
* @brief 微秒级延时函数
* @param us 延时微秒数
* @note 基于11.0592MHz晶振,12时钟周期
*/
void delay_us(unsigned int us)
{
while(us--)
{
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
}
/**
* @brief 毫秒级延时函数
* @param ms 延时毫秒数
*/
void delay_ms(unsigned int ms)
{
while(ms--)
{
delay_us(1000);
}
}
5.3 复位函数实现
/**
* @brief DS18B20复位序列
* @return 1:复位成功,检测到器件存在
* 0:复位失败,器件无响应
*/
uint8_t DS18B20_Reset(void)
{
uint8_t presence = 0;
// 主机驱动总线为低电平
DQ_LOW();
// 保持低电平480μs以上(推荐500-550μs)
delay_us(550);
// 主机释放总线,上拉电阻拉至高电平
DQ_HIGH();
DQ_INPUT(); // 切换为输入模式
// 延时等待15-60μs
delay_us(30);
// 检测从机响应脉冲
if(DQ_READ() == 0)
{
// 等待从机释放总线(60-240μs)
uint16_t timeout = 250;
while(!DQ_READ() && timeout--);
if(timeout > 0)
{
presence = 1; // 检测到器件
}
}
// 等待总线恢复(至少480μs)
delay_us(500);
return presence;
}
5.4 数据读写函数
/**
* @brief 向DS18B20写入一个字节
* @param data 要写入的数据字节
*/
void DS18B20_WriteByte(uint8_t data)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
// 写时间槽开始
DQ_LOW();
if(data & 0x01) // 写入"1"
{
// 保持低电平>1μs,然后释放总线
_nop_(); _nop_(); // 约2μs延时
DQ_HIGH();
DQ_INPUT();
// 保持总线高电平至少45μs
delay_us(50);
}
else // 写入"0"
{
// 保持低电平60-120μs
delay_us(70);
DQ_HIGH();
DQ_INPUT();
}
// 写时间槽结束,恢复总线
data >>= 1; // 准备下一位
delay_us(5); // 位间恢复时间
}
// 字节写入完成后,确保总线处于释放状态
DQ_HIGH();
DQ_INPUT();
}
/**
* @brief 从DS18B20读取一个字节
* @return 读取到的数据字节
*/
uint8_t DS18B20_ReadByte(void)
{
uint8_t i;
uint8_t data = 0;
for(i = 0; i < 8; i++)
{
// 读时间槽开始
DQ_LOW();
_nop_(); _nop_(); // 约2μs低电平
// 主机释放总线,准备采样
DQ_HIGH();
DQ_INPUT();
// 延时15μs后采样
delay_us(15);
// 读取总线状态
if(DQ_READ())
{
data |= (0x01 << i); // 读取到"1"
}
// 完成读时间槽(总时间>60μs)
delay_us(45);
// 确保总线恢复
DQ_HIGH();
DQ_INPUT();
}
return data;
}
5.5 温度读取完整流程
/**
* @brief 读取当前温度值
* @return 温度值(浮点数,单位:℃)
* @note 使用12位分辨率,转换时间约750ms
*/
float DS18B20_ReadTemperature(void)
{
uint8_t temp_low, temp_high;
int16_t temp_raw;
float temperature;
// 步骤1:启动温度转换
if(!DS18B20_Reset())
{
return ERROR_TEMPERATURE; // 定义错误值,如-999.0
}
// 发送跳过ROM命令(仅单设备情况)
DS18B20_WriteByte(0xCC);
// 发送温度转换命令
DS18B20_WriteByte(0x44);
// 等待转换完成(12位分辨率需750ms)
delay_ms(750);
// 步骤2:读取温度数据
if(!DS18B20_Reset())
{
return ERROR_TEMPERATURE;
}
// 发送跳过ROM命令
DS18B20_WriteByte(0xCC);
// 发送读暂存器命令
DS18B20_WriteByte(0xBE);
// 读取温度寄存器(低字节和高字节)
temp_low = DS18B20_ReadByte();
temp_high = DS18B20_ReadByte();
// 合成16位温度原始值
temp_raw = (temp_high << 8) | temp_low;
// 步骤3:温度值转换
// 判断温度符号
if(temp_raw & 0x8000) // 负温度
{
// 计算补码的绝对值
temp_raw = ~temp_raw + 1;
temperature = -(temp_raw * 0.0625);
}
else // 正温度
{
temperature = temp_raw * 0.0625;
}
return temperature;
}
七、调试与故障排除
7.1 常见问题及解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 读取温度始终为0 | 总线无上拉电阻 | 添加4.7kΩ上拉电阻至VCC |
| 温度值异常波动 | 电源噪声干扰 | 在VDD和GND间添加100nF电容 |
| 器件无响应 | 时序不符合规范 | 使用逻辑分析仪检查时序 |
| 温度转换失败 | 延时不足 | 确保750ms转换等待时间 |
| 多个传感器冲突 | ROM未正确匹配 | 实现ROM搜索和匹配算法 |
八、技术参数总结表
| 技术指标 | 规格描述 |
|---|---|
| 通信接口 | 单总线(1-Wire) |
| 数据格式 | 16位二进制补码 |
| 转换精度 | 用户可编程9-12位 |
| 最大采样率 | 9位:约10.6Hz,12位:约1.33Hz |
| 总线负载能力 | 理论上最多可挂接数百个器件 |
| 温度误差 | ±0.5℃(-10℃至+85℃) |
| 长期稳定性 | ±0.2℃/年(典型值) |
| ESD保护 | 人体模型:≥4kV |