ทำความรู้จัก RS485

RS232, RS422, RS423 และ RS485 เป็นการสื่อสารแบบ Serial สำหรับคอมพิวเตอร์และอุปกรณ์ต่างๆ ถ้าพูดถึง RS232 คงจะรู้จักกัน เพราะมันเป็นฮาร์ดแวร์มาตราฐานที่ติดมากับเครื่อง Desktop (ความจริงในสมัยก่อนเครื่อง Notebook ก็มี RS232)

RS232 จะมีข้อจำกัดอยู่หลายอย่าง เช่น ความยาวของสายต้องไม่เกิน 50 ฟุต และความเร็วสูงสุดอยู่ที่ 20 kbs ซึ่งไม่เพียงพอสำหรับการสื่อสารที่ต้องเดินสายไกล/ความเร็วสูง ต่อมาได้มี RS485 มาแทนที่ RS232

ปัญหาหลักของ RS232 คือไม่ทนต่อ Noise เนื่องจากข้อมูลในสาย TX และ RX ต้องเปรียบเทียบระดับสัญญาณกับ GND เมื่อ GND ถูกรบกวนทำให้ GND เปลี่ยนไปจากเดิม แต่ RS485 ไม่ได้ใช้การอ้างอิงสัญญาณกับ GND RS485 ใช้ความแตกต่างระหว่างสาย 2 สาย (A และ B) เป็นตัวบอกว่า Logic “1″ หรือ Logic “0″ วิธีนี้จะป้องกัน GND loop ที่เกิดขึ้น

จากประสบการณ์ที่ใช้งานพบว่าสายแบบ Twist จะป้องกัน Noise ได้ดีกว่าสายตรงที่เดินขนานกันไป และจะให้ดียิ่งขึ้นต้องเป็นสายที่ Shield จะสามารถป้องกันสนามไฟฟ้า สนามแม่เหล็กเข้ามากวนได้

การใช้ไมโครคอนโทรลเลอร์สื่อสารแบบ RS485
RS485 เป็นการรับส่งแบบ Half-Duplex การเขียนโปรแกรมจะกำหนดให้มี Master 1 ตัวเพื่อคอยจัดคิวการสื่อสารใน Network และให้อุปกรณ์ที่เหลือเป็น Slave โดย Slave แต่ละตัวจะมี Address ของตัวเอง เวลาที่ Master ต้องการจะสื่อสารกับ Slave ทำได้โดย ส่ง Address ที่ต้องการจะสื่อสารออกไป แล้วตามด้วยฟังก์ชัน Slave ทุกตัวจะรับข้อมูลได้เหมือนกัน Slave จะเช็คดูว่า Address นั้นใน Address ของตัวเองหรือไม่ ถ้าเป็น Address ของตัวเองก็จะทำการตอบข้อมูลกลับตามที่ Master ต้องการ

โปรโตคอลที่ใช้ในการสื่อสารใน RS485
เราสามารถกำหนดโปรโตคอลเองได้ว่าจะให้มีลักษณะยังไง หรือจะใช้ Open โปรโตคอลก็ได้เช่นโปรโตคอล MODBUS ที่นิยมใช้ใน PLC งานอุตสาหกรรม

IC ที่นิยมใช้แปลงสัญญาณ UART <—> RS485 จะเป็นเบอร์ SN75176 มีราคาถูก สามารถต่อได้มากสุด 32 Node

คำแนะนำในการเขียนโปรแกรม
โดยปกติแล้วเราจะ Jump RE และ DE ของ SN75176 เข้าด้วยกัน เวลาจะส่งข้อมูลออกไปต้องให้ MCU ส่ง “1″ มาที่ขา RE และ DE เพื่อ Enable การส่งและเมื่อส่งข้อมูลเสร็จแล้วต้องส่ง “0″ มาที่ขา RE และ DE เพื่อรอรับข้อมูล ใน Bus RS485 ถ้ามีตัวใดตัวหนึ่ง Enable DE ไว้ตัวที่เหลือจะไม่สามารถส่งข้อมูลได้เลยและเมื่อส่งข้อมูลเสร็จแล้วต้องส่ง “0″ มาที่ขา RE และ DE เพื่อรอรับข้อมูล ใน Bus RS485 ถ้ามีตัวใดตัวหนึ่ง Enable DE ไว้ตัวที่เหลือจะไม่สามารถส่งข้อมูลได้เลย

รูปแบบของ Network (Nowork Topology)
ในการเดินสาย RS485 ที่ถูกต้องจะต้องเดินเป็นเส้นยาว เราจะเรียกอุปกรณ์ในแต่ละตัวว่า Node เราจะวาง Node แรกไว้ที่ต้นสาย และ Nodeสุดท้ายไว้ที่ปลายสาย และNode อื่นๆ ก็จะ Jump เข้าที่กลางสาย ใน Datasheet จะแนะนำว่าให้ต้อง R ค่า 120 Ohm ไว้ที่หัวและท้ายของสายด้วยตำแหน่งละตัว ถ้าเราเอา VOM มาวัดความต้านทานในสาย A และ B จะได้ความต้านทานเท่ากับ R 120 Ohm ขนานกัน หรือเท่ากับ 60 Ohm

Typical Application Circuit

