cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Problem

Epsilon03
Associate II

I have 2 MCU, one is the STM32F401RE acting as master and the other is STM32G474RE acting as slave, I have kept both the controllers in open drain and pulled up, the slave address is 0x30<<1, I think the data is being transferred because on pressing the reset button on the master, the slave displays this over UART "SLAVE HAL I2C NOT READY" , live expression is not working for me so that was my other option. 

My master code is this

int main(void)
{
 
  HAL_Init();
 
  SystemClock_Config();
 
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART2_UART_Init();
 
  char outputBuffer[200];
  char errorBuffer[200];
  uint8_t errorTxBuffer[] ="Master Transmission Not Complete";
  uint8_t errorTxBuffer1[] ="HAL";
 
  do
   {
     /*##-2- Start the transmission process #####################################*/
     /* While the I2C in reception process, user can transmit data through
     "aTxBuffer" buffer */
     if(HAL_I2C_Master_Transmit_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, sizeof(aTxBuffer))!= HAL_OK)
     {
       /* Error_Handler() function is called in case of error. */
       Error_Handler();
     }
 
     /*##-3- Wait for the end of the transfer ###################################*/
     /*  Before starting a new communication transfer, you need to check the current
     state of the peripheral; if it�s busy you need to wait for the end of current
     transfer before starting a new one.
     For simplicity reasons, this example is just waiting till the end of the
     transfer, but application may perform other tasks while transfer operation
     is ongoing. */
     while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
     {
    sprintf(errorBuffer, " State: %s \r\n",errorTxBuffer);
    HAL_UART_Transmit(&huart2,errorTxBuffer,strlen((char*)errorTxBuffer),HAL_MAX_DELAY);
    HAL_Delay(500);
     }
 
     /* When Acknowledge failure occurs (Slave don't acknowledge its address)
     Master restarts communication */
   }
   while(HAL_I2C_GetError(&hi2c1) == HAL_I2C_ERROR_AF);
 
sprintf(outputBuffer, "DATA: %s \r", aTxBuffer);
HAL_UART_Transmit(&huart2,aTxBuffer,strlen((char*)aTxBuffer),HAL_MAX_DELAY);
HAL_Delay(500);
 
 
  /*##-4- Put I2C peripheral in reception process ############################*/
//   do
//   {
//     if(HAL_I2C_Master_Receive_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t *)aRxBuffer, sizeof(aRxBuffer)) != HAL_OK)
//     {
//       /* Error_Handler() function is called in case of error. */
//       Error_Handler();
//     }
//
//     /* When Acknowledge failure occurs (Slave don't acknowledge its address)
//     Master restarts communication */
//   }
//   while(HAL_I2C_GetError(&hi2c1) == HAL_I2C_ERROR_AF);
// sprintf(errorBuffer, "Error: %s \r\n",errorTxBuffer1);
// HAL_UART_Transmit(&huart2,errorTxBuffer1,strlen((char*)errorTxBuffer1),HAL_MAX_DELAY);
// HAL_Delay(500);
 
}
 
