cancel
Showing results for 
Search instead for 
Did you mean: 

My I2C communication in DMA mode is not working properly

Mabou.1
Associate II

Hello,

I have developed two codes to test the I2C communication between a master device (STM32F411RE) and a slave device (also STM32F411RE) in DMA mode. The expected result is as follows: whenever there is a rising or falling edge interruption on GPIO_PIN_11 of the master device, it should send a TX buffer to the slave device. After receiving the buffer by the slave device, master device should enter the reception mode for I2C and wait for a response from the slave.

On the slave device, I have initially set it to the reception mode for I2C. Once the first buffer sent by the master is received by the slave, it waits for 1 seconds before switching to the transmission mode to send a response back to the master. I am using a button connected to GPIO pin 11 to generate the interruptions.

The result that I get is when I trigger the first interruption on the master device, it successfully sends the buffer to the slave, and the slave accurately receives the buffer. However, I am not receiving any response from the slave device afterward.

My master code

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
 
  /*for(int i = 1; i<20; i++){
	  ret = HAL_I2C_IsDeviceReady(&hi2c1, i, 3, 100);
	  if(ret == HAL_OK){
		  uint8_t address = i;
	  }
	  while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){
 
	  }
  }*/
  txbuffer[0] = 0x01;
  txbuffer[1] = 0xFF;
  txbuffer[2] = 0x05;
  txbuffer[3] = 0xFF;
  txbuffer[4] = 0xFF;
  txbuffer[5] = 0xFF;
  txbuffer[6] = 0xFF;
  txbuffer[7] = 0xFF;
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	  while (1)
	  {
	    /* USER CODE END WHILE */
 
		  if(RXflag == true){
			if(HAL_I2C_Master_Receive_DMA(&hi2c1, 16, rxbuffer, sizeof(rxbuffer)) != HAL_OK)
			{
				/* Transfer error in reception process */
				Error_Handler();
			}
			RXflag = false;
		  }
 
		  if(TXflag == true){
			if(HAL_I2C_Master_Transmit_DMA(&hi2c1, 16, txbuffer, sizeof(txbuffer)) != HAL_OK)
			{
				/* Transfer error in transmission process */
				Error_Handler();
			}
			TXflag = false;
		  }
	/* USER CODE BEGIN 3 */
	  }
  /* USER CODE END 3 */
}
 
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef*hi2c)
{
	RXflag = true;
}
 
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef*hi2c)
{
	TXflag = true;
}
 
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin){
	case GPIO_PIN_11:
		HAL_I2C_Master_Transmit_DMA(&hi2c1, 16, (uint8_t *)txbuffer, sizeof(txbuffer));
		break;
 
	case GPIO_PIN_12:
			break;
 
	default:
		break;
	}
}

My Slave code

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  HAL_I2C_MspInit(&hi2c1);
  /* USER CODE BEGIN 2 */
 
  if(HAL_I2C_Slave_Receive_DMA(&hi2c1, rxbuffer, sizeof(rxbuffer)) != HAL_OK)
  {
    /* Transfer error in reception process */
    Error_Handler();
  }
 
  txbuffer[0] = 11;
  txbuffer[1] = 12;
  txbuffer[2] = 13;
  txbuffer[3] = 14;
  txbuffer[4] = 15;
  txbuffer[5] = 16;
  txbuffer[6] = 17;
  txbuffer[7] = 18;
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	/* USER CODE END WHILE */
	  if(RXflag == true){
		if(HAL_I2C_Slave_Receive_DMA(&hi2c1, rxbuffer, sizeof(rxbuffer)) != HAL_OK)
		{
			/* Transfer error in reception process */
			Error_Handler();
		}
		RXflag = false;
	  }
 
	  if(TXflag == true){
		HAL_Delay(1000);
		if(HAL_I2C_Slave_Transmit_DMA(&hi2c1, txbuffer, sizeof(txbuffer)) != HAL_OK)
		{
			/* Transfer error in transmission process */
			Error_Handler();
		}
		TXflag = false;
	  }
 
	/* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	RXflag = true;
}
 
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	TXflag = true;
	if(rxbuffer[0] == 0x01)
	{
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
	}
}

5 REPLIES 5
Foued_KH
ST Employee

Hello @Mabou.1​ ,

Try to set breakpoint and debug your code. Take an oscilloscope to check the I2C_SDA and I2C_SCL behavior.

If you are facing some erratic behavior on STM32, do not forget to check Errata sheet of the device. There are few points related to I2C interface. 

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello,

I have observed that for the slave device to provide a response to the master, it needs to enter the transmission mode before the master device enters the reception mode. However, this poses a challenge for me because in my scenario, the slave device must respond after varying durations, such as 500ms or 2 seconds, depending on the specific data buffer received from the master.

Any ideas how can I get this work properly ?

 Run the Controller before run the Target, this will let a false startup phase on Target side

 as there is no high level on the bus, if the Target is started before the Controller.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

You can also check the I2C available examples on the CubeFW : STM32Cube_FW_F4_V1.27.1\Projects\STM32F410xx-Nucleo\Examples\I2C\I2C_TwoBoards_ComDMA

This example has been tested with STM32F4xx-Nucleo RevC board and can be easily tailored to any other supported device and development board. 

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Yes, I have already reviewed various examples, but I haven't found a solution that can fix my problem.