cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 I2C does not work

Jiri VLCEK
ST Employee
STM32 I2C does not work

Summary

This FAQ describes few tips related to I2C peripheral on STM32 devices.
 

1. I2C Hardware

1.1 Signal integrity

The I2C IO pins must be configured as open drain mode. The logic high level is driven by external pull-up resistor.


Typical value of I2C pull-up resistors (from practice) is between 2.2kOhm up to 10kOhm whereas customers implemented 100kOhm observing the wrong I2C bus timing. Internal pull-up resistor typical value is 40kOhm so external one must be populated.
The timing of I2C must be in line with I2C specification. You should measure and check the signal integrity on the bus.
 
115.png
(Figure 1: Pull-ups on I2C bus)

1.2 Filters

If you see unwanted glitches on I2C bus (coming from bad PCB design, Motor control application, ...), you can use digital and analog noise filters which are available between GPIO logic and I2C registers. 
  • Analog filter is compliant with the I2C specification which requires the suppression of spikes with a pulse width up to 50 ns. 
  • Digital filter allows spikes with a programmable length of 1 to 15 I2CCLK periods to be suppressed.
 
116.png
(Figure 2: I2C filters)

But BEWARE of filter setting. It must be set properly otherwise the filter could suppress common communication.


1.3 Timing:

Some STM32 devices have I2C timing register (I2C_TIMINGR) which can impact I2C communication. It must be set properly. Here is an application note with I2C timing specification and tips how to configure the register:
https://www.st.com/resource/en/application_note/dm00074956-i2c-timing-configuration-tool-for-stm32f3xxxx-and-stm32f0xxxx-microcontrollers-stmicroelectronics.pdf
CubeMX tool can do the computation automatically if you fill all required parameters. 
Tip how to fill Rise & Fall time in formula: Each PCB could have different Rise and Fall time because of different capacity of bus. You should measure these values on your real hardware and use it for the computation.
 


2. I2C Software

2.1 HAL library

I2C HAL library allows usage of I2C peripheral without deep knowledge of registers. Each CubeMX firmware pack (example: STM32Cube_FW_F4_V1.25.0) includes files:
stm32f4xx_hal_i2c.c/h
stm32f4xx_hal_i2c_ex.c/h
where you can find function for easy I2C usage. There are even examples in firmware pack which are available under ST evaluation boards. The examples show how to use the library’s function for Polling, Interrupt or DMA transfer. 
For Example:
STM32Cube_FW_F4_V1.25.2\Projects\STM32F4-Discovery\Examples\I2C
  • NVIC I2C interrupt must be enabled for using interrupt and DMA modes
117.png
 (Figure 3: I2C NVIC settings in CubeMX)
 

2.2 Register’s access

If you write your own I2C driver based on register access, you must always follow Reference Manual of STM32 device. There are figures "Transfer sequence" for each type of communication (master receiver, master transmitter, slave receiver, slave transmitter) with event description (EV). Each EV must be handled by the driver. Here is an example from STM32F407 - Reference manual :
 
118.png
 (Figure 4: Example of transfer sequence)
 

3. Errata sheet

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. Anyway, errata sheet is individual for each device. 
 

4. I2C Bootloader on STM32 devices

I2C protocol used in the STM32 bootloader is described in Application note AN4221:
https://www.st.com/resource/en/application_note/dm00072315-i2c-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf
 
Comments
熊大
Associate

I used STM32CubeIDE to generate I2C code. I wrote the following code:

 /* USER CODE BEGIN WHILE */

uint8_t Buf[] = {0x00, 0x00};

 while (1)

 {

  HAL_I2C_Master_Transmit(&hi2c1, hi2c1.Init.OwnAddress1, Buf, 2, 20);

  HAL_Delay(500);

  /* USER CODE END WHILE */

After enter to debugging mode, I step into "HAL_I2C_Master_Transmit" function. I found I2C always stuck at "HAL_BUSY".

Maybe you can give me some advise to debug it.

Thanks,

Frank

MFran.4
Senior

Why do you transmit to OwnAddress? try using another address or a real i2c peripheral (temperature sensor, oled display).

I suggest to create a topic elsewhere.

Jiri VLCEK
ST Employee

The flag HAL_BUSY is returned only in case that hi2c->State is not HAL_I2C_STATE_READY at the beginning of function. It would mean that previous execution of HAL_I2C_Master_Transmit() returned HAL_ERROR. I would recommend to check what flag is causing HAL_ERROR and take a look to I2C_ISR description in Reference Manual. It should provide a feedback what is wrong.

Version history
Last update:
‎2021-04-12 06:01 AM
Updated by: