cancel
Showing results for 
Search instead for 
Did you mean: 

I2C communication between 2 STM32 MCUs

RSy.1
Associate III

Hello I am trying to learn I2C communication between 2 STM32F103C8 MCUs. MCU1 acts as the master and MCU2 acts as the slave. I am using CubeMX to configure the settings however I could not establish a link between the 2 MCUs. What I wanted to happen is that once I toggle a button connected to MCU1, the LED controlled by MCU2 should be enabled.

May I ask for your advice on the code below.

Master MCU1 code:
     
   //Enable Button_LED1 and transmit 0xFF data.  0x5A (0b01011010) Slave + Write (0)
        if(HAL_GPIO_ReadPin(BUTTON_LED1_GPIO_Port, BUTTON_LED1_Pin))
        {
            Buffer_I2C[0] = 0xFF;
            HAL_I2C_Master_Transmit(&hi2c1, 0x5A, Buffer_I2C, 1, 10);
        }
 
        //Disable Button_LED1 and transmit 0x00 data
        else
        {
            Buffer_I2C[0] = 0x00;
            HAL_I2C_Master_Transmit(&hi2c1, 0x5A, Buffer_I2C, 1, 10);
        } 
 
 
Slave MCU2 code:
 
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0x5B;                                                      //Slave + Read (1)
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 
    {           
        HAL_I2C_Slave_Receive(&hi2c1, Buffer_I2C, 1, 10);
        uint8_t data = Buffer_I2C[0];
        switch(data)
        {
            case 0xFF:
            HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
            break;
            
            case 0x00:
            HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
            break;
            
            default:
            break;
        }
    }

:

9 REPLIES 9
KnarfB
Principal III

The timeout for HAL_I2C_Slave_Receive is pretty short. Try with a longer timeout, even HAL_MAX_DELAY for a blocking read. And: check the return code.

Thank you for the hint. I tried changing the timeout longer to 50 but still it is not working. What is wrong with the return code?

Msd.1
Associate II

Is this your actual code?

if yes in you slave code your if statement should be

if (HAL_I2C_Init(&hi2c1) == HAL_OK)

RSy.1
Associate III

Sorry I forgot to tell that the If statement of the Slave is in the while(1) loop.

I did not change the line you mentioned as this was generated by CubeMX:

if (HAL_I2C_Init(&hi2c1) != HAL_OK)

Slave MCU2 code:
 
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0x5B;                                                      //Slave + Read (1)
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 
 
  while(1)
    {           
        HAL_I2C_Slave_Receive(&hi2c1, Buffer_I2C, 1, 10);
        uint8_t data = Buffer_I2C[0];
        switch(data)
        {
            case 0xFF:
            HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
            break;
            
            case 0x00:
            HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
            break;
            
            default:
            break;
        }
    }
}

You don't check it.

RSy.1
Associate III

I tried changing that line as you suggested but still not working.

TDK
Guru

> as this was generated by CubeMX:

Are you sure you didn't delete a call to Error_Handler? The code you posted looks edited from what CubeMX generates.

> HAL_I2C_Slave_Receive(&hi2c1, Buffer_I2C, 1, 10);

You should be looking at the return value and only processing the byte if it was actually received, as opposed to a timeout happening.

If you feel a post has answered your question, please click "Accept as Solution".
RSy.1
Associate III

No I did not edit anything else after I generated the code only the address of the slave. Thanks for the suggestions.

RShan.3
Associate

In master , you mentioned the slave address as 0x5A " HAL_I2C_Master_Transmit(&hi2c1, 0x5A, Buffer_I2C, 1, 10); "

In Slave , you mentioned the slave address as 0x5B " hi2c1.Init.OwnAddress1 = 0x5B; "

Actually, API will call 7-bit address and based on the Transmit & Receive functions, it will automatically append the R/nW bit. Yes, API "ll do it for you.

Just declare the " 7-bit address with right shift of 1 bit " throughout the program.