驱动DS18B20温度传感器
DS18B20是一款由Dallas Semiconductor公司生产的单总线数字温度传感器。单总线接口:仅需一根数据线即可与微控制器进行通信,大大减少了硬件连接的复杂性。高精度测量:测量范围为 - 55°C 至 + 125°C,精度可达 ± 0.5°C。可编程分辨率:可以通过配置寄存器设置9 - 12位的分辨率,对应的温度精度分别为 0.5°C、0.25°C、0.125°C 和 0.0625°C
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇
一、DS18B20简介
DS18B20是一款由Dallas Semiconductor公司生产的单总线数字温度传感器。它具有以下特点:
- 单总线接口:仅需一根数据线即可与微控制器进行通信,大大减少了硬件连接的复杂性。
- 高精度测量:测量范围为 - 55°C 至 + 125°C,精度可达 ± 0.5°C。
- 可编程分辨率:可以通过配置寄存器设置9 - 12位的分辨率,对应的温度精度分别为 0.5°C、0.25°C、0.125°C 和 0.0625°C。
- 自带温度校准:内部集成了温度校准电路,无需额外的校准操作。
二、硬件连接
DS18B20通常有三个引脚:VDD(电源)、GND(接地)和DQ(数据)。连接时,VDD接电源(一般为3.3V或5V),GND接地,DQ引脚连接到微控制器的一个GPIO引脚。为了保证通信的稳定性,通常需要在DQ引脚上拉一个4.7KΩ的电阻到电源。
三、通信协议
DS18B20采用单总线通信协议,通信过程主要包括初始化、ROM操作命令和功能命令三个步骤。
1. 初始化
初始化过程是主机和DS18B20建立通信的第一步。主机通过拉低数据线至少480μs,然后释放数据线,等待15 - 60μs后,检测DS18B20是否存在。如果DS18B20存在,它会拉低数据线60 - 240μs作为响应。
2. ROM操作命令
在初始化成功后,主机可以发送ROM操作命令来识别总线上的DS18B20。常见的ROM操作命令有:
- 搜索ROM(0xF0):用于识别总线上所有DS18B20的64位ROM代码。
- 读取ROM(0x33):用于读取单个DS18B20的64位ROM代码。
- 匹配ROM(0x55):用于指定与主机通信的DS18B20。
- 跳过ROM(0xCC):当总线上只有一个DS18B20时,可以跳过ROM操作,直接进行功能命令操作。
3. 功能命令
在完成ROM操作后,主机可以发送功能命令来控制DS18B20的工作。常见的功能命令有:
- 温度转换(0x44):启动DS18B20进行温度转换。
- 读取暂存器(0xBE):读取DS18B20内部暂存器中的温度数据。
四、代码实现(以STM32为例,使用HAL库)
#include "stm32f1xx_hal.h"
#include <stdio.h>
// 定义DS18B20连接的GPIO引脚
#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_PIN_0
// 初始化DS18B20
uint8_t DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIOA时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置DS18B20引脚为推挽输出模式
GPIO_InitStruct.Pin = DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
// 拉低数据线至少480μs
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay(1); // 延时1ms
// 释放数据线
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
HAL_Delay(1); // 延时1ms
// 检测DS18B20的响应
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
if (HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN) == GPIO_PIN_RESET)
{
HAL_Delay(2); // 延时2ms
if (HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN) == GPIO_PIN_SET)
{
return 1; // 初始化成功
}
}
return 0; // 初始化失败
}
// 向DS18B20写入一个字节
void DS18B20_WriteByte(uint8_t dat)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
for (uint8_t i = 0; i < 8; i++)
{
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay(1); // 延时1μs
if (dat & 0x01)
{
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
}
HAL_Delay(60); // 延时60μs
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
dat >>= 1;
}
}
// 从DS18B20读取一个字节
uint8_t DS18B20_ReadByte(void)
{
uint8_t dat = 0;
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
for (uint8_t i = 0; i < 8; i++)
{
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay(1); // 延时1μs
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
HAL_Delay(1); // 延时1μs
dat >>= 1;
if (HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN) == GPIO_PIN_SET)
{
dat |= 0x80;
}
HAL_Delay(60); // 延时60μs
}
return dat;
}
// 启动DS18B20进行温度转换
void DS18B20_StartConvert(void)
{
if (DS18B20_Init())
{
DS18B20_WriteByte(0xCC); // 跳过ROM操作
DS18B20_WriteByte(0x44); // 启动温度转换
}
}
// 读取DS18B20的温度值
float DS18B20_ReadTemperature(void)
{
uint8_t LSB, MSB;
int16_t temp;
float temperature;
if (DS18B20_Init())
{
DS18B20_WriteByte(0xCC); // 跳过ROM操作
DS18B20_WriteByte(0xBE); // 读取暂存器
LSB = DS18B20_ReadByte();
MSB = DS18B20_ReadByte();
temp = (MSB << 8) | LSB;
temperature = (float)temp / 16.0;
}
else
{
temperature = -127.0; // 初始化失败,返回错误值
}
return temperature;
}
int main(void)
{
HAL_Init();
float temperature;
while (1)
{
DS18B20_StartConvert();
HAL_Delay(750); // 等待温度转换完成
temperature = DS18B20_ReadTemperature();
printf("Temperature: %.2f°C\n", temperature);
HAL_Delay(1000); // 每隔1秒读取一次温度
}
}
五、代码解释
- DS18B20_Init函数:用于初始化DS18B20,通过拉低和释放数据线,检测DS18B20的响应信号,判断初始化是否成功。
- DS18B20_WriteByte函数:向DS18B20写入一个字节的数据,通过逐位发送的方式将数据写入。
- DS18B20_ReadByte函数:从DS18B20读取一个字节的数据,通过逐位读取的方式将数据读取出来。
- DS18B20_StartConvert函数:启动DS18B20进行温度转换,先跳过ROM操作,然后发送温度转换命令。
- DS18B20_ReadTemperature函数:读取DS18B20的温度值,先跳过ROM操作,然后发送读取暂存器命令,读取低字节和高字节的数据,将其组合成一个16位的整数,最后转换为浮点数表示的温度值。
- main函数:在主函数中,循环调用
DS18B20_StartConvert函数启动温度转换,等待750ms(保证温度转换完成),然后调用DS18B20_ReadTemperature函数读取温度值,并通过串口输出。
通过以上步骤和代码,我们可以成功驱动DS18B20温度传感器,实现温度的测量和读取。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)