My slave code is this 
int main(void)
{
 
  HAL_Init();
 
 
  SystemClock_Config();
 
 
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_LPUART1_UART_Init();
 
  char outputBuffer[200];
  char errorBuffer[200];
  uint8_t errorRxBuffer[] ="SLAVE HAL I2C NOT READY";
  uint8_t errorRxBuffer1[] ="SLAVE HAL NOT OK";
  uint8_t errorRxBuffer2[] ="SLAVE RUN";
 
 
 
  while (1)
  {
  if(HAL_I2C_Slave_Receive_IT(&hi2c1, (uint8_t *)aRxBuffer, sizeof(aRxBuffer)) != HAL_OK)
    {
      /* Transfer error in reception process */
sprintf(errorBuffer, "Error: %s \r\n",errorRxBuffer1);
HAL_UART_Transmit(&hlpuart1,errorRxBuffer1,strlen((char*)errorRxBuffer1),HAL_MAX_DELAY);
HAL_Delay(500);
      Error_Handler();
    }
 
    /*##-3- Wait for the end of the transfer ###################################*/
    /*  Before starting a new communication transfer, you need to check the current
        state of the peripheral; if it�s busy you need to wait for the end of current
        transfer before starting a new one.
        For simplicity reasons, this example is just waiting till the end of the
        transfer, but application may perform other tasks while transfer operation
        is ongoing. */
    while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
    {
    sprintf(errorBuffer, "Error: %s \r\n",errorRxBuffer);
    HAL_UART_Transmit(&hlpuart1,errorRxBuffer,strlen((char*)errorRxBuffer),HAL_MAX_DELAY);
    HAL_Delay(500);
    }
    //aRxBuffer[sizeof(aRxBuffer) - 1] = '\0';
    /////////////////////////////////////////////////////////////////////////////////////
sprintf(errorBuffer, "Error: %s \r\n",errorRxBuffer2);
HAL_UART_Transmit(&hlpuart1,errorRxBuffer2,strlen((char*)errorRxBuffer2),HAL_MAX_DELAY);
HAL_Delay(500);
///////////////////////////////////////////////////////////////////////////////////
sprintf(outputBuffer, "DATA: %s \r", aRxBuffer);
HAL_UART_Transmit(&hlpuart1,aRxBuffer,strlen((char*)aRxBuffer),HAL_MAX_DELAY);
HAL_Delay(500);
//     /*##-4- Start the transmission process #####################################*/
//     /* While the I2C in reception process, user can transmit data through
//        "aTxBuffer" buffer */
//     if(HAL_I2C_Slave_Transmit_IT(&I2cHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
//     {
//       /* Transfer error in transmission process */
//       Error_Handler();
//     }
 
  }
 
}
 
I have attached both codes. Please help me out since i am trying to figure this out for the past week 
4 REPLIES 4
Pierre_Paris
ST Employee

Hello @Epsilon03,

I quickly looked at your code, here is a list of suggestions/questions for you: 

  • What displays the master over UART ? Run your Master.c in debug mode to verify the address is well acknowledge and to check the transmission. 
  • What is the value of aRxBuffer once the code ended ? You can  also display it via UART.
  • Are you using OpenOCD ? It does not support Live expressions. You need to switch the debug probe to either ST-Link GDB server or J-Link, they both support the feature.
  • It might also be a synchronization issue, try to add a little delay to make sure the master transmits once the slave is ready.

Best Regards,

Pierre

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.

TDK
Guru
HAL_I2C_Slave_Receive_IT is non-blocking. If you want to wait for it to complete, you will need to wait for the state to be HAL_I2C_STATE_READY.
 
You almost do this, except you output an error if it's not ready, hence your complaint about it outputting "SLAVE HAL I2C NOT READY".
 
I'd suggest getting it up and running with blocking functions first, then graduate to *_IT functions.
 
If you feel a post has answered your question, please click "Accept as Solution".
Epsilon03
Associate II

@Pierre_Paris @TDK, I got the live expression working, basically for some reason it was disabled and now I have set it to the highest level of debugging, I also realized that the code is working, once the live expressions allowed me to see what is inside the slave receiving variable.

 Also @TDK the "Slave HAL I2C NOT Ready" is only printing on resetting my master board or the slave board.  

However there is one issue still remaining, I cannot display the data I received on my slave device, on UART. It's not exiting loop, probably due to the non-blocking feature like TDK mentioned, how do I get around that? 

Edit: The data I was sending was bigger than the rxBuffer so the program was waiting for the complete data to be transferred, on shortening the data, UART started displaying the Data . 

Thanks for all the help!! @TDK @Pierre_Paris

Pierre_Paris
ST Employee

Hello @Epsilon03,

The problem must be with I2C and not the UART. I think you aren't exiting the loop because you're sending aTxBuffer with a size of 150 uint8_t but you declare aRxBuffer with a size of 100. The master wait an acknowledge from slave and don't go back in the ready state. The master never terminates the transmission with a STOP condition.

Can you please fix it and tell me if it still gets stuck ? 

Best Regards,

Pierre

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.