IOT

How to use I2C in STM32F103C8T6? STM32 I2C Tutorial

This tutorial will demonstrate I2C communication on an STM32 Blue Pill Board, which is based on the STM32F103C8T6 MCU. It takes at least one Master and one Slave to demonstrate I2C Communication. Therefore, I will be utilizing an STM32 MCU as the Master and an Arduino UNO as the Slave for this STM32 I2C Tutorial.

Introduction

Arduino has been used in a number of I2C-related projects so far. Let’s review the most important facts regarding the I2C Protocol in a hurry. Phillips created the Inter-Integrated Communication (I2C) standard as a straightforward two-wire serial communication protocol for exchanging information at low speeds between a microcontroller and various low-speed peripherals such as memory, timers, sensors, input/output (I/O), analog-to-digital converters (ADCs), digital-to-analog converters (DACs), and so on.

These days, nearly all microcontrollers come equipped with an I2C communication protocol straight out of the box. The Inter-Integrated Circuit (I2C) bus is a two-wire serial bus that can be used for communication between devices with different masters and slaves (there should be a common GND).

I2C Bus Layout

To drive logic HIGH on the bus, you’ll need to use a pull-up resistor on the two wires because they’re in open drain configuration.

When the master sends the START condition, which consists of a transition from HIGH to LOW on the SDA line and HIGH to LOW on the SCL line, the I2C communication begins. After the address, which is 7 bits long, comes a single bit that either indicates a read (‘1’) or a write (‘0’) operation.

I2C in STM32F103C8T6

I2C1 and I2C2 are the two I2C interfaces on the STM32F103C8T6 MCU. The I2C interfaces can operate at either the typical (100KHz) or the high-speed (400KHz) rate of communication.

STM32F103C8T6 Blue Pill Pin Layout

The pin mapping for both the I2C Interfaces in STM32 Blue Pill is mentioned below:

  • I2C1
    • SDA – PB7 or PB9
    • SCL – PB6 or PB8
  • I2C2
    • SDA – PB11
    • SCL – PB10

In this project, I will be using PB7 as SDA and PB6 as SCL.

I2C in Arduino

Slave devices for I2C communication are required, therefore common components like the DS1307 real-time clock IC, the PCF8574 general-purpose I/O expander IC, the AT24XX EEPROM IC, etc., can be substituted. In this project, however, I’ll be using an Arduino UNO as the I2C Slave Device, allowing the two devices to exchange data back and forth.

The I2C communication pins on the Arduino UNO are A4 (SDA) and A5 (SCL).

Components Required

  • STM32F103C8T6 MCU based STM32 Blue Pill Board
  • Arduino UNO
  • 2 x 5mm LEDs
  • 2 x 220Ω Resistors
  • 2 x 4.7KΩ Resistors
  • 2 x 10KΩ Resistors
  • 2 x Push Buttons
  • Connecting Wires
  • USB to UART Converter (if programming through UART)

Circuit Diagram

A schematic illustrating how to connect an STM32F103C8T6 to an Arduino via I2C Bus is provided below.

How to use I2C in STM32F103C8T6 Circuit Diagram

Connecting an STM32F103C8T6 to show how I2C works is a breeze because of how straightforward the pinouts are. Join PB7, the STM32’s SDA pin, to A4, the Arduino’s SDA pin. Similarly, link PB6 on the STM32 to the SCL pin on the Arduino, which is A5. Two 4.7K resistors are needed to get the SDA and SCL pins to a HIGH state.

Now, connect the push button and the 10K resistor to the PA0 pin of the STM32. Join the switch’s other terminal to 3.3V.

The similar procedure must be followed for Arduino, with Digital IO pin 6 being connected to a push button and the resistor value of 10K being used to bring the pin low (GND). Join the push button’s opposite end to a source of 5V.

LEDs on both boards can be used; in STM32, we use PC13, and in Arduino, we use Digital IO pin 13. Be sure to connect the GND pins of the Arduino and STM32 together.

Programming STM32 for I2C Communication

The STM32 is the device that serves as the I2C Master, so let’s begin there. Identify PC13 as the LED pin and PA0 as the button pin. The Arduino Slave Address must also be defined as 0x8. Start the I2C communication by setting the LED pin to OUTPUT and the button pin to INPUT.

The loop function should be broken down into two sub-functions: one to read the button pin and send the associated data, and another to read the incoming data and toggle the LED (based on the received data).

Code

#include <Wire.h>
#define LEDPIN PC13
#define BUTTONPIN PA0
#define SLAVEADDRESS 0x8
int sendData = 0;
void setup()
{
pinMode(BUTTONPIN, INPUT);
pinMode(LED, OUTPUT);
Wire.begin();
}
void loop()
{
int buttonValue = digitalRead(BUTTONPIN);
Wire.requestFrom(SLAVEADDRESS, 1);
byte readData = Wire.read();
if (readData == 1)
{
digitalWrite(LED,HIGH);
}
else
{
digitalWrite(LED,LOW);
}
if(buttonValue == HIGH)
{
sendData = 1;
}
else
{
sendData = 0;
}
Wire.beginTransmission(SLAVEADDRESS);
Wire.write(sendData);
Wire.endTransmission();
delay(500);
}

Programming Arduino for I2C Communication

Finally, Arduino, which must be set up as a slave device. Initialize the LED Pin to be an OUTPUT and the Button Pin to be an INPUT on Digital IO pins 13 and 6, respectively.

In order to initiate I2C communication with Arduino, we must use the slave address because Arduino is the slave. This address must correspond with the one specified in the master code (or vice versa), i.e. the slave address specified in the slave code must coincide with the master code’s specified address.

Keep in mind that with I2C Communication, the Slave has no control over the transfer and must instead respond to the Master’s instructions to read or write data.

As a result, if the master conducts a read operation, the Wire.onRequest function is invoked, which in turn invokes the supplied requestFun.

Similarly, if the master initiates a write operation, Wire.onReceive is called, which then calls receiveFun.

Code

#include <Wire.h>
#define LEDPIN 13
#define BUTTONPIN 6
#define SLAVEADDRESS 0x8
byte sendData = 0;
void setup()
{
pinMode(LED,OUTPUT);
Wire.begin(SLAVEADDRESS);
Wire.onReceive(receiveFun);
Wire.onRequest(requestFun);
}
void loop()
{
delay(100);
}
void receiveFun (int bytes)
{
byte recvData = Wire.read();
if (recvData == 1)
{
digitalWrite(LED,HIGH);
}
else
{
digitalWrite(LED,LOW);
}
delay(500);
}
void requestFun()
{
int buttonValue = digitalRead(buttonpin);
if (buttonValue == HIGH)
{
sendData = 1;
}
else
{
sendData = 0;
}
Wire.write(sendData);
}

Conclusion

Hope this blog helps you to understand How to use I2C in STM32F103C8T6? We, MATHA ELECTRONICS will come back with more informative blogs.

Leave a Reply

Your email address will not be published.