2022-04-18 01:28 AM
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 */
}
...........................
}
2022-04-18 06:22 AM
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?
2022-04-18 05:34 PM
Hi,
HAL_I2C_IsDeviceReady return HAL_OK.
I test I2C communication so Calling HAL_I2C_Master_Transmit_DMA at main() function after initialization.
2022-04-18 06:54 PM
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
2022-04-20 07:15 PM
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?
2022-04-21 07:01 AM
2022-04-21 08:18 PM
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.
2022-04-22 07:22 AM
2022-04-22 07:34 AM
2022-04-23 05:56 PM
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.