cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429's I2C cannot send data after calling HAL_I2C_Master_Transmit_DMA, Then both the SDA and SCL switch high level to low? it always return HAL_I2C_STATE_BUSY_TX.

ausera uirwaij
Associate III
HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
{
  if(hi2c->State == HAL_I2C_STATE_READY)
  {
    if((pData == NULL) || (Size == 0))
    {
      return  HAL_ERROR;
    }
 
    /* Wait until BUSY flag is reset */
    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG) != HAL_OK)
    {
      return HAL_BUSY;
    }
 
    /* Process Locked */
    __HAL_LOCK(hi2c);
    
    /* Disable Pos */
    hi2c->Instance->CR1 &= ~I2C_CR1_POS;
 
    hi2c->State = HAL_I2C_STATE_BUSY_TX;
    hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
 
    hi2c->pBuffPtr = pData;
    hi2c->XferSize = Size;
    hi2c->XferCount = Size;
 
    /* Set the I2C DMA transfer complete callback */
    hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
 
    /* Set the DMA error callback */
    hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
 
    /* Enable the DMA Stream */
    HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->DR, Size);
 
    /* Send Slave Address */
    if(I2C_MasterRequestWrite(hi2c, DevAddress, I2C_TIMEOUT_FLAG) != 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;
      }
    }
 
    /* Enable DMA Request */
    hi2c->Instance->CR2 |= I2C_CR2_DMAEN;
 
    /* Clear ADDR flag */
    __HAL_I2C_CLEAR_ADDRFLAG(hi2c);
 
    /* Process Unlocked */
    __HAL_UNLOCK(hi2c);
 
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
 
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2cHandle->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */
 
  /* USER CODE END I2C1_MspInit 0 */
 
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PB8     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = CS_PIN_I2C1_SCL_DPSENSOR_Pin|CS_PIN_I2C1_SDA_DPSENSOR_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
 
    /* I2C1 DMA Init */
    /* I2C1_RX Init */
    hdma_i2c1_rx.Instance = DMA1_Stream0;
    hdma_i2c1_rx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_i2c1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_rx);
 
    /* I2C1_TX Init */
    hdma_i2c1_tx.Instance = DMA1_Stream6;
    hdma_i2c1_tx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_i2c1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c1_tx);
 
  /* USER CODE BEGIN I2C1_MspInit 1 */
 
  /* USER CODE END I2C1_MspInit 1 */
  }
 
...........................
}

13 REPLIES 13
TDK
Guru

HAL_I2C_STATE_BUSY_TX indicates the previous transaction is not complete.

Showing where and how you call HAL_I2C_Master_Transmit_DMA would be more insightful than showing HAL code. Don't call within an interrupt, wait for previous transaction to complete, ensure arrays are within DMA accessible region.

Does HAL_I2C_IsDeviceReady return HAL_OK?

If you feel a post has answered your question, please click "Accept as Solution".

Hi,

HAL_I2C_IsDeviceReady  return HAL_OK.

I test I2C communication so Calling HAL_I2C_Master_Transmit_DMA at main() function after initialization.

Otavio Borges
Associate III

SCL SDA driving low can be master waiting from slave ACK. Slaves acknowledge the master by setting SDA to high. Are both pins set as Open Drain? Try tweaking line pullups, if those are too weak the communication sometimes doens't work

Hi, @Otavio Borges​ 

both SCL SDA are pullup by 1.5Kohm resister to 3.3V. I attached my I2C captures , it seems receiving no ACK bit from slave device after master device sending 0x7C. isn't it?0693W00000LyXsjQAF.png

Are all those from the same slave?
The two first ACK seems good, but there's no response from 0x7C, are you sending one too many bytes to the slave?
Double check the slave's datasheet to make sure you are sending the correct data​

yes, those are sending to one slave. the slave address is before 0x36,I send 0x36,0x7C, then sending another two bytes according to slave device datasheet.

it should be there's no response from SLAVE devce since 0x7C? I agree with this, but the the slave supplier disagree this and they think it's STM32F429's bug even though they couldn't point out where is bug.

Well, couple of things you can try​:
- Is 0x7C a read or write command? On the capture you send this is a
write sequence (on first byte, last bit before ACK. 0 is writing, 1 is
read). If 0x7c is only read the slave shouldn't respond;​
- 1.5k might be too much for your slave to pull down, try other bigger
pullups, like 4.7k and 10k
Another thing:
The default is for i2c commands to reply with ACK after each byte. So there should be one after 0x7C, unless the slave manufacturer specifies otherwise. Do you have problems trying other commands to the slave? If you do you need to check your wiring/master i2c configuration.
I see on your capture that there's something on the line before. Does the slave asks for a repeated start before a new command? Are you generating such on the master?

Do your think 1.5k is too much so that slave cannot set ACK bit ? the capture shows there is one ACK bit set by slave after master sending 0x36, so may be the resistance is OK.

>> . Does the slave asks for a repeated start before a new command? Are you generating such on the master?

where can you see there are repeated start ? I just send command 0x367c.