How to use I2C Communication in STM32 Microcontroller

Published  January 7, 2019   4
How to use I2C Communication in STM32 Microcontroller

In our previous tutorials, we have learned about SPI and I2C communication between two Arduino boards. In this tutorial we will replace one Arduino board with the Blue Pill board that is STM32F103C8 and will communicate with the Arduino board using I2C bus.

STM32 has more features than Arduino board. So it would be great to learn about communication between STM32 and Arduino by using SPI & I2C bus. In this tutorial, we will use I2C bus for communication between Arduino and STM32F103C8, and will learn about SPI bus in next tutorial. To know more about STM32 board, check other STM32 projects.

 

STM32F103C8 I2C Overview

Comparing I2C (Inter Integrated Circuits) in STM32F103C8 Blue Pill board with Arduino Uno, then we will see that Arduino has ATMEGA328 microcontroller in it, and STM32F103C8 has ARM Cortex- M3 in it. STM32 has Two I2C bus while Arduino Uno only has one I2C bus and STM32 is faster than Arduino.  

To learn more about I2C communication, refer our previous articles

 

I2C pins in STM32F103C8

SDA:  PB7 or PB9, PB11.

SCL:  PB6 or PB8, PB10.

STM32 Pin Details

 

I2C pins in Arduino

SDA: A4 pin

SCL: A5 pin

I2C in Arduino

 

Components Required

  • STM32F103C8
  • Arduino Uno
  • LED (2-Nos)
  • Push Button (2-Nos)
  • Resistors (4-Nos [10k-2 & 2.2k-2])
  • Breadboard
  • Connecting Wires

 

Circuit Diagram and Connections

Circuit Diagram for using I2C Communication in STM32 Microcontroller

 

The following table shows the connection between STM32 Blue Pill and Arduino Uno for using I2C bus. It requires only two wires.

STM32F103C8

Arduino

Pin Description

B7

A4

SDA

B6

A5

SCL

GND

GND

Ground

 

Important

  • Don’t forget to connect the Arduino GND and STM32F103C8 GND together.
  • Then connect a Pull down resistor of 10k to the push button pins of both the board separately.

 

In this STM32 I2C tutorial we will configure the STM32F103C8 as Master and Arduino as Slave. Both boards are attached with an LED & a push button separately.

To demonstrate I2C communication in STM32, we control the master STM32 LED by using slave Arduino push button value and control slave Arduino LED by using master STM32F103C8 push button value. These values are sent via I2C communication bus.

 

I2C Programming in STM32

The programming is similar to the Arduino code. The same <wire.h> library is used in programming STM32F103C8. It can be programmed using USB port without using FTDI programmer, to learn more about programming STM32 with Arduino IDE follow the link.

This tutorial has two programs one for master STM32 and other for slave Arduino. Complete programs for both the sides are given at the end of this project with a demonstration Video.

 

Master STM32 Programming Explanation

In Master STM32 let’s see what’s happening:

1. First of all we need to include the Wire library and softwire library for using I2C communication functions in STM32F103C8.

#include<Wire.h>    
#include<SoftWire.h>                      

 

2. In void setup()

  • We Start Serial Communication at Baud Rate 9600.
Serial.begin(9600);     

          

  • Next we start the I2C communication at pin (B6,B7)
Wire.begin();       

 

3. In Void loop()

  • First we get the data from the Slave Arduino so we use requestFrom() with the slave address 8 and we request one byte.
Wire.requestFrom(8,1);                           

 

The received value is read using Wire.read()

byte a = Wire.read();              

 

  • Depending upon the received value from slave the Master LED is turned ON or OFF by using digitalwrite at pin PA1 and also serial print is used to print value in serial monitor
if (a==1)                            
      { 
      digitalWrite(LED,HIGH);
      Serial.println("Master LED ON");
      }
    else
      {
      digitalWrite(LED,LOW);
      Serial.println("Master LED OFF");
      }

 

  • Next we need to read the status of the pin PA0 that is the master STM32 push button.
int pinvalue = digitalRead(buttonpin);

   

  •  Next send the pin value according to the logic, so we use if condition and then begin the transmission with slave arduino with 8 as address and then write the value according to the push button input value.
if(pinvalue==HIGH)                         
    {
      x=1;

    }   
  else
   {
      x=0; 

    }

Wire.beginTransmission(8);                           
Wire.write(x);                        
Wire.endTransmission();                 

 

Slave Arduino Programming Explanation

1. First of all we need to include the Wire library for using I2C communication functions.

#include<Wire.h>    

              

2. In void setup()

  • We Start Serial Communication at Baud Rate 9600.
Serial.begin(9600);                

 

  • Next start the I2C communication at pin (A4, A5) with slave address as 8. Here it is important to specify the slave address.                                         
 Wire.begin(8);       

 

Next we need to call Wire.onReceive function when Slave receives value from master and Wire.onRequest function call when Master request value from Slave.

Wire.onReceive(receiveEvent);       Wire.onRequest(requestEvent);           

 

3. Next we have two functions one for request event and one for receive event 

 

For request Event

When Master STM32 request value from slave this function will execute. This function does take input value from the Slave Arduino push button and send a byte (1 or 0) to Master STM32 according to push button value by using Wire.write().

void requestEvent()                         
  {
  int value = digitalRead(buttonpin);         

  if (value == HIGH)                            
{
    x=1;
  }
  else
  {
   x=0;
  }
  Wire.write(x);                           
 }

 

