先簡介一下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並沒有規定使用任何界面,只要電氣特性相符即可。
最左邊是接UART , 你可以看到它提供3種介面的RS485 A/B ,除了杜邦線之外就是2P端子 ,以及一個
腳立說明如下,資料來源:
主要特點為RSE這一支腳,它控制了資料流的方向,當RSE為HIGH時,代表要送資料,
RSE為LOW時表示要接收資料,所以一開始Master會預設為發送,remote會預設為接收。
由於RS485是半雙工的通訊方式,所以每一個裝都只能是傳送或是接收其中一種狀態。
參考了以下網址的範例。
https://arduino-info.wikispaces.com/SoftwareSerialRS485Example
這個範例master每次只能傳送一個byte,然候就會切換到接收模式直到Serial有再次輸入,就會切回去發送模式(此時remote傳再多它也收不到了),而remote在接收到資料後會切換成傳送模式把資料發送回去,10ms後就會再回到接收模式。
這個範例master每次只能傳送一個byte,然候就會切換到接收模式直到Serial有再次輸入,就會切回去發送模式(此時remote傳再多它也收不到了),而remote在接收到資料後會切換成傳送模式把資料發送回去,10ms後就會再回到接收模式。
接腳如下:
arduino RS485
10 RX
11 TX
3 RSE
5V VCC
GND GDN
二塊板子之間的A接A,B接B。
之後燒錄程式,一邊為Master,一邊為remote
Master端程式如下:
remote端如下
程式碼來源:(我有稍微做一點修改)
https://arduino-info.wikispaces.com/SoftwareSerialRS485Example
master執行畫面(記得選擇為沒有結尾)
remote執行畫面(使用CoolTerm)
記得先修改一下傳送的結尾模式
由master傳送一個字元a,會收到一個相同回應
remote端也會將收到的字元顯示並回傳給Master
如果一次輸入一堆字傳送,可能就會出現問題,例如我輸入1234567890abcdefg
remote端收到的也是不正確的字元
所以使用rs485做傳輸時,一定要注意收和送的時間點,建議使用現有的協定,例如ModBus,因為在收和送之間需要切換,這個如果沒有搭配好,會出現異常的資料。
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,因為在收和送之間需要切換,這個如果沒有搭配好,會出現異常的資料。
很棒 感謝分享
回覆刪除