ds18b20hal代码
时间: 2025-05-14 22:03:34 浏览: 18
### DS18B20 温度传感器 HAL 实现
为了实现 DS18B20 的功能,通常需要通过单总线协议与其通信。以下是基于 STM32 HAL 库的一个典型 DS18B20 配置和读取温度的代码示例。
#### 单总线初始化
首先,在 `main.c` 文件中定义 GPIO 引脚用于与 DS18B20 进行通信,并完成必要的初始化操作[^1]:
```c
#include "stm32g4xx_hal.h"
#define ONE_WIRE_PIN GPIO_PIN_5 // 定义使用的 GPIO 引脚 (例如 PA5)
#define ONE_WIRE_PORT GPIOA // 定义使用的端口 (例如 GPIOA)
void OneWire_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 GPIOA 时钟
// 设置为开漏输出模式
GPIO_InitStruct.Pin = ONE_WIRE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ONE_WIRE_PORT, &GPIO_InitStruct);
}
```
#### 发送复位脉冲并检测存在信号
在与 DS18B20 通信之前,需发送一个复位脉冲来启动设备,并等待其返回的存在信号。
```c
uint8_t OneWire_Reset(void) {
uint8_t presence = 0;
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉引脚
HAL_Delay(500); // 等待至少 480us
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 上拉引脚
HAL_DelayMicroseconds(70); // 延迟约 60~70 us
if (!HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN)) {
presence = 1; // 存在信号被检测到
}
while(!HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN)); // 等待总线释放
return presence;
}
```
#### 数据传输函数
提供写入字节和读取字节的功能以便于后续命令交互。
```c
void OneWire_WriteByte(uint8_t data) {
for(int i=0;i<8;i++) {
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉引脚
HAL_DelayMicroseconds(2);
if(data & 0x01){
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 如果当前位是 '1' 则快速释放
}
HAL_DelayMicroseconds(60); // 等待数据稳定时间
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 总线上浮
data >>= 1; // 移动下一位
}
}
uint8_t OneWire_ReadByte(void) {
uint8_t byte = 0;
for(int i=0;i<8;i++) {
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); // 下拉引脚
HAL_DelayMicroseconds(2);
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); // 快速释放让主机采样
HAL_DelayMicroseconds(12); // 等待数据稳定
if(HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN)){
byte |= (1 << i); // 将接收到的数据拼接到变量中
}
}
return byte;
}
```
#### 主程序逻辑
最后编写主循环中的调用来获取温度值。
```c
int main(void) {
HAL_Init();
OneWire_Init();
while (1) {
if(OneWire_Reset()) { // 复位成功则继续执行下面的操作
OneWire_WriteByte(0xCC); // 跳过 ROM 操作指令
OneWire_WriteByte(0x44); // 开始转换温度
HAL_Delay(1000); // 等待一段时间直到转换结束
if(OneWire_Reset()) { // 再次确认连接正常
OneWire_WriteByte(0xCC); // 跳过 ROM 操作指令
OneWire_WriteByte(0xBE); // 读寄存器
int lsb = OneWire_ReadByte(); // 获取低字节
int msb = OneWire_ReadByte(); // 获取高字节
float temp = ((msb << 8) | lsb) * 0.0625f; // 计算实际温度
printf("Temperature: %.2f C\n", temp); // 打印结果至串口或其他显示方式
}
}
}
}
```
### 注意事项
上述代码片段仅作为基础框架展示如何利用 HAL 函数库控制 DS18B20 工作流程的一部分。具体项目可能还需要调整延时参数或者增加错误处理机制以适应不同应用场景需求。
阅读全文
相关推荐


















