首页 > 解决方案 > 为什么“HAL_I2C_Master_Transmit”在每个循环中写入 2 个字节的数据

问题描述

我正在为 stm32f4 (V1.7.1) 使用 HAL 库,并试图了解 HAL_I2C_Master_Transmit 的工作原理。该函数在 SDA 线上传输一个“主从”数据包。在发送从地址后的 stm32f4xx_hal_i2c.c 代码中,有一个循环 ( while(hi2c->XferSize > 0U)) 发送我们想要传输给从属的字节。这个循环一直工作到所有字节都传输完。但是有一个问题是“为什么函数要在每个循环中传输两个字节?” 循环 ( ) 中有一个 IF,if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U))它检查当前是否传输了前一个字节,然后发送下一个字节!我不知道在下一个循环中可以传输其他字节时存在这个IF的原因是什么?!

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t 
DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint32_t tickstart = 0x00U;

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  if(hi2c->State == HAL_I2C_STATE_READY)
  {
    /* Wait until BUSY flag is reset */
    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, 
I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK)
    {
      return HAL_BUSY;
    }

/* Process Locked */
__HAL_LOCK(hi2c);

/* Check if the I2C is already enabled */
if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
{
  /* Enable I2C peripheral */
  __HAL_I2C_ENABLE(hi2c);
}

/* Disable Pos */
hi2c->Instance->CR1 &= ~I2C_CR1_POS;

hi2c->State     = HAL_I2C_STATE_BUSY_TX;
hi2c->Mode      = HAL_I2C_MODE_MASTER;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;

/* Prepare transfer parameters */
hi2c->pBuffPtr    = pData;
hi2c->XferCount   = Size;
hi2c->XferOptions = I2C_NO_OPTION_FRAME;
hi2c->XferSize    = hi2c->XferCount;

/* Send Slave Address */
if(I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK)
{
  if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
  {
    /* Process Unlocked */
    __HAL_UNLOCK(hi2c);
    return HAL_ERROR;
  }
  else
  {
    /* Process Unlocked */
    __HAL_UNLOCK(hi2c);
    return HAL_TIMEOUT;
  }
}

/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);

while(hi2c->XferSize > 0U)
{
  /* Wait until TXE flag is set */
  if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
  {
    if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
    {
      /* Generate Stop */
      hi2c->Instance->CR1 |= I2C_CR1_STOP;
      return HAL_ERROR;
    }
    else
    {
      return HAL_TIMEOUT;
    }
  }

  /* Write data to DR */
  hi2c->Instance->DR = (*hi2c->pBuffPtr++);
  hi2c->XferCount--;
  hi2c->XferSize--;

  if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U))
  {
    /* Write data to DR */
    hi2c->Instance->DR = (*hi2c->pBuffPtr++);
    hi2c->XferCount--;
    hi2c->XferSize--;
  }

  /* Wait until BTF flag is set */
  if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
  {
    if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
    {
      /* Generate Stop */
      hi2c->Instance->CR1 |= I2C_CR1_STOP;
      return HAL_ERROR;
    }
    else
    {
      return HAL_TIMEOUT;
    }
  }
}

/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;

hi2c->State = HAL_I2C_STATE_READY;
hi2c->Mode = HAL_I2C_MODE_NONE;

/* Process Unlocked */
__HAL_UNLOCK(hi2c);

return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

标签: i2cmaster-slavehalstm32f4

解决方案


推荐阅读