cancel
Showing results for 
Search instead for 
Did you mean: 

Connecting Raspberry PI to STM32F105xx via I2C.

SSoko
Associate II

Hi,

I am trying to connect raspberry Pi with STM32 via I2C.. for 2 weeks now.. going to the specifics: RPI3 is a master, STM32 is a slave, I use HAL library and CubeMX. All communication should be the simplest possible. I want to send / receive one byte - nothing more. I have connected a logic analyzer and UART console for debugging purposes.

Maybe I'll show my code first.

Init I2C:

/* I2C2 init function */
void MX_I2C2_Init(void)
{
  hi2c2.Instance = I2C2;
  hi2c2.Init.ClockSpeed = 62500;
  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c2.Init.OwnAddress1 = 32;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
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    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA 
    */
    GPIO_InitStruct.Pin = SCL_EEPROM_Pin|SDA_EEPROM_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
  /* USER CODE BEGIN I2C1_MspInit 1 */
 
  /* USER CODE END I2C1_MspInit 1 */
  }
  else if(i2cHandle->Instance==I2C2)
  {
  /* USER CODE BEGIN I2C2_MspInit 0 */
 
  /* USER CODE END I2C2_MspInit 0 */
  
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C2 GPIO Configuration    
    PB10     ------> I2C2_SCL
    PB11     ------> I2C2_SDA 
    */
    GPIO_InitStruct.Pin = SCL_RP3_Pin|SDA_RP3_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* I2C2 clock enable */
    __HAL_RCC_I2C2_CLK_ENABLE();
 
    /* I2C2 interrupt Init */
    HAL_NVIC_SetPriority(I2C2_EV_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
    HAL_NVIC_SetPriority(I2C2_ER_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C2_ER_IRQn);
  /* USER CODE BEGIN I2C2_MspInit 1 */
 
  /* USER CODE END I2C2_MspInit 1 */
  }
}

All Callbacks:

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
	debug_tx("HAL_I2C_AddrCallback\r\n");
 
	UNUSED(hi2c);
	//UNUSED(TransferDirection);
	UNUSED(AddrMatchCode);
 
	if(TransferDirection)
	{
		RPI_State = API_RPI_TO_STM;
		debug_tx("DIR: RPI_TO_STM\r\n");
	}
	else
	{
		RPI_State = API_STM_TO_RPI;
		debug_tx("DIR: STM_TO_RPI\r\n");
	}
}
 
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
	/* Prevent unused argument(s) compilation warning */
	UNUSED(hi2c);
 
	debug_tx("HAL_I2C_ListenCpltCallback\r\n");
 
	if(RPI_State == API_RPI_TO_STM)
	{
		if (HAL_I2C_Slave_Receive_IT(&hi2c2, rx_buf, 1) != HAL_OK)
		{
			Error_Handler();
		}
	}
	else if(RPI_State == API_STM_TO_RPI)
	{
		lcd_string(4, 0, "SLAVE TX 1 ");
		if (HAL_I2C_Slave_Transmit_IT(&hi2c2, tx_buf, 1) != HAL_OK)
		{
			Error_Handler();
			lcd_string(5, 0, "SLAVE TX ER");
		}
	}
}
 
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	debug_tx("HAL_I2C_SlaveTxCpltCallback\r\n");
}
 
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	debug_tx("HAL_I2C_SlaveRxCpltCallback\r\n");
 
	lcd_hex(5, 0, rx_buf[0]);
	HAL_I2C_EnableListen_IT(&hi2c2); // Restart
}
 
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
	debug_tx("Error_Handler\r\n");
 
  /* USER CODE END Error_Handler_Debug */
}

When RPI sends:

0690X00000BvV84QAF.png

in the console I can see:

0690X00000BvV89QAF.png

Doesn't enter "HAL_I2C_SlaveRxCpltCallback". If RPI sends an identical frame a second time then it goes into "HAL_I2C_SlaveRxCpltCallback".

0690X00000BvV8EQAV.png

Byte reception works every second time.

When I want to send some byte to RPI3 it's even worse. The frame looks like this:

0690X00000BvV8JQAV.png

From RPI's point of view, I'm only sending an address and waiting for 1 byte. I have no idea why STM sends these 2 bytes back. When we look at the console:

0690X00000BvV8OQAV.png

You can see that it enters only the "HAL_I2C_AddrCallback". And it misreads the direction flag.

When I change "NoStretchMode" to DISABLE it's even worse. It is only better that it reads the direction flag correctly.

Do you have any idea what I'm doing wrong? Or maybe there are some bugs in HAL? I really got stuck. I will be veery grateful for any help.

Best regards,

Sebastian

10 REPLIES 10
jplee0707
Associate

I had the same problem and struggled with it for a week, so I can relate to you. Thank you for all, But i'm so confused because HAL_I2C_Enablelisten_IT function works only in listencpltcallback. In rxcpltcallback or addrcallback, it does not works. Its so confused, but I think it's either a bug or my mistake because I don't know the more complex code configuration. I wish please everyone who suffer from same question can come this site and share there idea to us.