通信協(xié)議是數(shù)字電子和嵌入式系統(tǒng)的組成部分。只要有多個(gè)微控制器和外圍設(shè)備的接口,就必須使用通信協(xié)議來(lái)交換大量數(shù)據(jù)。有多種類型的串行通信協(xié)議可用。RS485 是串行通信協(xié)議之一,用于工業(yè)項(xiàng)目和重型機(jī)械。
本教程是關(guān)于在 STM32F103C8 微控制器中使用RS-485 串行通信。
在本教程中,Master STM32F103C8 具有三個(gè)按鈕,用于通過(guò)使用 RS-485 串行通信來(lái)控制 Slave Arduino Uno 上的三個(gè) LED 的狀態(tài)。
RS-485 串行通訊
RS-485 是一種不需要時(shí)鐘的異步串行通信協(xié)議。它使用一種稱為差分信號(hào)的技術(shù)將二進(jìn)制數(shù)據(jù)從一個(gè)設(shè)備傳輸?shù)搅硪粋€(gè)設(shè)備。
那么這種差分信號(hào)傳輸方法是什么?
差分信號(hào)方法通過(guò)使用正負(fù) 5V產(chǎn)生差分電壓來(lái)工作。它在使用兩線時(shí)提供半雙工通信,在使用四線時(shí)提供全雙工通信。
通過(guò)使用這種方法:
RS-485 支持最高 30Mbps 的更高數(shù)據(jù)傳輸率。
與RS-232 協(xié)議相比,它還提供最大的數(shù)據(jù)傳輸距離。它傳輸?shù)臄?shù)據(jù)最大可達(dá) 1200 米。
RS-485 相對(duì)于 RS-232 的主要優(yōu)點(diǎn)是具有單個(gè)主控的多個(gè)從站,而 RS-232 僅支持單個(gè)從站。
最多可以有 32 臺(tái)設(shè)備連接到 RS-485 協(xié)議。
RS-485的另一個(gè)優(yōu)點(diǎn)是不受噪聲影響,因?yàn)樗鼈兪褂貌罘中盘?hào)方法進(jìn)行傳輸。
RS-485 比 I2C 協(xié)議更快。
RS-485 模塊可以連接到任何具有串行端口的微控制器。為了將 RS-485 模塊與微控制器一起使用,需要一個(gè)名為5V MAX485 TTL 到 RS485 的模塊,該模塊基于 Maxim MAX485 IC,因?yàn)樗试S在 1200 米的長(zhǎng)距離上進(jìn)行串行通信,并且它是雙向的,半雙工的數(shù)據(jù)傳輸速率為 2.5 Mbps。該模塊需要 5V 的電壓。
RS-485 引腳說(shuō)明:
RS485模塊具有以下特點(diǎn):
工作電壓:5V
板載MAX485芯片
RS485通信的低功耗
轉(zhuǎn)換速率受限收發(fā)器
5.08mm間距2P端子
方便的 RS-485 通訊接線
芯片的所有引腳均已引出,可通過(guò)微控制器進(jìn)行控制
板尺寸:44 x 14mm
將此模塊與 STM32F103C8 和 Arduino UNO 一起使用非常容易。使用微控制器的硬件串行端口。STM32 和 arduino UNO 中的硬件串行引腳如下所示。
在 STM32F103C8 中:引腳 PA9 (TX) & PA10 (RX)
在 Arduino Uno 中:引腳 0 (RX) & 1 (TX)
編程也很簡(jiǎn)單,只需使用Serial.print()寫入 RS-485 并使用 Serial.Read()從 RS-485 讀取,并將 RS-485 的 DE 和 RE 引腳設(shè)為低電平以接收數(shù)據(jù)并設(shè)為高電平以將數(shù)據(jù)寫入RS-485 總線。
所需組件
STM32F103C8
Arduino UNO
MAX485 TTL 到 RS485 轉(zhuǎn)換器模塊 - (2)
10K電位器
按鈕 - 3
LED - 3
面包板
連接電線
電路原理圖
在本教程中,STM32F103C8 用作帶有一個(gè) RS-485 模塊的 Master,而 Arduino UNO 用作帶有另一個(gè) RS-485 模塊的 Slave。
RS-485 和 STM32F103C8 (Master) 之間的電路連接:
STM32F103C8 帶三個(gè)按鈕:
三個(gè)帶有三個(gè) 10k 下拉電阻的按鈕連接到 STM32F103C8 的引腳 PA0、PA1、PA2。
RS-485 和 Arduino UNO (Slave) 之間的電路連接:
使用三個(gè) LED,其中電阻為 330 歐姆的 LED 的陽(yáng)極連接到 Arduino UNO 的引腳 4、7、8,LED 的陰極連接到 GND。
為 RS485 串行通信編程 STM32F103C8 和 Arduino UNO
Arduino IDE 用于開(kāi)發(fā)和編程兩個(gè)板,即 STM32 和 Arduino UNO。但請(qǐng)確保您已從Tools-》Port和 Board 從Tools-》Board中選擇了相應(yīng)的 PORT 。如果您發(fā)現(xiàn)任何困難或疑問(wèn),請(qǐng)參考在 ARDUINO IDE 中對(duì)您的 STM32 進(jìn)行編程。本教程的編程包括兩部分,第一部分用于 STM32F103C8(主),另一部分用于 Arduino UNO(從)。下面將一一解釋這兩個(gè)代碼。
STM32F103C8 作為主控
在主端,讀取按鈕的狀態(tài),然后通過(guò) STM32F103C8 的硬件串行端口 1(PA9、PA10)將這些值串行寫入 RS-485 總線。到目前為止,也不需要外部庫(kù)。Arduino 具有串行通信所需的所有庫(kù)。
使用硬件串行引腳(PA9、PA10)以 9600 的 buadrate 開(kāi)始串行通信。
?
Serial1.開(kāi)始(9600);
?
讀取 STM32F103C8 的 PA0、PA1、PA2 引腳上的按鈕狀態(tài),并將它們存儲(chǔ)在變量 button1val、button2val、button3val 中。如果按下按鈕,則值為 HIGH,未按下時(shí)值為 LOW。
?
int button1val = digitalRead(button1); int button2val = digitalRead(button2); int button3val = digitalRead(button3);
?
在將按鈕值發(fā)送到串口之前,RS-485 的 DE 和 RE 引腳應(yīng)為高電平,連接到 STM32F103C8 的引腳 PA3(使引腳 PA3 為高電平):
?
數(shù)字寫入(啟用引腳,高);
?
接下來(lái)將這些值放入串行端口并根據(jù)按下哪個(gè)按鈕發(fā)送值,使用 if else 語(yǔ)句并在按下按鈕時(shí)發(fā)送相應(yīng)的值。
如果按下第一個(gè)按鈕,則條件匹配并將值“1”發(fā)送到連接 Arduino UNO 的串行端口。
?
if (button1val == HIGH) { int num1 = 1; Serial1.println(num1); }
?
類似地,當(dāng)按下按鈕 2 時(shí),值 2 通過(guò)串行端口發(fā)送,當(dāng)按下按鈕 3 時(shí),值 3 通過(guò)串行端口發(fā)送。
?
否則 if (button2val == HIGH) { int num2 =2; Serial1.println(num2); } else if (button3val == HIGH) { int num3 =3; Serial1.println(num3); }
?
當(dāng)沒(méi)有按下按鈕時(shí),值 0 被發(fā)送到 Arduino Uno。
?
否則 { int num = 0; Serial1.println(num); }
?
這樣就完成了將 STM32 配置為主設(shè)備的編程。?
Arduino UNO 作為奴隸
在從端,Arduino UNO 接收從主 STM32F103C8 發(fā)送的整數(shù)值,該整數(shù)值可在連接 RS-485 模塊的 Arduino UNO (P0, 1) 的硬件串行端口獲得。
只需讀取值并存儲(chǔ)在變量中。根據(jù)接收到的值,連接到 Arduino GPIO 的相應(yīng) LED 會(huì)打開(kāi)或關(guān)閉。
要從主機(jī)接收值,只需將 RS-485 模塊的 DE 和 RE 引腳設(shè)為L(zhǎng)OW。所以 Arduino UNO 的 pin-2 (enablePin) 被設(shè)為低電平。
?
數(shù)字寫入(啟用引腳,低);
?
現(xiàn)在只需讀取串行端口上可用的整數(shù)數(shù)據(jù)并將它們存儲(chǔ)在一個(gè)變量中。
?
int 接收 = Serial.parseInt();
?
根據(jù)接收到的值,即 (0, 1, 2, 3),三個(gè) LED 中的相應(yīng)一個(gè)被打開(kāi)。
?
if (receive == 1) //根據(jù)收到的值相應(yīng)的 LED 打開(kāi)或關(guān)閉 { digitalWrite(ledpin1,HIGH); } else if (receive == 2) { digitalWrite(ledpin2,HIGH); } else if (receive == 3) { digitalWrite(ledpin3,HIGH); } else { digitalWrite(ledpin1,LOW); 數(shù)字寫入(ledpin2,低); 數(shù)字寫入(ledpin3,低); }
?
這樣就完成了將 Arduino UNO 編程和配置為從設(shè)備。這也完成了 Arduino UNO 和 STM32 的完整配置。本教程末尾附有工作視頻和所有代碼。
測(cè)試 STM32F103C8 和 Arduino UNO 之間的 RS485 通信:
1. 當(dāng)按下連接到 Master STM32 的 Push button-1 時(shí),連接到 Slave Arduino 的 LED 1 亮起。
2. 按下連接到 Master STM32 的 Push button-2 時(shí),連接到 Slave Arduino 的 LED 2 亮起。
3. 同樣,當(dāng)按下按鈕 3 時(shí),LED 3 打開(kāi)連接到從 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 開(kāi)始串行通信
pinMode(enablePin, OUTPUT);
pinMode(按鈕1,輸入);
pinMode(按鈕2,輸入);
pinMode(按鈕3,輸入);
延遲(10);
數(shù)字寫入(啟用引腳,高);//(總是高,因?yàn)?Master 向 Slave 寫入數(shù)據(jù))
}
無(wú)效循環(huán)()
{
int button1val = digitalRead(button1);//讀取Push Button的狀態(tài)
int button2val = digitalRead(button2);
int button3val = digitalRead(button3);
if (button1val == HIGH)
{
int num1 = 1;
Serial1.println(num1); //發(fā)送按鈕值 1 if HIGH (Pressed)
}
else if (button2val == HIGH)
{
int num2 =2;
Serial1.println(num2); //發(fā)送按鈕值 2 if HIGH (Pressed)
}
else if (button3val == HIGH)
{
int num3 =3;
Serial1.println(num3); //發(fā)送按鈕值 3 if HIGH (Pressed)
}
else
{
int num = 0;
Serial1.println(num); //如果沒(méi)有按下任何按鈕,則發(fā)送 0
}
delay(50);
}
從機(jī)代碼:Arduino UNO:
//STM32F103C8 和 Arduino Uno 之間的 RS-485 串行通信
#define enablePin 2
#define ledpin1 4
#define ledpin2 7
#define ledpin3 8
無(wú)效設(shè)置()
{
序列.開(kāi)始(9600);// 以波特率 9600 開(kāi)始串行通信
pinMode(ledpin1,OUTPUT);
pinMode(ledpin2,輸出);
pinMode(ledpin3,輸出);
pinMode(enablePin, 輸出);
延遲(10);
數(shù)字寫入(啟用引腳,低);//(引腳 8 始終為低電平以接收來(lái)自主機(jī)的值)
}
無(wú)效循環(huán)()
{
while (Serial.available()) //當(dāng)串口有數(shù)據(jù)時(shí),這個(gè)循環(huán)執(zhí)行
{
int receive = Serial.parseInt(); // 讀取從 STM32 發(fā)送的整數(shù)值
if (receive == 1) //根據(jù)接收到的值相應(yīng)的 LED 打開(kāi)或關(guān)閉
{
digitalWrite(ledpin1,HIGH);
}
else if (receive == 2)
{
digitalWrite(ledpin2,HIGH);
}
else if (receive == 3)
{
digitalWrite(ledpin3,HIGH);
}
else
{
digitalWrite(ledpin1,LOW);
數(shù)字寫入(ledpin2,低);
數(shù)字寫入(ledpin3,低);
}
}
}
評(píng)論
查看更多