買了一塊WaveShare 的UART轉RS485(5V)板子來玩玩看。
先簡介一下RS485:
EIA-485(過去叫做RS-485或者RS485
])是隸屬於OSI模型實體層的電氣特性規定為2線,
半雙工,多點通訊的標準。它的電氣特性和RS-232不大一樣。
用纜線兩端的電壓差值來表示傳遞訊號,1極的電壓標識為邏輯1,另一段標識為邏輯0。兩端的電壓差最小為0.2V以上時有效,任何不大於12V或者不小於-7V的差值對接受端都被認為是正確的。
EIA-485僅僅規定了接受端和傳送端的電氣特性。它沒有規定或推薦任何資料協定。EIA-485可以應用於配置便宜的廣域網路和採用單機傳送,多機接受通訊連結。它提供高速的資料通訊速率(10m時35Mbit/s;1200m時100kbit/s)。EIA-485和EIA-422一樣使用雙絞線進行高電壓差分平衡傳輸,它可以進行大面積長距離傳輸(超過4000英尺,1200公尺)。
EIA-485經常和常用裝置
UART一起使用來實現在飛機上的低速率資料傳輸,舉個例子,一些乘客控制單元採用這種裝置,從而只需要很少的線纜就可以實現幾端子共享線纜,從而減輕整個裝置的重量。
所以RS485上會常見到一些協定,例如Modbus,
BacNet and
Profibus 。
當然RS485 也可以利用2組A/B來達成全雙工(一對專送,一對專收)
以上資料來源:
EIA-485 WIKI
簡單來說,RS485並沒有規定使用任何界面,只要電氣特性相符即可。
最左邊是接UART , 你可以看到它提供3種介面的RS485 A/B ,除了杜邦線之外就是2P端子 ,以及一個
腳立說明如下,資料來源:
主要特點為RSE這一支腳,它控制了資料流的方向,當RSE為HIGH時,代表要送資料,
RSE為LOW時表示要接收資料,所以一開始Master會預設為發送,remote會預設為接收。
由於RS485是半雙工的通訊方式,所以每一個裝都只能是傳送或是接收其中一種狀態。
參考了以下網址的範例。
接腳如下:
arduino RS485
10 RX
11 TX
3 RSE
5V VCC
GND GDN
二塊板子之間的A接A,B接B。


之後燒錄程式,一邊為Master,一邊為remote
Master端程式如下:
/* YourDuino SoftwareSerialExample1
- Connect to another Arduino running "YD_SoftwareSerialExampleRS485_1Remote"
- Connect this unit Pins 10, 11, Gnd
- Pin 3 used for RS485 direction control
- To other unit Pins 11,10, Gnd (Cross over)
- Open Serial Monitor, type in top window.
- Should see same characters echoed back from remote Arduino
Questions: terry@yourduino.com
*/
/*-----( Import needed libraries )-----*/
#include <SoftwareSerial.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX 10 //Serial Receive pin
#define SSerialTX 11 //Serial Transmit pin
#define SSerialTxControl 3 //RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
#define Pin13LED 13
/*-----( Declare objects )-----*/
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;
void setup() /****** SETUP: RUNS ONCE ******/
{
// Start the built-in serial port, probably to Serial Monitor
Serial.begin(9600);
Serial.println("YourDuino.com SoftwareSerial remote loop example");
Serial.println("Use Serial Monitor, type in upper window, ENTER");
pinMode(Pin13LED, OUTPUT);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Receive); // Init Transceiver
// Start the software serial port, to another device
RS485Serial.begin(4800); // set the data rate
}//--(end setup )---
void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
digitalWrite(Pin13LED, HIGH); // Show activity
if (Serial.available())
{
byteSend = Serial.read();
digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
RS485Serial.write(byteSend); // Send byte to Remote Arduino
digitalWrite(Pin13LED, LOW); // Show activity
delay(10);
digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
}
if (RS485Serial.available()) //Look for data from other Arduino
{
digitalWrite(Pin13LED, HIGH); // Show activity
byteReceived = RS485Serial.read(); // Read received byte
if (byteReceived!=0 && byteReceived!=10 && byteReceived!=13)
{
Serial.print("receive:"); // Show on Serial Monitor
Serial.write(byteReceived);
Serial.println();
}
delay(10);
digitalWrite(Pin13LED, LOW); // Show activity
}
}//--(end main loop )---
/*-----( Declare User-written Functions )-----*/
//NONE
//*********( THE END )***********
remote端如下
/* YourDuino SoftwareSerialExample1Remote
- Used with YD_SoftwareSerialExampleRS485_1 on another Arduino
- Remote: Receive data, loop it back...
- Connect this unit Pins 10, 11, Gnd
- To other unit Pins 11,10, Gnd (Cross over)
- Pin 3 used for RS485 direction control
- Pin 13 LED blinks when data is received
Questions: terry@yourduino.com
*/
/*-----( Import needed libraries )-----*/
#include <SoftwareSerial.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX 10 //Serial Receive pin
#define SSerialTX 11 //Serial Transmit pin
#define SSerialTxControl 3 //RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
#define Pin13LED 13
/*-----( Declare objects )-----*/
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;
void setup() /****** SETUP: RUNS ONCE ******/
{
// Start the built-in serial port, probably to Serial Monitor
Serial.begin(9600);
Serial.println("SerialRemote"); // Can be ignored
pinMode(Pin13LED, OUTPUT);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Receive); // Init Transceiver
// Start the software serial port, to another device
RS485Serial.begin(4800); // set the data rate
}//--(end setup )---
void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
//Copy input data to output
if (RS485Serial.available())
{
byteSend = RS485Serial.read(); // Read the byte
digitalWrite(Pin13LED, HIGH); // Show activity
delay(10);
digitalWrite(Pin13LED, LOW);
Serial.write(byteSend);
digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
if (byteSend!=0 && byteSend!=10 && byteSend!=13)
RS485Serial.write(byteSend); // Send the byte back
delay(10);
digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
// delay(100);
}// End If RS485SerialAvailable
}//--(end main loop )---
/*-----( Declare User-written Functions )-----*/
//NONE
//*********( THE END )***********
程式碼來源:(我有稍微做一點修改)
https://arduino-info.wikispaces.com/SoftwareSerialRS485Example
master執行畫面(記得選擇為沒有結尾)
remote執行畫面(使用CoolTerm)
記得先修改一下傳送的結尾模式
由master傳送一個字元a,會收到一個相同回應
remote端也會將收到的字元顯示並回傳給Master
如果一次輸入一堆字傳送,可能就會出現問題,例如我輸入1234567890abcdefg
remote端收到的也是不正確的字元
所以使用rs485做傳輸時,一定要注意收和送的時間點,建議使用現有的協定,例如ModBus,因為在收和送之間需要切換,這個如果沒有搭配好,會出現異常的資料。