Почему «HAL_I2C_Master_Transmit» записывает 2 байта данных в каждом цикле - PullRequest
0 голосов
/ 30 января 2019

Я использую библиотеку HAL для stm32f4 (V1.7.1) и пытаюсь понять, как работает 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;
  }
}
...