前面我介紹了51單片機(jī)的串口通信協(xié)議, 其核心是操作單片機(jī)的SCON,SBUF和定時(shí)器1,通過外部引腳Tx與Rx來實(shí)現(xiàn)與外部的數(shù)據(jù)交換?,F(xiàn)在加入我們要實(shí)現(xiàn)兩個(gè)mcu之間的遠(yuǎn)程通信,顯然直接連接他們的Tx與Rx腳是不可行的。因?yàn)門TL通信容易受噪聲干擾,其次線路過長(zhǎng)本身也會(huì)有壓降,再次信號(hào)線與地線之間形成一個(gè)電容,我們知道電容兩端電壓不能突變,因?yàn)門TL電平容易變形進(jìn)而導(dǎo)致傳輸錯(cuò)誤。
RS485通信
因此我們引入一種差分傳輸接口標(biāo)準(zhǔn)RS485,它具備以下特點(diǎn)。
1、我們?cè)谥vA/D的時(shí)候,講過差分信號(hào)輸入的概念,同時(shí)也介紹了差分輸入的好處,最大的優(yōu)勢(shì)是可以抑制共模干擾。尤其工業(yè)現(xiàn)場(chǎng)的環(huán)境比較復(fù)雜,干擾比較多,所以通信如果采用的是差分方式,就可以有效的抑制共模干擾。而RS485就是一種差分通信方式,它的通信線路是兩根,通常用A和B或者D+和D-來表示。邏輯“1”以兩線之間的電壓差為+(0.2~6)V表示,邏輯“0”以兩線間的電壓差為-(0.2~6)V來表示,是一種典型的差分通信。
2、RS485通信速度快,最大傳輸速度可以達(dá)到10Mb/s以上。
3、RS485內(nèi)部的物理結(jié)構(gòu),采用的是平衡驅(qū)動(dòng)器和差分接收器的組合,抗干擾能力也大大增加。
4、傳輸距離最遠(yuǎn)可以達(dá)到1200米左右,但是他的傳輸速率和傳輸距離是成反比的,只有在100Kb/s以下的傳輸速度,才能達(dá)到最大的通信距離,如果需要傳輸更遠(yuǎn)距離可以使用中繼。
5、可以在總線上進(jìn)行聯(lián)網(wǎng)實(shí)現(xiàn)多機(jī)通信,總線上允許掛多個(gè)收發(fā)器,從現(xiàn)有的RS485芯片來看,有可以掛32、64、128、256等不同個(gè)設(shè)備的驅(qū)動(dòng)器。
RS485的接口非常簡(jiǎn)單,和RS232所使用的MAX232是類似的,只需要一個(gè)RS485轉(zhuǎn)換器,就可以直接和我們單片機(jī)的UART串行接口連接起來,并且完全使用的是和UART一致的異步串行通信協(xié)議。但是由于RS485是差分通信,因此接收數(shù)據(jù)和發(fā)送數(shù)據(jù)是不能同時(shí)進(jìn)行的,也就是說它是一種半雙工通信。那我們?nèi)绾闻袛嗍裁磿r(shí)候發(fā)送,什么時(shí)候接收呢?MAX485是美信(Maxim)推出的一款常用RS485轉(zhuǎn)換器。其中5腳和8腳是電源引腳,6腳和7腳就是485通信中的A和B兩個(gè)引腳,而1腳和4腳分別接到我們單片機(jī)的RXD和TXD引腳上,直接使用單片機(jī)UART進(jìn)行數(shù)據(jù)接收和發(fā)送。而2腳和3腳就是方向引腳了,其中2腳是低電平使能接收器,3腳是高電平使能輸出驅(qū)動(dòng)器。我們把這兩個(gè)引腳連到一起,平時(shí)不發(fā)送數(shù)據(jù)的時(shí)候,保持這兩個(gè)引腳是低電平,讓MAX485處于接收狀態(tài),當(dāng)需要發(fā)送數(shù)據(jù)的時(shí)候,把這個(gè)引腳拉高,發(fā)送數(shù)據(jù),發(fā)送完畢后再拉低這個(gè)引腳就可以了。為了提高RS485的抗干擾性能,需要在靠近MAX485的A和B引腳之間并接一個(gè)電阻,這個(gè)電阻阻值從100歐到1K都可以。
RS485的單工通信協(xié)議
好了,現(xiàn)在我們先來用485做一次單向的傳遞,一塊MCU做主機(jī)發(fā)送一個(gè)片上AD讀取的數(shù)字量給另一塊MCU。我們可以定義一個(gè)簡(jiǎn)單的單工通信協(xié)議。即主機(jī)發(fā)送的數(shù)據(jù)需遵守如下格式:
0xAA
adH
adL
adsum
其中0XAA為包頭,表示數(shù)據(jù)包的開始;adH為AD轉(zhuǎn)換結(jié)果的高8位,adL位AD轉(zhuǎn)換結(jié)果的低8位,adsum為(adH+adL)%256為校驗(yàn)碼。為什么需要校驗(yàn)碼?這是因?yàn)槲覀円l(fā)送的是一個(gè)占兩個(gè)字節(jié)的數(shù)ad,而SBUF是一個(gè)字節(jié)的寄存器,因此一個(gè)ad要分兩次發(fā)。如果發(fā)送過程傳輸中斷,正巧只發(fā)了高8位,那么下一次再開始發(fā)送的時(shí)候重新開始,這個(gè)高8位便會(huì)和另外一個(gè)8位組成一個(gè)數(shù)。因此需要校驗(yàn),當(dāng)然這種校驗(yàn)方法是不準(zhǔn)確的。好了。直接上代碼吧。
RS485主機(jī)代碼
先看主機(jī)的代碼。main.c
#include "12864.h"
#include "stc_adc.h"
#include "uart.h"
#include "timer.h"
#include "rs485.h"
void Isr_Init()
{
EA=1;
ES=1;
ET0=1;
}
void main()
{
LCD_Init();
STCADC_Init();
Timer0_Init();
RS485_Init();
Isr_Init();
Show_String(0x80,"RS485 主機(jī)");
while(1)
{
ad=Read_StcAdc(5);
RS485_Send();
Show_Number(0x88,ad);
//...
}
}
rs485.c
#include"rs485.h" #include "stc_adc.h" #include "uart.h" #include "timer.h" sbit RT485=P1^0;//MAX485的收發(fā)狀態(tài)控制位 //1:發(fā)送 0:接收 void RS485_Init() { Uart_Init(); RT485=0; //初始化485為接收狀態(tài) } void RS485_Send() //將當(dāng)前的數(shù)字量發(fā)送給從機(jī) { u8 buf[4],i; if(ms.ms1<200) { return ; } buf[0]=0xaa; buf[1]=ad/256; buf[2]=ad%256; buf[3]=(buf[1]+buf[2])%256; RT485=1; //發(fā)送狀態(tài) for(i=0;i<4;i++) { Send_Byte(buf[i]); } RT485=0; //接收狀態(tài) ms.ms1=0; }rs485.h
#ifndef _485_
#define _485_
#include "reg51.h"
#define u8 unsigned char
#define u16 unsigned int
void RS485_Init();
void RS485_Send();
#endif
uart.c
評(píng)論
查看更多