通信协议是数字电子和嵌入式系统的组成部分。只要有多个微控制器和外围设备的接口,就必须使用通信协议来交换大量数据。有多种类型的串行通信协议可用。RS485 是串行通信协议之一,用于工业项目和重型机械。
本教程是关于在 STM32F103C8 微控制器中使用RS-485 串行通信。
在本教程中,Master STM32F103C8 具有三个按钮,用于通过使用 RS-485 串行通信来控制 Slave Arduino Uno 上的三个 LED 的状态。
RS-485 串行通讯
RS-485 是一种不需要时钟的异步串行通信协议。它使用一种称为差分信号的技术将二进制数据从一个设备传输到另一个设备。
那么这种差分信号传输方法是什么?
差分信号方法通过使用正负 5V产生差分电压来工作。它在使用两线时提供半双工通信,在使用四线时提供全双工通信。
通过使用这种方法:
RS-485 支持最高 30Mbps 的更高数据传输率。
与RS-232 协议相比,它还提供最大的数据传输距离。它传输的数据最大可达 1200 米。
RS-485 相对于 RS-232 的主要优点是具有单个主控的多个从站,而 RS-232 仅支持单个从站。
最多可以有 32 台设备连接到 RS-485 协议。
RS-485的另一个优点是不受噪声影响,因为它们使用差分信号方法进行传输。
RS-485 比 I2C 协议更快。
RS-485 模块可以连接到任何具有串行端口的微控制器。为了将 RS-485 模块与微控制器一起使用,需要一个名为5V MAX485 TTL 到 RS485 的模块,该模块基于 Maxim MAX485 IC,因为它允许在 1200 米的长距离上进行串行通信,并且它是双向的,半双工的数据传输速率为 2.5 Mbps。该模块需要 5V 的电压。
RS-485 引脚说明:
RS485模块具有以下特点:
工作电压:5V
板载MAX485芯片
RS485通信的低功耗
转换速率受限收发器
5.08mm间距2P端子
方便的 RS-485 通讯接线
芯片的所有引脚均已引出,可通过微控制器进行控制
板尺寸:44 x 14mm
将此模块与 STM32F103C8 和 Arduino UNO 一起使用非常容易。使用微控制器的硬件串行端口。STM32 和 arduino UNO 中的硬件串行引脚如下所示。
在 STM32F103C8 中:引脚 PA9 (TX) & PA10 (RX)
在 Arduino Uno 中:引脚 0 (RX) & 1 (TX)
编程也很简单,只需使用Serial.print()写入 RS-485 并使用 Serial.Read()从 RS-485 读取,并将 RS-485 的 DE 和 RE 引脚设为低电平以接收数据并设为高电平以将数据写入RS-485 总线。
所需组件
STM32F103C8
Arduino UNO
MAX485 TTL 到 RS485 转换器模块 - (2)
10K电位器
按钮 - 3
LED - 3
电阻器
面包板
连接电线
电路原理图
在本教程中,STM32F103C8 用作带有一个 RS-485 模块的 Master,而 Arduino UNO 用作带有另一个 RS-485 模块的 Slave。
RS-485 和 STM32F103C8 (Master) 之间的电路连接:
STM32F103C8 带三个按钮:
三个带有三个 10k 下拉电阻的按钮连接到 STM32F103C8 的引脚 PA0、PA1、PA2。
RS-485 和 Arduino UNO (Slave) 之间的电路连接:
使用三个 LED,其中电阻为 330 欧姆的 LED 的阳极连接到 Arduino UNO 的引脚 4、7、8,LED 的阴极连接到 GND。
为 RS485 串行通信编程 STM32F103C8 和 Arduino UNO
Arduino IDE 用于开发和编程两个板,即 STM32 和 Arduino UNO。但请确保您已从Tools-》Port和 Board 从Tools-》Board中选择了相应的 PORT 。如果您发现任何困难或疑问,请参考在 ARDUINO IDE 中对您的 STM32 进行编程。本教程的编程包括两部分,第一部分用于 STM32F103C8(主),另一部分用于 Arduino UNO(从)。下面将一一解释这两个代码。
STM32F103C8 作为主控
在主端,读取按钮的状态,然后通过 STM32F103C8 的硬件串行端口 1(PA9、PA10)将这些值串行写入 RS-485 总线。到目前为止,也不需要外部库。Arduino 具有串行通信所需的所有库。
使用硬件串行引脚(PA9、PA10)以 9600 的 buadrate 开始串行通信。
Serial1.开始(9600);
读取 STM32F103C8 的 PA0、PA1、PA2 引脚上的按钮状态,并将它们存储在变量 button1val、button2val、button3val 中。如果按下按钮,则值为 HIGH,未按下时值为 LOW。
int button1val = digitalRead(button1); int button2val = digitalRead(button2); int button3val = digitalRead(button3);
在将按钮值发送到串口之前,RS-485 的 DE 和 RE 引脚应为高电平,连接到 STM32F103C8 的引脚 PA3(使引脚 PA3 为高电平):
数字写入(启用引脚,高);
接下来将这些值放入串行端口并根据按下哪个按钮发送值,使用 if else 语句并在按下按钮时发送相应的值。
如果按下第一个按钮,则条件匹配并将值“1”发送到连接 Arduino UNO 的串行端口。
if (button1val == HIGH) { int num1 = 1; Serial1.println(num1); }
类似地,当按下按钮 2 时,值 2 通过串行端口发送,当按下按钮 3 时,值 3 通过串行端口发送。
否则 if (button2val == HIGH) { int num2 =2; Serial1.println(num2); } else if (button3val == HIGH) { int num3 =3; Serial1.println(num3); }
当没有按下按钮时,值 0 被发送到 Arduino Uno。
否则 { int num = 0; Serial1.println(num); }
这样就完成了将 STM32 配置为主设备的编程。
Arduino UNO 作为奴隶
在从端,Arduino UNO 接收从主 STM32F103C8 发送的整数值,该整数值可在连接 RS-485 模块的 Arduino UNO (P0, 1) 的硬件串行端口获得。
只需读取值并存储在变量中。根据接收到的值,连接到 Arduino GPIO 的相应 LED 会打开或关闭。
要从主机接收值,只需将 RS-485 模块的 DE 和 RE 引脚设为LOW。所以 Arduino UNO 的 pin-2 (enablePin) 被设为低电平。
数字写入(启用引脚,低);
现在只需读取串行端口上可用的整数数据并将它们存储在一个变量中。
int 接收 = Serial.parseInt();
根据接收到的值,即 (0, 1, 2, 3),三个 LED 中的相应一个被打开。
if (receive == 1) //根据收到的值相应的 LED 打开或关闭 { digitalWrite(ledpin1,HIGH); } else if (receive == 2) { digitalWrite(ledpin2,HIGH); } else if (receive == 3) { digitalWrite(ledpin3,HIGH); } else { digitalWrite(ledpin1,LOW); 数字写入(ledpin2,低); 数字写入(ledpin3,低); }
这样就完成了将 Arduino UNO 编程和配置为从设备。这也完成了 Arduino UNO 和 STM32 的完整配置。本教程末尾附有工作视频和所有代码。
测试 STM32F103C8 和 Arduino UNO 之间的 RS485 通信:
1. 当按下连接到 Master STM32 的 Push button-1 时,连接到 Slave Arduino 的 LED 1 亮起。
2. 按下连接到 Master STM32 的 Push button-2 时,连接到 Slave Arduino 的 LED 2 亮起。
3. 同样,当按下按钮 3 时,LED 3 打开连接到从 Arduino。
主码:STM32F103C8
//STM32F103C8和Arduino Uno之间的RS-485串行通信
#define button1 PA0
#define button2 PA1
#define button3 PA2
#define enablePin PA3
void setup()
{
Serial1.begin(9600); // 在串行 1 端口 PA9、PA10 以波特率 9600 开始串行通信
pinMode(enablePin, OUTPUT);
pinMode(按钮1,输入);
pinMode(按钮2,输入);
pinMode(按钮3,输入);
延迟(10);
数字写入(启用引脚,高);//(总是高,因为 Master 向 Slave 写入数据)
}
无效循环()
{
int button1val = digitalRead(button1);//读取Push Button的状态
int button2val = digitalRead(button2);
int button3val = digitalRead(button3);
if (button1val == HIGH)
{
int num1 = 1;
Serial1.println(num1); //发送按钮值 1 if HIGH (Pressed)
}
else if (button2val == HIGH)
{
int num2 =2;
Serial1.println(num2); //发送按钮值 2 if HIGH (Pressed)
}
else if (button3val == HIGH)
{
int num3 =3;
Serial1.println(num3); //发送按钮值 3 if HIGH (Pressed)
}
else
{
int num = 0;
Serial1.println(num); //如果没有按下任何按钮,则发送 0
}
delay(50);
}
从机代码:Arduino UNO:
//STM32F103C8 和 Arduino Uno 之间的 RS-485 串行通信
#define enablePin 2
#define ledpin1 4
#define ledpin2 7
#define ledpin3 8
无效设置()
{
序列.开始(9600);// 以波特率 9600 开始串行通信
pinMode(ledpin1,OUTPUT);
pinMode(ledpin2,输出);
pinMode(ledpin3,输出);
pinMode(enablePin, 输出);
延迟(10);
数字写入(启用引脚,低);//(引脚 8 始终为低电平以接收来自主机的值)
}
无效循环()
{
while (Serial.available()) //当串口有数据时,这个循环执行
{
int receive = Serial.parseInt(); // 读取从 STM32 发送的整数值
if (receive == 1) //根据接收到的值相应的 LED 打开或关闭
{
digitalWrite(ledpin1,HIGH);
}
else if (receive == 2)
{
digitalWrite(ledpin2,HIGH);
}
else if (receive == 3)
{
digitalWrite(ledpin3,HIGH);
}
else
{
digitalWrite(ledpin1,LOW);
数字写入(ledpin2,低);
数字写入(ledpin3,低);
}
}
}