ST意法半导体
直播中

王晾其

9年用户 1106经验值
私信 关注
[问答]

STM32H743IIC HAL库驱动硬件I2C,hi2c2.state一直是busy. 为什么?

void MX_I2C2_Init(void)
{

  /* USER CODE BEGIN I2C2_Init 0 */

  /* USER CODE END I2C2_Init 0 */

  /* USER CODE BEGIN I2C2_Init 1 */

  /* USER CODE END I2C2_Init 1 */
  hi2c2.Instance = I2C2;
  hi2c2.Init.timing = 0x10C0ECFF;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C2_Init 2 */

  /* USER CODE END I2C2_Init 2 */

}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(i2cHandle->Instance==I2C2)
  {
  /* USER CODE BEGIN I2C2_MspInit 0 */

  /* USER CODE END I2C2_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C2;
    PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_RCC_GPIOH_CLK_ENABLE();
    /**I2C2 GPIO Configuration
    PH4     ------> I2C2_SCL
    PH5     ------> I2C2_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

    /* I2C2 clock enable */
    __HAL_RCC_I2C2_CLK_ENABLE();

    /* I2C2 DMA Init */
    /* I2C2_RX Init */
    hdma_i2c2_rx.Instance = DMA1_Stream2;
    hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX;
    hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR;
    hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx);

    /* I2C2_TX Init */
    hdma_i2c2_tx.Instance = DMA1_Stream3;
    hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX;
    hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR;
    hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx);

  /* USER CODE BEGIN I2C2_MspInit 1 */

  /* USER CODE END I2C2_MspInit 1 */
  }
}


以上是初始化代码。然后使用以下代码发送数据:

HAL_I2C_Master_Transmit_DMA(&hi2c2, PCF8574_ADDR, &temp, 1);

现象是只能发一次,之后hi2c2.state一直是busy。在中断处理函数中手动改为ready后,dma的状态一直处于busy.




回帖(1)

半导体开发

2025-3-13 17:13:40

在使用STM32H743的HAL库驱动硬件I2C时,hi2c2.state一直处于HAL_I2C_STATE_BUSY状态,可能有以下几种原因:


1. I2C总线被占用或未正确释放



  • 如果在之前的操作中,I2C总线没有被正确释放(例如,由于错误或异常情况),可能会导致hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:在初始化之前,尝试调用HAL_I2C_DeInit(&hi2c2)来释放I2C总线,然后重新初始化。


2. I2C总线上的设备未响应



  • 如果I2C总线上的设备没有正确响应,可能会导致I2C操作超时,从而使hi2c2.state保持在HAL_I2C_STATE_BUSY状态。

  • 解决方法:检查I2C总线上的设备是否正常工作,确保设备地址正确,并且设备已正确连接到总线。


3. I2C时序配置不正确



  • hi2c2.Init.Timing的值可能配置不正确,导致I2C总线无法正常工作。

  • 解决方法:根据STM32H743的参考手册和实际硬件情况,调整hi2c2.Init.Timing的值。可以使用STM32CubeMX工具生成合适的时序配置。


4. I2C中断或DMA未正确处理



  • 如果使用了I2C中断或DMA,并且中断或DMA未正确处理,可能会导致hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:确保中断或DMA处理程序正确实现,并且在操作完成后正确清除相关标志。


5. I2C硬件故障



  • 如果I2C硬件本身存在故障(例如,引脚损坏或短路),也可能导致hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:检查硬件连接,确保I2C引脚没有短路或损坏。


6. 初始化顺序问题



  • 如果在初始化I2C之前没有正确初始化相关的时钟或GPIO,可能会导致I2C无法正常工作。

  • 解决方法:确保在初始化I2C之前,先初始化相关的时钟和GPIO。


7. HAL库版本问题



  • 如果使用的HAL库版本存在bug,可能会导致hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:更新到最新的HAL库版本,或查看是否有相关的已知问题和修复。


8. I2C总线上的设备冲突



  • 如果I2C总线上有多个设备,并且设备地址冲突,可能会导致I2C总线无法正常工作。

  • 解决方法:检查I2C总线上的设备地址,确保没有冲突。


9. I2C总线上的拉电阻问题



  • 如果I2C总线上的上拉电阻值不合适,可能会导致I2C信号不稳定,从而使hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:检查I2C总线上的上拉电阻值,确保其符合I2C规范。


10. I2C操作未完成



  • 如果I2C操作未完成(例如,由于超时或错误),可能会导致hi2c2.state一直处于HAL_I2C_STATE_BUSY状态。

  • 解决方法:在I2C操作完成后,确保调用HAL_I2C_StateCallback或类似函数来更新状态。


示例代码


void MX_I2C2_Init(void)
{
    /* USER CODE BEGIN I2C2_Init 0 */
    /* USER CODE END I2C2_Init 0 */

    /* USER CODE BEGIN I2C2_Init 1 */
    /* USER CODE END I2C2_Init 1 */

    hi2c2.Instance = I2C2;
    hi2c2.Init.Timing = 0x10C0ECFF;  // 确保时序配置正确
    hi2c2.Init.OwnAddress1 = 0;
    hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    if (HAL_I2C_Init(&hi2c2) != HAL_OK)
    {
        // 初始化错误处理
        Error_Handler();
    }

    /* USER CODE BEGIN I2C2_Init 2 */
    /* USER CODE END I2C2_Init 2 */
}

如果以上方法仍然无法解决问题,建议逐步调试代码,检查每一步的操作是否正确执行,并查看是否有错误标志被设置。

举报

更多回帖

×
20
完善资料,
赚取积分