Getting started with I2C

Revision as of 10:17, 24 November 2022 by Registered User (→‎Examples I2C HAL functions)

This article explains what is the I2C and how to use it through examples

1. What is I2C?

I²C (Inter-Integrated Circuit) is a two-wire serial communication system used between integrated circuits which was originally created by Philips Semiconductors back in 1982.
The I2C is a multi-master, multi-slave, synchronous, bidirectional, half-duplex serial communication bus.

1.1. I2C Overview

  • SDA (Serial Data) is the line where master and slave send or receive the information (sequence of bits).
  • SCL (Serial Clock) is the line dedicated to the clock to synchronize the data flow.

i2c buq.png
SDA and SCL lines need to be pulled up with resistors. The value of these resistors depends on the bus length (the bus capacitance) and the transmission speed. The common value is 4.7kO. In any case, there are many guides to size them and we refer their reading to the more attentive reader.

1.2. I2C Modes

  • Standard-Mode (Sm) with a bit rate up to 100 kbit/s
  • Fast-Mode (Fm) with a bit rate up to 400 kbit/s
  • Fast-Mode Plus (Fm+) with a bit rate up to 1 Mbit/s

1.3. I2C Frame

i2c trame.png

-Start Condition (S)
-Stop Condition (P)
-Repeated Start (Restart) Condition (Sr)
-Acknowledge ACK (A)
-Not Acknowledge NACK (/A)

1.4. STM32 I2C Mode selectio

The interface can operate in one of the four following modes:

  • Slave transmitter
  • Slave receiver
  • Master transmitter
  • Master receiver

1.5. Main I2C HAL functions

I2C in STM32 can be done in 3 methods.
1. Blocking Mode
2. Interrupt Mode
3. DMA Mode

Blocking mode :
The communication is performed in the polling mode.The status of all data processing is returned by the same function after finishing transfer.
No-Blocking mode :
The communication is performed using Interrupts or DMA. These functions return the status of the transfer startup.
The end of the data processing will be indicated through the dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.

- Blocking Mode:

HAL_I2C_Master_Transmit()
HAL_I2C_Master_Receive()
HAL_I2C_Slave_Transmit()
HAL_I2C_Slave_Receive()
HAL_I2C_Mem_Write()
HAL_I2C_Mem_Read()

- Interrupt Mode:

HAL_I2C_Master_Transmit_IT()
HAL_I2C_Master_Receive_IT()
HAL_I2C_Slave_Transmit_IT()
HAL_I2C_Slave_Receive_IT()
HAL_I2C_Mem_Write_IT()
HAL_I2C_Mem_Read_IT()


- DMA Mode:

HAL_I2C_Master_Transmit_DMA()
HAL_I2C_Master_Receive_DMA()
HAL_I2C_Slave_Transmit_DMA()
HAL_I2C_Slave_Receive_DMA()
HAL_I2C_Mem_Write_DMA()
HAL_I2C_Mem_Read_DMA()

2. Objectives

  • Learn how to set I2C in different modes.
  • Communicate data between two NUCLEO-L476RG

3. How

  • Create the STM32CubeIDE project
  • Setup the I2C in STM32CubeIDE
  • Connect the boards

3.1. Create project in STM32CubeIDE

NUCLEO-L476RG Board

  • STM32L476RG board Pinout

File:pinout.png

Create NUCLEO-L476RG I2C project using STM32CubeIDE

  • Create a new STM32 project using STM32CubeIDE.
  • Select NUCLEO-L476RG MCU Selector.

File:STM32newproject.png

  • Project option

File:wiki.png

CubeMX I2C configuration

  • Open the STM32CubeMX project from the workspace

iocproject.png

  • Select I2C1
  • Select PB8: SCL and PB9: SDA for I2C1 if weren't selected

File:i2cinstance.PNG

Parameter Settings
Set the I2C Mode Standard Mode and the I2C Frequency at 100 KHz File:parameterset.PNG

  • GPIO Settings

- Tab>GPIO Settings
- Check Pull-UP
- Check GPIO speed
midlle



Interrupt Mode only
- Tab>NVIC settings
- Enable interrupt
nvic.png


DMA Mode only
- Tab>DMA settings
File:dmaa.PNG

- Add I2C1_TX for Master
DMA master.PNG

- Add I2C1_RX for Master
DMA slave.PNG


  • Save the STM32CubeMX project and generate the code.

Edit and compile the NUCLEO-L476RG I2C project

MASTER Board

  • Open main.c in Project Explorer / myproject / Src / main.c.
  • Insert the following lines between /* USER CODE BEGIN PV */ and /* USER CODE END PV */ :
/* USER CODE BEGIN PV */
/* Private variables 
uint8_t TX_Buffer [] = "A" ; // DATA to send
/* USER CODE END PV */
  • Insert the following lines between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ :

Blocking Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Master_Transmit(&hi2c1,20,TX_Buffer,1,1000); //Sending in Blocking mode
  HAL_Delay(100);
/* USER CODE END 2 */

Interrupt Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Master_Transmit_IT(&hi2c1,20,TX_Buffer,1); //Sending in Interrupt mode
  HAL_Delay(100);
/* USER CODE END 2 */

DMA Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Master_Transmit_DMA(&hi2c1,20,TX_Buffer,1); //Sending in DMA mode
  HAL_Delay(100);
/* USER CODE END 2 */
  • Click on Build button to compile the project.
  • Click in Debug button to run the software.

SLAVE Board

  • Open main.c in Project Explorer / myproject / Src / main.c.
  • Insert the following lines between /* USER CODE BEGIN PV */ and /* USER CODE END PV */ :
/* USER CODE BEGIN PV */
/* Private variables 
uint8_t RX_Buffer [1] ; // DATA to receive
/* USER CODE END PV */
  • Insert the following lines between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ :

Blocking Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Slave_Receive(&hi2c1 ,(uint8_t *)RX_Buffer, 1,1000); //Receiving in Blocking mode
  HAL_Delay(100);
/* USER CODE END 2 */

Interrupt Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Slave_Receive_IT(&hi2c1 ,(uint8_t *)RX_Buffer, 1); //Receiving in Interrupt mode
  HAL_Delay(100);
/* USER CODE END 2 */

DMA Mode

/* USER CODE BEGIN 2 */
  HAL_I2C_Slave_Receive_DMA(&hi2c1 ,(uint8_t *)RX_Buffer, 1); //Receiving in DMA mode
  HAL_Delay(100);
/* USER CODE END 2 */
  • Click on Build button to compile the project.
  • Click in Debug button to run the software.

3.2. Project workspace

The following table shows the connection between 2 STM32 boards for using I2C bus. It requires only two wires.

NUCLEO-L476RG MASTER NUCLEO-L476RG SLAVE Pin description
PB8 PB8 SCL
PB9 PB9 SDA
GND GND Ground

File:workspace.PNG




[[category:Getting_started_with_STM32_system_peripherals | 15]]