You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 Nucleo-F302R8单总线DS18B20检测GPIO配置问题排查

STM32 单总线驱动DS18B20检测故障排查

问题背景

  • 开发平台:Nucleo-F302R8开发板,做STM32底层开发,不依赖第三方功能库实现外设驱动,目标是通过PC0引脚的OneWire单总线检测DS18B20温度传感器:检测到传感器则点亮PB13引脚连接的板载LED,未检测到则熄灭LED。
  • 硬件状态:接线、DS18B20传感器已通过Arduino平台实测可正常工作,排除硬件损坏、接线错误问题。
  • 实现逻辑:对照DS18B20数据手册的初始化时序编写逻辑:将PC0配置为输出模式拉低总线480us,之后切换为输入模式释放总线,等待60us后读取总线电平,按手册说明读到低电平代表传感器存在,高电平则无传感器。
  • 故障现象:代码始终无法正常检测到传感器,排障过程中观测到输出模式下总线连接的LED微亮,GPIO模式切换时LED会出现极短时间的闪烁,初步怀疑故障点在GPIO输入输出配置、或者微秒级延时精度异常。

现有代码

1. GPIO输入输出切换函数

void ONEWIRE_OUTPUT(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
{
    GPIO_InitTypeDef GPIO_InitStructOUT = {0}; // 存储引脚配置参数
    GPIO_InitStructOUT.Pin = GPIO_PIN_0;
    GPIO_InitStructOUT.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructOUT.Speed = GPIO_SPEED_LOW;

    HAL_GPIO_Init(GPIOC, &GPIO_InitStructOUT);

}

void ONEWIRE_INPUT(GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin)
{

    GPIO_InitTypeDef  gpio_prms = {0};
    gpio_prms.Pin   = GPIO_Pin;
    gpio_prms.Mode  = GPIO_MODE_INPUT;
    gpio_prms.Pull  = GPIO_PULLUP;

    HAL_GPIO_Init(GPIOx, &gpio_prms);
}

2. 基于TIM1的微秒延时函数(暂未通过示波器验证延时精度)

void Delay_us(uint16_t delay)
{
    __HAL_TIM_SET_COUNTER(&htim1,0); // 计数器清零
    while (__HAL_TIM_GET_COUNTER(&htim1) < delay ); // 等待计数到目标值
}

3. 主循环逻辑

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* 复位所有外设,初始化Flash接口、Systick */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* 配置系统时钟 */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* 初始化所有配置的外设 */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* 无限循环 */
  /* USER CODE BEGIN WHILE */
  HAL_TIM_Base_Start(&htim1); // 启动定时器1


  int timer_val;

  while (1)
  {
      // 配置为输出模式
      ONEWIRE_OUTPUT(GPIOC, GPIO_PIN_0);

      // 拉低总线保持480us
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, 0);
      Delay_us(480);

      timer_val = __HAL_TIM_GET_COUNTER(&htim1);
      uart_buf_len = sprintf(uart_buf, "%u us -- 目标值约480 us\r\n" , timer_val );
      HAL_UART_Transmit(&huart2, (uint8_t *)uart_buf, uart_buf_len, 100);


      // 释放总线,切换为输入模式
      ONEWIRE_INPUT(GPIOC, GPIO_PIN_0);

      // 等待60us
      Delay_us(60);
      // 读取电平,低电平代表传感器存在,高电平代表无传感器
      timer_val = __HAL_TIM_GET_COUNTER(&htim1);
      uart_buf_len = sprintf(uart_buf, "%u us -- 目标值约60 us\r\n" , timer_val );
      HAL_UART_Transmit(&huart2, (uint8_t *)uart_buf, uart_buf_len, 100);

      // 更新LED状态
      if ( HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) ) {
          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
      }else
      {
          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
      }
      HAL_Delay(1000);
      // 间隔1秒检测一次

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

故障排查思路

  • 先查GPIO配置逻辑错误:ONEWIRE_OUTPUT函数没有使用传入的形参GPIOx和GPIO_Pin,而是硬编码写死了GPIOC和GPIO_PIN_0,当前调用虽然参数匹配不会触发问题,但这种写法很容易在后续修改时出现引脚配置错位的问题,建议统一改成使用传入参数配置。另外当前输出模式配置的速度等级是GPIO_SPEED_LOW,压摆率不足会导致电平上升/下降沿过缓,无法满足OneWire微秒级的时序要求,建议改成GPIO_SPEED_FREQ_HIGH。
  • 校准延时精度:你已经在代码里加了串口打印定时器计数值的逻辑,先看串口输出的两个计数值是否和目标值匹配。如果TIM1的预分频系数配置错误,1个计数单位不是1us,实际延时长度会完全偏离DS18B20的时序要求。另外注意HAL_GPIO_Init函数执行本身会消耗数微秒的时间,会吃掉一部分你预留的等待窗口,计算延时时要把这部分时间算进去。
  • 调整存在脉冲检测逻辑:按照DS18B20手册,传感器收到主机的复位脉冲后,会在总线释放后的1560us区间内拉低总线60240us作为存在应答。你现在固定等待60us读一次电平的逻辑容错性很差,很容易错过低电平窗口:比如总线释放慢、延时有偏差,60us时传感器已经释放总线回到高电平,就会误判为无传感器。建议改成释放总线后等待15us,之后连续轮询总线电平100us,只要在这个窗口内读到低电平就判定传感器存在。
  • 排查总线负载问题:你提到输出模式下总线上接的LED微亮,先确认这个LED是不是直接并联在OneWire总线上。单总线本身驱动能力很弱,额外挂LED这类负载会拉低总线高电平值,导致传感器无法识别总线状态,建议检测时暂时去掉总线上多余的负载,只保留DS18B20和4.7k上拉电阻。

STM32底层编程学习资源推荐

  • 对应芯片的官方参考手册:STM32F302系列的参考手册是最权威的开发资料,所有寄存器定义、外设工作逻辑、时序要求、电气参数都以手册描述为准,写底层驱动时要随时对照。
  • 官方HAL/LL库源码:不需要完全依赖库函数实现逻辑,但可以参考库函数里的外设初始化流程,对照参考手册看每一行操作对应哪个寄存器的哪一位,能快速掌握外设的配置方法,比零散看教程效率高很多。
  • ARM Cortex-M4内核编程指南:内核层面的中断机制、内存映射、位带操作、指令周期等内容是所有Cortex-M芯片通用的底层知识,掌握之后不管用哪个型号的STM32都能快速上手。

内容的提问来源于stack exchange,提问作者Spider999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 16:24:30