I2C-связь на STM32 (STM32F103C8): обмен данными с Arduino

Перевод статьи How to use I2C Communication in STM32 Microcontroller (STM32F103C8) — Pramoth Thangavel, Circuit Digest.
В прошлых материалах мы разбирали связь по SPI и I2C между двумя платами Arduino. В этом руководстве мы заменим одну из Arduino платой Blue Pill (STM32F103C8) и наладим обмен с Arduino по шине I2C.
Обзор I2C в STM32F103C8#
Если сравнить I2C (Inter-Integrated Circuits) у STM32F103C8 Blue Pill и Arduino Uno: в Arduino стоит ATMEGA328, а в STM32F103C8 — ARM Cortex-M3. У STM32 две шины I2C, у Arduino Uno — одна, и STM32 быстрее.
Пины I2C у STM32F103C8#
- SDA: PB7, PB9 или PB11;
- SCL: PB6, PB8 или PB10.

Пины STM32F103C8.
Пины I2C у Arduino#
- SDA: пин A4;
- SCL: пин A5.

Пины I2C на Arduino: SDA (A4), SCL (A5).
Компоненты#
- STM32F103C8;
- Arduino Uno;
- светодиод — 2 шт.;
- кнопка — 2 шт.;
- резисторы — 4 шт. (10 кОм — 2, 2,2 кОм — 2);
- макетная плата;
- соединительные провода.
Схема и подключения#
В таблице ниже — соединения STM32 Blue Pill и Arduino Uno для шины I2C. Нужно всего два провода.
| STM32F103C8 | Arduino | Назначение |
|---|---|---|
| B7 | A4 | SDA |
| B6 | A5 | SCL |
| GND | GND | Земля |
Важно:
- обязательно соедините GND у Arduino и STM32F103C8;
- к пинам кнопок обеих плат подключите подтягивающие к земле резисторы 10 кОм.
В этом руководстве STM32F103C8 — мастер, Arduino — ведомый. К каждой плате отдельно подключены светодиод и кнопка. Мы управляем светодиодом мастера (STM32) кнопкой ведомого (Arduino) и наоборот — значения передаются по шине I2C.

Схема I2C-связи STM32 ↔ Arduino.
Программирование I2C на STM32#
Программирование похоже на код Arduino — используется та же библиотека <Wire.h>. STM32F103C8 можно прошивать через USB без FTDI-программатора.
Разбор кода мастера (STM32)#
- Подключаем библиотеки Wire и SoftWire.
#include<Wire.h>
#include<SoftWire.h>
- В
setup(): запускаем Serial на 9600 и начинаем I2C на пинах (B6, B7).
Serial.begin(9600);
Wire.begin();
- В
loop(): сначала запрашиваем данные у ведомого Arduino (адрес 8, один байт) и читаем полученное значение.
Wire.requestFrom(8,1);
byte a = Wire.read();
В зависимости от полученного значения зажигаем или гасим светодиод мастера (пин PA1). Затем читаем состояние кнопки мастера (PA0) и отправляем соответствующее значение ведомому.
Wire.beginTransmission(8);
Wire.write(x);
Wire.endTransmission();
Разбор кода ведомого (Arduino)#
Подключаем библиотеку Wire.
В
setup(): запускаем Serial, начинаем I2C с адресом ведомого 8 на пинах (A4, A5) и регистрируем обработчики событий приёма и запроса.
Wire.begin(8);
Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent);
- Обработчик запроса
requestEvent()вызывается, когда мастер запрашивает данные: читает кнопку ведомого и отправляет байт (1 или 0). Обработчик приёмаreceiveEvent()вызывается, когда мастер прислал данные: читает значение и зажигает/гасит светодиод ведомого.
Результат#
- При нажатии кнопки на мастере (STM32) загорается светодиод, подключённый к ведомому Arduino (белый).
- При нажатии кнопки на стороне ведомого загорается светодиод мастера (красный), а при отпускании — гаснет.
- При одновременном нажатии обеих кнопок оба светодиода горят вместе, пока кнопки удерживаются.
Так и работает I2C-связь на STM32 — теперь к плате можно подключить любой I2C-датчик.

Нажата кнопка мастера — загорается светодиод ведомого.

Нажата кнопка ведомого — загорается светодиод мастера.

Обе кнопки нажаты — оба светодиода горят.
Полный код#
Мастер (STM32)#
//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);
}
}
Ведомый (Arduino)#
//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
}