【STM32】HAL库HAL_I2C_Transmit详解

Diagram中,上方为硬件自动执行,下方为软件控制的事件(EVx)

STM32 Master Transmit diagram

HAL_I2C_Master_Transmit

函数流程图


REF:3.HAL_I2C_Master_Transmit 函数解析

代码解析

代码解析对照STM32开发指南的Master Transmit Diagram进行讲解,由Diagram可见,对于7-bit master transmitter,其流程如下:

  1. 发送Start信号;
  2. EV5 事件;
  3. 发送从机7-bit地址(加上写指令),等待从机ACK;
  4. EV6 事件;
  5. EV8_1 事件;
  6. 不断发送DATA;
  7. EV8_2事件;
  8. 发送Stop信号。
    其中1~3I2C_MasterRequestWrite函数内实现:
static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart)
{
  /* Declaration of temporary variable to prevent undefined behavior of volatile usage */
  uint32_t CurrentXferOptions = hi2c->XferOptions;

  /* Generate Start condition if first transfer */
  if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME))
  {
    /* Generate Start */
    SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
  }
  else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX)
  {
    /* Generate ReStart */
    SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
  }
  else
  {
    /* Do nothing */
  }

  /* Wait until SB flag is set */
  if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)  //EV5
  {
    if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
    {
      hi2c->ErrorCode = HAL_I2C_WRONG_START;
    }
    return HAL_TIMEOUT;
  }

  if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)   // Send slave address
  {
    /* Send slave address */
    hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);     // 数据在DR寄存器会自动发送
  }
  else
  {
    /* Send header of slave address */
    hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress);

    /* Wait until ADD10 flag is set */
    if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK)
    {
      return HAL_ERROR;
    }

    /* Send slave address */
    hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress);
  }

  /* Wait until ADDR flag is set */
  if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)  // EV6 
  {
    return HAL_ERROR;
  }

  return HAL_OK;
}
  • EV5 事件对应为I2C_SR1→Bit0 SB位置1。当I2C Master发送START信号后,Bit0 SB会硬件置1,对应为EV5 事件。
  • EV6 事件对应为I2C_SR1→Bit1 ADDR位置1。当7-bit从机地址和从机匹配上,Bit0 ADDR 会硬件置1,对应为EV6 事件。
  • 在检查EV6 事件(ADDR flag is set)时,若失败,还会检查I2C_SR1→Bit1 AF 的状态,判断是哪种错误
  • 5对应为通过I2C_WaitOnTXEFlagUntilTimeout判断I2C_SR1→Bit1 TXE 是否为1

  • EV8_1 事件对应为当为I2C_SR1→Bit1 TXE 为1,此时Data Register,即I2C_DR为空,此时可向I2C_DR内写数据,I2C_DR内的数据会自动发送。
  • 7对应为通过__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET判断I2C_SR1→Bit1 BTF 是否为1

  • EV8_2 事件对应为当I2C_SR1→Bit1 BTF 为1,此时对应为In transmission when a new byte should be sent and DR has not been written yet (TxE=1),主机后续发送Stop,结束此次的I2C通信。
  • 作者:康

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【STM32】HAL库HAL_I2C_Transmit详解

    发表回复