For Receive Event

When Master sends data to slave with slave address (8), this function will execute. This function reads the received value from master and store in a variable of type byte and then use if logic to turn slave LED ON or OFF depending upon the value received. If received value is 1 then LED turns ON and for 0 LED turns OFF.

void receiveEvent (int howMany)           
 {
  byte a = Wire.read();                     

  if (a == 1)                               

 {
   digitalWrite(LED,HIGH);
   Serial.println("Slave LED ON");

  }
  else
  {
    digitalWrite(LED,LOW);
    Serial.println("Slave LED OFF");
  }
  delay(500);
}

 

 

Output

1. When we press the push button at Master STM32, the LED connected to Slave Ardiono turns ON (White).

I2C Communication takes place in STM32

 

2. Now when we press the push button at Slave side, the LED connected to Master turns ON (Red) and when button is released LED turns OFF.

Connection between STM32 and Arduino using I2C

 

3. When both the push buttons pressed simultanewolsy, then both the LEDs glow at the same time, and remains ON until the buttons are pressed

Testing I2C Communication in STM32 Microcontroller

 

So this is how I2C communication takes place in STM32. Now you can interface any I2C sensor with STM32 board.

The complete coding for Master STM32 and Slave Arduino is given below with a demonstration video

Code

Master STM32 Code

//I2C Master Code (STM32F103C8)
//I2C Communication between STM32 and Arduino
//Circuit Digest

#include<Wire.h>                      
#include<SoftWire.h>                   //Library for I2C Communication functions

#define LED PA1
#define buttonpin PA0

int x = 0;

void setup() 

  
  Serial.begin(9600);                  //Begins Serial Communication at 9600 baud rate
  pinMode(buttonpin,INPUT);            //Sets pin PA0 as input 
  pinMode(LED,OUTPUT);                 //Sets PA1 as Output
  Wire.begin();                        //Begins I2C communication at pin (B6,B7)
}

void loop()

    Wire.requestFrom(8,1);               // request  bytes from slave arduino(8)
    byte a = Wire.read();                // receive a byte from the slave arduino and store in variable a
    
    if (a==1)                            //Logic to turn Master LED ON (if received value is 1) or OFF (if received value is 0)
      { 
      digitalWrite(LED,HIGH);
      Serial.println("Master LED ON");
      }
    else
      {
      digitalWrite(LED,LOW);
      Serial.println("Master LED OFF");
      }
  {
   
   int pinvalue = digitalRead(buttonpin);    //Reads the status of the pin PA0
   
  
  if(pinvalue==HIGH)                         //Logic for Setting x value (To be sent to slave Arduino) depending upon inuput from pin PA0
    {
      x=1;
    }
    
  else
   {
      x=0;
   }
  
  Wire.beginTransmission(8);                 // starts transmit to device (8-Slave Arduino Address)
  Wire.write(x);                             // sends the value x to Slave
  Wire.endTransmission();                    // stop transmitting
  delay(500);
  }
}     
  

Slave Arduino Code

//I2C Slave Code (Arduino)
//I2C Communication between STM32 and Arduino
//Circuit Digest

#include<Wire.h>                             //Library for I2C Communication functions

#define LED 7
#define buttonpin 2

byte x =0;
void setup() 

{
  Serial.begin(9600);                        //Begins Serial Communication at 9600 baud rate
  pinMode(LED,OUTPUT);                       //Sets pin 7 as output
  Wire.begin(8);                             // join i2c bus with its slave Address as 8 at pin (A4,A5)
  Wire.onReceive(receiveEvent);              //Function call when Slave Arduino receives value from master STM32
  Wire.onRequest(requestEvent);              //Function call when Master STM32 request value from Slave Arduino
}

void loop() 
{
  delay(100);
}

void receiveEvent (int howMany)              //This Function is called when Slave Arduino receives value from master STM32
{
  byte a = Wire.read();                      //Used to read value received from master STM32 and store in variable a
  
  if (a == 1)                                //Logic to turn Slave LED ON (if received value is 1) or OFF (if received value is 0)
  {
   digitalWrite(LED,HIGH);
   Serial.println("Slave LED ON");
   
  }
  else
  {
    digitalWrite(LED,LOW);
    Serial.println("Slave LED OFF");
  }
  delay(500);
  
}

void requestEvent()                            //This Function is called when Master STM32 wants value from slave Arduino
{
  int value = digitalRead(buttonpin);          //Reads the status of the pin 2   
  if (value == HIGH)                           //Logic to set the value of x to send to master depending upon input at pin 2
  {
    x=1;
  }
  else 
  {
    x=0;
  }
  Wire.write(x);                             // sends one byte of x value to master STM32
}
  
}

Video

Have any question realated to this Article?

Ask Our Community Members

Comments

I didn't see on this article or your other communication articles how to use the second I2C bus (I2C-2) in the same program as the first bus I2C-1 for the Blue Pill.  Would you please explain and/or provide code to show how to do it?  Thank you.

Hi everyone, in this example there aren't the pull-up resistor on I2C bus and a shift level device.

The STM32 works at 3.3V and Arduino works at 5V. 

I had some problems with this communication (I2C) and different type of voltage level.

I think it is necessary to put a shift level on I2C bus between Arduino board and STM32 board.

Bye