stm32g0 ds18b20
时间: 2025-05-04 12:47:41 浏览: 22
### 实现 STM32G0 系列 MCU 驱动 DS18B20 温度传感器
为了在 STM32G0 系列微控制器上实现 DS18B20 温度传感器功能,可以采用 HAL 库编写驱动程序。以下是完整的解决方案:
#### 1. 初始化 GPIO 和 TIM 延时函数
DS18B20 使用单总线通信协议,因此需要配置一个 GPIO 引脚作为数据输入/输出接口,并通过软件模拟单总线通信。
```c
#include "stm32g0xx_hal.h"
#define ONE_WIRE_PIN GPIO_PIN_5 // 定义使用的GPIO引脚
#define ONE_WIRE_PORT GPIOA // 定义使用的GPIO端口
// 微秒级延时函数
void DelayUs(uint16_t us) {
__HAL_TIM_SET_COUNTER(&htim1, 0); // 设置计数器初值为0
__HAL_TIM_ENABLE(&htim1); // 开启定时器
while (__HAL_TIM_GET_COUNTER(&htim1) < us);
__HAL_TIM_DISABLE(&htim1); // 关闭定时器
}
```
此部分代码定义了用于 DS18B20 的 GPIO 引脚以及基于 TIM 的微秒级延时函数[^3]。
#### 2. 单总线初始化和操作函数
以下是一些必要的单总线操作函数,包括复位、读取和写入数据等功能。
```c
// 将引脚设置为低电平
static inline void OneWireLow(void) {
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET);
}
// 将引脚设置为高电平
static inline void OneWireHigh(void) {
HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET);
}
// 获取当前引脚状态
static inline uint8_t OneWireReadPin(void) {
return HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN);
}
// 复位单总线并检测是否存在设备
uint8_t OneWireReset(void) {
uint8_t presence = 0;
OneWireLow(); // 下拉总线
DelayUs(480); // 持续至少480us
OneWireHigh(); // 上拉总线
DelayUs(70); // 等待主机释放总线后的延迟时间
if (!OneWireReadPin()) // 如果存在设备,则会返回低电平
presence = 1;
DelayUs(400); // 等待剩余的时间
return presence;
}
// 向单总线发送一字节数据
void OneWireWriteByte(uint8_t data) {
for (int i = 0; i < 8; i++) {
OneWireLow();
if ((data & 0x01) == 0)
DelayUs(60); // 发送'0'
else
DelayUs(10); // 发送'1'
OneWireHigh();
data >>= 1;
DelayUs(60); // 数据恢复时间
}
}
// 从单总线上读取一字节数据
uint8_t OneWireReadByte(void) {
uint8_t byte = 0;
for (int i = 0; i < 8; i++) {
OneWireLow();
DelayUs(2); // 主机下拉总线
OneWireHigh();
DelayUs(12); // 给从机准备时间
if (OneWireReadPin())
byte |= 0x01 << i; // 读取到的是‘1’
DelayUs(60); // 数据恢复时间
}
return byte;
}
```
这些函数实现了单总线的基本操作逻辑,包括复位、写入和读取字节等[^1]。
#### 3. DS18B20 测量温度的核心流程
以下是测量 DS18B20 温度的主要过程。
```c
float ReadTemperature(void) {
float temperature = 0;
// 步骤1:复位单总线
if (!OneWireReset()) {
return -999; // 若未检测到设备则返回错误值
}
// 步骤2:发送跳过ROM命令
OneWireWriteByte(0xCC);
// 步骤3:发送转换温度命令
OneWireWriteByte(0x44);
// 等待转换完成(约需750ms)
DelayUs(750 * 1000);
// 再次复位单总线
if (!OneWireReset()) {
return -999;
}
// 跳过ROM命令
OneWireWriteByte(0xCC);
// 发送读寄存器命令
OneWireWriteByte(0xBE);
// 读取两个字节的数据(LSB和MSB)
uint8_t lsb = OneWireReadByte();
uint8_t msb = OneWireReadByte();
// 计算实际温度值
int16_t raw_temp = (msb << 8) | lsb;
temperature = (float)(raw_temp / 16.0f);
return temperature;
}
```
该核心函数完成了 DS18B20 的温度采集工作流,包括复位、启动测温和读取结果等步骤[^2]。
---
### 示例主循环调用
```c
int main(void) {
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化GPIO
MX_TIM1_Init(); // 初始化TIM1用于延时
while (1) {
float temp = ReadTemperature();// 读取温度
if (temp != -999) { // 判断是否成功获取温度
printf("Current Temperature: %.2f°C\n", temp);
} else {
printf("Error reading temperature!\n");
}
HAL_Delay(1000); // 每隔一秒刷新一次
}
}
```
以上为主程序框架,展示了如何周期性地调用 `ReadTemperature` 函数来显示实时温度。
---
阅读全文
相关推荐


















