stm32读取ds18B20
时间: 2025-05-22 10:35:28 浏览: 16
### STM32 读取 DS18B20 温度传感器的实现方法
#### 硬件配置
STM32F103C8T6 是一款基于 ARM Cortex-M3 的微控制器,具有丰富的外设资源。DS18B20 是一种数字温度传感器,支持单总线通信协议。为了在 OLED 显示屏上显示 DS18B20 的温度值,需要完成以下几个部分的工作:初始化硬件、读取 DS18B20 数据以及更新 OLED 屏幕。
---
#### 软件设计流程
以下是实现 STM32 读取 DS18B20 并将其结果显示在 OLED 上的主要步骤:
1. **GPIO 配置**: 将 GPIO 设置为推挽模式以驱动 DS18B20 和 OLED 接口。
2. **单总线协议处理**: 实现 DS18B20 所需的单总线通信功能,包括复位、ROM 命令发送和数据收发。
3. **温度计算**: 解析从 DS18B20 获取的数据并转换成实际温度值。
4. **OLED 显示**: 初始化 SSD1306 控制器并通过 I2C 或 SPI 协议向屏幕写入数据显示。
---
#### 示例代码
以下是一个完整的示例程序,展示如何使用 HAL 库来控制 STM32F103C8T6 板上的 DS18B20 和 OLED 设备。
```c
#include "stm32f1xx_hal.h"
#include <stdio.h>
#include <string.h>
#define ONE_WIRE_PIN GPIO_PIN_4 // 定义 DS18B20 连接的引脚 (PA4)
#define ONE_WIRE_PORT GPIOA // 定义 DS18B20 连接的端口
// 函数声明
void OneWire_Init(void);
uint8_t OneWire_Reset(void);
void OneWire_WriteBit(uint8_t bit);
uint8_t OneWire_ReadBit(void);
void OneWire_WriteByte(uint8_t byte_val);
uint8_t OneWire_ReadByte(void);
float GetTemperature_DS18B20(void); // 获取 DS18B20 温度函数
int main(void) {
HAL_Init(); // 初始化HAL库
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 PA 端口时钟
OneWire_Init(); // 初始化单总线接口
while (1) {
float temperature = GetTemperature_DS18B20();
char buffer[50];
sprintf(buffer, "Temp: %.2f C", temperature);
// TODO: 更新 OLED 显示内容
printf("%s\n", buffer); // 测试打印
HAL_Delay(1000); // 每秒刷新一次
}
}
/**
* @brief 初始化单总线接口
*/
void OneWire_Init() {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = ONE_WIRE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出模式
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ONE_WIRE_PORT, &GPIO_InitStruct);
}
/**
* @brief 发送复位脉冲并检测是否存在设备响应
* @return 存在返回1;不存在返回0
*/
uint8_t OneWire_Reset() {
uint8_t presence_pulse = 0;
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉信号线
HAL_DelayMicroseconds(480); // 复位持续时间 >= 480us
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 放开信号线
HAL_DelayMicroseconds(70); // 等待存在脉冲
if (!HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN)) // 如果有下拉,则表示存在设备
presence_pulse = 1;
HAL_DelayMicroseconds(410); // 总线恢复等待时间
return presence_pulse;
}
/**
* @brief 写入一位数据到单总线上
* @param bit 待写入的一位数据
*/
void OneWire_WriteBit(uint8_t bit) {
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉信号线
HAL_DelayMicroseconds(bit ? 10 : 60); // '1' 时间短,'0' 时间长
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 放开信号线
HAL_DelayMicroseconds(10); // 稳定时间
}
/**
* @brief 从单总线上读取一位数据
* @return 返回读取的一位数据
*/
uint8_t OneWire_ReadBit() {
uint8_t value = 0;
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉信号线
HAL_DelayMicroseconds(5); // 创建采样窗口
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 放开信号线
HAL_DelayMicroseconds(5); // 等待稳定
if (HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN))
value = 1;
HAL_DelayMicroseconds(50); // 结束周期延迟
return value;
}
/**
* @brief 写入一字节数据到单总线上
* @param byte_val 待写入的一个字节数据
*/
void OneWire_WriteByte(uint8_t byte_val) {
for (uint8_t i = 0; i < 8; ++i) {
OneWire_WriteBit(byte_val & 0x01);
byte_val >>= 1;
}
}
/**
* @brief 从单总线上读取一字节数据
* @return 返回读取的一个字节数据
*/
uint8_t OneWire_ReadByte() {
uint8_t byte_val = 0;
for (uint8_t i = 0; i < 8; ++i) {
byte_val >>= 1;
if (OneWire_ReadBit())
byte_val |= 0x80;
}
return byte_val;
}
/**
* @brief 获取 DS18B20 当前测量的温度值
* @return 返回浮点型温度值
*/
float GetTemperature_DS18B20() {
int16_t raw_data = 0;
float temp_celsius = 0;
if (!OneWire_Reset()) // 判断是否有设备在线
return -127; // 错误标志
OneWire_WriteByte(0xCC); // 跳过 ROM 地址命令
OneWire_WriteByte(0x44); // 启动温度转换指令
HAL_Delay(750); // 等待转换完成 (~750ms)
if (!OneWire_Reset()) // 再次确认设备状态
return -127;
OneWire_WriteByte(0xCC); // 跳过 ROM 地址命令
OneWire_WriteByte(0xBE); // 读取暂存区命令
raw_data = ((int16_t)(OneWire_ReadByte())) << 8 | OneWire_ReadByte();
temp_celsius = (raw_data / 16.0); // 计算摄氏温度值
return temp_celsius;
}
```
---
#### 关键技术细节
- **单总线协议**:DS18B20 使用单总线通信方式,因此需要手动模拟其时序逻辑[^1]。
- **CRC 校验**:每个 DS18B20 都有一个唯一的 64 位 ID 编号,其中最后 8 位作为 CRC 校验码验证数据完整性[^2]。
- **温度解析**:DS18B20 提供的是原始整数值形式的结果,通常需要除以固定倍率因子(如 `16`)得到最终的实际温度。
---
阅读全文
相关推荐


















