在本教程中,我将向您展示如何在基于STM32蓝色药丸板的STM32F103C8T6单片机中使用I2C。演示I2C通信,我们至少需要一个主和一个从。因此,在这个STM32 I2C教程中,我将使用一个STM32 MCU作为主,一个Arduino UNO作为从。
简介
我们已经看到了几个用Arduino实现的I2C通信相关项目。让我们快速回忆一下关于I2C协议的一些关键信息。I2C是Inter Integrated Communication的缩写,是由Phillips公司开发的一种简单的双线串行通信协议,用于微控制器和一些低速外设如Memory、timer、sensor、IO、ADC、DAC等之间的短距离数据传输。
几乎所有现代微控制器都内置I2C通信协议系统。I2C是一种多主多从协议,只需要两条线,即SDA(串行数据)和SCL(串行时钟)进行通信(应该有一个公共GND)。
要记住的一件重要的事情是,两根电线是开漏配置,必须用适当的上拉电阻拉高,以便能够驱动总线上的逻辑高。
当主机启动START条件时,I2C通信开始,其中SDA线从高到低,而SCL线在高。后面是一个7位的从地址和一个单位表示读(' 1 ')操作或写(' 0 ')操作。
I2C在STM32F103C8T6
STM32F103C8T6单片机有两个I2C接口I2C1和I2C2。两个I2C接口都支持标准通信速度,如100KHz和快速通信速度,如400KHz。
STM32 Blue Pill中两个I2C接口的引脚映射如下:
- I2C1
- SDA - PB7或PB9
- SCL - PB6或PB8
- I2C2
- SDA - PB11
- sci - PB10
在这个项目中,我将使用PB7作为SDA,使用PB6作为SCL。
I2C的Arduino
由于我们需要一个I2C通信的从设备,我们可以使用任何著名的I2C设备,如DS1307 RTC IC, PCF8574 GPIO Expander IC, AT24XX EEPROM IC等。但是在这个项目中,我将使用Arduino UNO作为I2C Slave Device,这样我们就可以在STM32和Arduino之间进行来回通信。
对于Arduino中的I2C,引脚A4和A5是Arduino UNO中的I2C通信引脚,A4是SDA引脚,A5是SCL引脚。
组件的要求
- 基于STM32F103C8T6单片机的STM32蓝丸板
- Arduino UNO
- 2 × 5mm led
- 2 x 220Ω电阻
- 2 x 4.7KΩ电阻
- 2 x 10KΩ电阻
- 2个按钮
- 连接电线
- USB来UART转换器(如果通过UART编程)
线路图
下图是STM32F103C8T6中使用I2C通过I2C总线与Arduino通信的电路图。
连接解释
演示在STM32F103C8T6中使用I2C的连接非常简单。将STM32的SDA引脚PB7与Arduino对应的SDA引脚A4连接。同样,将STM32的SCL引脚PB6连接到Arduino对应的SCL引脚A5上。使用两个4.7KΩ电阻拉SDA和SCL引脚高。
现在,将一个按钮连接到STM32的PA0引脚,并使用10KΩ电阻将这个引脚拉到GND。将按钮的另一端连接到3.3V。
对Arduino重复同样的事情,即连接一个按钮到数字IO引脚6,并使用10KΩ电阻将该引脚拉到GND。将按钮的另一端连接到5V。
我们可以使用两个板上的led,它们分别连接到STM32中的PC13和Arduino中的Digital IO pin 13。确保Arduino和STM32的GND都是通用的。
用于I2C通信的STM32编程
首先,让我们从I2C主设备(即STM32)开始。定义LED引脚和按钮引脚为PC13和PA0。另外,将Arduino的从地址定义为0x8。初始化引脚,即LED引脚为输出,按钮引脚为输入,并开始I2C通信。
在循环函数中,将操作分为两部分,一是读取按钮引脚并发送相应的数据,另一部分是读取传入数据并打开或关闭LED(根据接收的数据)。
代码
# include < Wire.h >
#定义LEDPIN PC13
#定义BUTTONPIN PA0
#定义SLAVEADDRESS 0×8
int sendData = 0;
无效的设置()
{
pinMode (BUTTONPIN、输入);
pinMode(领导、输出);
Wire.begin ();
}
无效循环()
{
int buttonValue = digitalRead(BUTTONPIN);
电线。requestFrom (SLAVEADDRESS, 1);
byte readData = Wire.read();
if (readData == 1)
{
digitalWrite(领导、高);
}
其他的
{
digitalWrite(领导、低);
}
如果(buttonValue = =高)
{
sendData = 1;
}
其他的
{
sendData = 0;
}
Wire.beginTransmission (SLAVEADDRESS);
Wire.write (sendData);
Wire.endTransmission ();
延迟(500);
}
I2C通信Arduino编程
现在来到Arduino,它必须被配置为从设备。首先,定义LED引脚为数字IO引脚13,按钮引脚为数字IO引脚6,并分别初始化为OUTPUT和INPUT。
因为Arduino是从端,所以我们必须使用从端地址开始I2C通信。该地址必须与主码中定义的地址相同(或反之),即从码和主码中提到的从地址必须匹配。
另一件要记住的重要事情是,I2C通信中的从机不能发起传输,它只能遵从来自主机的读或写请求。
因此,如果主程序执行读操作,则Wire。onRequest函数被调用,该函数依次调用指定的requestFun。
类似地,如果写操作是由主机(即Wire)发起的。调用onReceive函数,该函数将调用receiveFun。
代码
# include < Wire.h >
#定义LEDPIN 13
#定义BUTTONPIN 6
#定义SLAVEADDRESS 0×8
字节sendData = 0;
无效的设置()
{
pinMode(领导、输出);
Wire.begin (SLAVEADDRESS);
Wire.onReceive (receiveFun);
Wire.onRequest (requestFun);
}
无效循环()
{
延迟(100);
}
void receiveFun (int bytes)
{
byte recvData = Wire.read();
if (recvData == 1)
{
digitalWrite(领导、高);
}
其他的
{
digitalWrite(领导、低);
}
延迟(500);
}
空白requestFun ()
{
int buttonValue = digitalRead(buttonpin);
if (buttonValue == HIGH)
{
sendData = 1;
}
其他的
{
sendData = 0;
}
Wire.write (sendData);
}
结论
基于STM32蓝丸板的STM32F103C8T6单片机中I2C的简单演示方案。STM32在I2C通信中充当主设备,而Arduino UNO用作从设备。
当按下主程序中的一个按钮(例如STM32)时,Arduino中的一个LED会亮起。同样,当按下Arduino中的按钮时,STM32中的LED会亮起。
一个回应
你需要做什么来告诉arduino哪些引脚是需要的I2C引脚,因为有不止一组引脚可以使用?