Skip to main content
ausera uirwaij
Associate III
April 18, 2022
Question

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.

  • April 18, 2022
  • 13 replies
  • 3067 views
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 */
 }
 
...........................
}

This topic has been closed for replies.

13 replies

TDK
April 18, 2022

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""."
ausera uirwaij
Associate III
April 19, 2022

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
April 19, 2022

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

ausera uirwaij
Associate III
April 21, 2022

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

Otavio Borges
Associate III
April 21, 2022
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​
Piranha
Principal III
April 24, 2022

The yellow rectangle at the left side of image before sending the 0x36 is not a correct START sequence. Solve that problem first.