ข้อมูลเพิ่มเติม

Download MODBUS Application ProtocalV1.1

การทดลองที่ 3 UART (Serial interrupt)

การสื่อสารทางพอร์ตอนุกรมเป็นการสื่อสารแบบ Full duplex คือสามารถรับและส่งได้ในเวลาเดียวกัน ซึ่งจะมีขา TXD ในการส่งและ RXD ในการรับ การสื่อสารทางพอร์ตอนุกรมโดยทั่วไปจะใช้ตัว driver/receiver มาต่อกับขา RXD/TXD อีกทีนึงเพื่อเพิ่มระยะทางในการสื่อสาร สำหรับการติดต่อกับคอมพิวเตอร์ เราจะต้องใช้ตัว driver/receiver เพื่อแปลงสัญญาณลอจิกของ MCS-51 ให้เป็นมาตราฐาน RS-232 เบอร์ที่นิยมใช้กันมากจะเป็น MAX232

  • มาตราฐานของ RS-232 ระบุไว้ว่าสามารถส่งได้เป็นระยะทาง 50 ฟุต หรือ 15 เมตร

สำหรับการส่งที่ต้องการระยะทางไกลมากขึ้นจะเป็น RS-485/RS-422 ตัว driver/receiver เช่นเบอร์ 75176

  • มาตราฐานของ RS-485/RS-422 ระบุไว้ว่าสามารถส่งได้เป็นระยะทาง 4000 ฟุต หรือ 1200 เมตร

สำหรับการทดลองนี้ผมจะทดลองกับ RS-232 ซึ่งเราสามารถส่งข้อมูลไปยังคอมพิวเตอร์ได้

null

รูปที่ 1 วงจรที่ใช้ในการทดลอง

ในการทดลองการรับส่งข้อมูลทาง serial port UART เราจะใช้โปรแกรมยอดฮิตที่ติดมาอยู่แล้วใน windows นั่นคือโปรแกรม HyperTerminal ถ้าใครหาโปรแกรมนี้ไม่เจอ ให้ไปที่ Start–>All Programs–>Accessories–>Communication–>Hyperterminal ตั้งต่าตามรูปที่ 2-4

รูปที่ 2

รูปที่ 3

รูปที่ 4

ทำการ Reset MCS-51 จะกด Reset หรือถอดปลั๊กแล้วเสียบใหม่ก็ได้ จะเห็นข้อความดังรูปที่ 5 ให้พิมพ์ชื่อตัวเองลงไป ผมพิมพ์ “Aon.” แล้ว Enter จะได้ข้อความดังรูปที่ 5

รูปที่ 5

การทดลองนี้ผมจะไม่ใช้ printf เนื่องจากคำสั่ง printf เราจะกินหน่วยความจำไปอีก 1K byte แต่ผมจะใช้วิธี copy string เข้าไปใน Txbuff แทน

//************************************************************************//
//Project : LAB3
//Description : Serial UART interrupt
//Device : 89S52
//XTAL : 11.0592 MHz
//By : ThaiEmbedded 2007
//************************************************************************//
#include <reg52.h>
#include <absacc.h>
#include <intrins.h>
#include <string.h>#define CR 0x0d
#define LF 0x0a

bit TX_OK,RX_OK;
unsigned char Txbuff[40];
unsigned char Rxbuff[20];
unsigned char Txn;
unsigned char Txcnt,Rxcnt;

//————————————————————————//
// Serial interrupt service routine
//————————————————————————//
void serial_isr() interrupt 4
{
if(TI)
{
TI=0;
if(Txcnt<Txn)
SBUF=Txbuff[Txcnt++];
else
TX_OK = 1;
}

if(RI)
{
RI=0;
if((!RX_OK)&&(Rxcnt<19))
{
Rxbuff[Rxcnt]=SBUF;
if(Rxbuff[Rxcnt]==0x0d)
RX_OK = 1;
Rxcnt++;
}
}

}
//————————————————————————//
// Initial register
//————————————————————————//
void init()
{
TMOD = 0×20;
TH1 = 0xfd;
IE = 0×90;
TR1 = 1;
SCON = 0×52;
}
//————————————————————————//
// Main
//————————————————————————//
void main ()
{
unsigned char i;
init();
// 01234567890123456789012
strncpy(Txbuff,”Welcome to ThaiEmbedded”,23);
Txbuff[23] = CR;
Txbuff[24] = LF;
Txn = 25;
Txcnt = 1;
TX_OK = 0;
SBUF = Txbuff[0];
while(!TX_OK);

while(1)
{
// 012345678901234
strncpy(Txbuff,”Type your name “,15);
Txn = 15;
Txcnt = 1;
TX_OK = 0;
SBUF = Txbuff[0];
while(!TX_OK);

Rxcnt = 0;
RX_OK = 0;
while(!RX_OK);

// 0123456789012
strncpy(Txbuff,”Your name is “,13);
Txn = 13;

for(i=0;i<Rxcnt;i++)
Txbuff[Txn++] = Rxbuff[i];

Txbuff[Txn++] = CR;
Txbuff[Txn++] = LF;
Txcnt = 1;
TX_OK = 0;
SBUF = Txbuff[0];
while(!TX_OK);
}
}

Download Code การทดลองที่ 3