2.2 RS-485
RS-485標準接口是單片機系統(tǒng)種常用的一種串行總線之一。RS-485通信方式RS-485標準是由EIA(電子工業(yè)協(xié)會)和TIA(通訊工業(yè)協(xié)會)共同制訂和開發(fā)的。RS-485作為一種多點差分數(shù)據(jù)傳輸?shù)?a target="_blank">電氣規(guī)范,已成為業(yè)界最廣泛應用的標準通信接口之一。理論上,RS-485標準最多接入32個設(shè)備(受芯片驅(qū)動能力的影響),可以工作在半雙工或全雙工模式下,最大傳輸距離約為1219米,最大傳輸速率約為10Mbps[1]。然而通常RS-485網(wǎng)絡(luò)采用平衡雙絞線作為傳輸媒體,平衡雙絞線的長度與傳輸速率成反比,只有在20Kbps的傳輸速率下,才可能達到最大傳輸距離。一般15米長的雙絞線最大傳輸速率僅為1Mbps。不過對于速率要求不是很高的控制系統(tǒng)來說已經(jīng)足夠了。
RS-485采用平衡發(fā)送和差分接收方式來實現(xiàn)通信:在發(fā)送端TXD將串行口的TTL電平信號轉(zhuǎn)換成差分信號A、B兩路輸出,經(jīng)傳輸后在接收端將差分信號還原成TTL電平信號。兩條傳輸線通常使用雙絞線,又是差分傳輸,因此有極強的抗共模干擾的能力,接收靈敏度也相當高。同時,最大傳輸速率和最大傳輸距離也大大提高。如果以10Kbps速率傳輸數(shù)據(jù)時傳輸距離可達12m,而用100Kbps時傳輸距離可達1.2km。如果降低波特率,傳輸距離還可進一步提高。另外RS-485實現(xiàn)了多點互連,最多可達256臺驅(qū)動器和256臺接收器,非常便于多器件的連接。不僅可以實現(xiàn)半雙工通信,而且可以實現(xiàn)全雙工通信。
2.3 多機通信原理
在多機通信中,每臺從機均分配有一個從機地址,主機與從機之間進行串行通信時,通常是主機先呼叫某從機地址,喚醒被叫從機后,主、從兩機之間進行數(shù)據(jù)交換。而未被呼叫的從機則繼續(xù)進行各自的工作??墒?,如果在主機與某被呼叫從機進行數(shù)據(jù)交換過程中,其他從機如果不采取相應的數(shù)據(jù)識別技術(shù),則這些從機就會因為串行通信線上有數(shù)據(jù)傳輸而時時被打斷,影響正常的工作。利用單片機的串口工作方式2、方式3可以很好解決上述問題。在多機通信過程中,從機首先要解決的是如何識別主機發(fā)送的是地址信息還是數(shù)據(jù)信息。當發(fā)送的是地址信息時,各從機都響應串口中斷,接收主機下發(fā)的一幀地址數(shù)據(jù)。而當主機發(fā)送數(shù)據(jù)幀時,無關(guān)從機可不響應串口中斷。解決的方法是:當主機發(fā)送一幀地址信息時,應保持這幀數(shù)據(jù)的第9位為1(即TB8=1)。從機按照工作方式2或工作方式3運行時,將串口寄存器SCON中的控制位SM2置為1,當所接收的一幀數(shù)據(jù)的第9位為1,所有從機都產(chǎn)生串口中斷,接收這一幀地址數(shù)據(jù)并與各自的從機地址進行比較,以判斷主機是否要與本機通信。接收到的地址數(shù)據(jù)與從機地址相等達到為被呼叫從機,該從機將串口控制寄存器SCON中的控制位SM2清為0, 去接收主機發(fā)送來的數(shù)據(jù)幀(數(shù)據(jù)幀的第9位為0),此時不管接收到的第9位數(shù)據(jù)是否為1或0,都要產(chǎn)生串口中斷,這就保證了主機與被呼叫從機間的正常數(shù)據(jù)通信。數(shù)據(jù)通信結(jié)束后,該從機又重新將串行口控制寄存器SCON中的控制位SM2置為1,為下一次與主機進行通信做好準備。其他從機則一直在SM2=1下繼續(xù)自己的工作,不會因為主、從機之間的數(shù)據(jù)通信而被打斷。
多機通信的實現(xiàn),主要靠主、從機正確地設(shè)置與判斷多機通信控制位SM2和發(fā)送或接收的第9位數(shù)據(jù)(TB8或RB8)。當主機給從機發(fā)送信息時,要根據(jù)發(fā)送信息的性質(zhì)來設(shè)置TB8,發(fā)送地址信號時,設(shè)置TB8=1;發(fā)送數(shù)據(jù)或命令時,設(shè)置TB8=0。當從機的SM2為1時,該從機只接收地址幀(RB8位為1),對數(shù)據(jù)幀(RB8位為0)將不予理睬。而當SM2為0時,該從機接收所有發(fā)送來的信息。多機通信過程如下:(1) 使所有從機的SM2置1,處于只接收地址幀的狀態(tài)(即從機復位);
(2) 主機發(fā)送一地址幀信息,其中包含8位地址,第9位為地址、數(shù)據(jù)標志位,第9
位置1表示發(fā)送的是地址;
?。?) 從機接收到地址幀后,各自中斷CPU,把接收到的地址與本地址作比較; (4) 地址相符的從機,使SM2清零以接收主機隨后發(fā)來的所有信息,對于地址不相符
的從機,仍保持SM2=1狀態(tài),對主機隨后發(fā)送的數(shù)據(jù)不予理睬,直到主機發(fā)送來新的地址幀;
(5) 主機發(fā)送數(shù)據(jù)或控制信息給被尋址的從機;
?。?) 被尋址的從機,因SM2=0,可以接收主機發(fā)送過來的所有數(shù)據(jù),當從機接收數(shù)據(jù)
結(jié)束時,置位SM2,返回接收地址幀狀態(tài)(復位狀態(tài));
?。?) 當主機改為與另外從機聯(lián)系時,可再發(fā)地址幀尋址其從機,而先前被尋址過的從
機恢復SM2=1
第4章 系統(tǒng)問題及其解決
4.1 通信規(guī)則
由于MAX485通訊是一種半雙工通訊,發(fā)送和接收共用同一物理信道。在任意時刻只允許一臺單機處于發(fā)送狀態(tài)。因此要求應答的單機必須在偵聽到總線上呼叫信號已經(jīng)發(fā)送完畢,并且沒有其它單機發(fā)出應答信號的情況下,才能應答。半雙工通訊對主機和從機的發(fā)送和接收時序有嚴格的要求。如果在時序上配合不好,就會發(fā)生總線沖突,使整個系統(tǒng)的通訊癱瘓,無法正常工作。要做到總線上的設(shè)備在時序上的嚴格配合,必須要遵從以下幾項原則: ?。?) 復位時,主從機都應該處于接收狀態(tài)。
MAX485芯片的發(fā)送和接收功能轉(zhuǎn)換是由芯片的 RE* ,DE端控制的。RE*=1,DE=1時,MAX485發(fā)送狀態(tài);RE*=0,DE=0時,MAX485處于接收狀態(tài)。一般使用單片機的一根口線連接RE*,DE端。在上電復位時,由于硬件電路穩(wěn)定需要一定的時間,并且單片機各端口復位后處于高電平狀態(tài),這樣就會使總線上各個分機處于發(fā)送狀態(tài),加上上電時各電路的不穩(wěn)定,可能向總線發(fā)送信息。因此,如果用一根口線作發(fā)送和接收控制信號,應該將口線反向后接入MAX485的控制端,使上電時MAX485處于接收狀態(tài)。 另外,在主從機軟件上也應附加若干處理措施,如:上電時或正式通訊之前,對串行口做幾次空操作,清除端口的非法數(shù)據(jù)和命令。
?。?) 控制端RE*,DE的信號的有效脈寬應該大于發(fā)送或接收一幀信號的寬度。 在全雙工通訊過程中,發(fā)送和接收信號分別在不同的物理鏈路上傳輸,發(fā)送端始終為發(fā)送端,接收端始終為接收端,不存在發(fā)送、接收控制信號切換問題。在RS-485半雙工通訊中,由于MAX485的發(fā)送和接收都由同一器件完成,并且發(fā)送和接收使用同一物理鏈路,必須對控制信號進行切換??刂菩盘柡螘r為高電平,何時為低電平,一般以單片機的TXC(發(fā)送完成標記),RXC(接收完成標記)信號作參考。
發(fā)送時,檢測TXC是否建立起來,當TXC為高電平后關(guān)閉發(fā)送功能轉(zhuǎn)為接收功能; 接收時,檢測RXC是否建立起來,當RXC為高電平后,接收完畢,又可以轉(zhuǎn)為發(fā)送。 在理論上雖然行得通,但在實際聯(lián)調(diào)中卻出現(xiàn)傳輸數(shù)據(jù)時對時錯的現(xiàn)象。根據(jù)查證有關(guān)資料,并借助示波器反復測試,才發(fā)現(xiàn)一個值得注意的問題,我們可以查看單片機的時序:
單片機在串行口發(fā)送數(shù)據(jù)時,只要將8位數(shù)據(jù)位傳送完畢,TXC標志即建立,但此時應發(fā)送的第九位數(shù)據(jù)位(若發(fā)送地址幀時)和停止位尚未發(fā)出。如果在這是關(guān)閉發(fā)送控制,勢必造成發(fā)送幀數(shù)據(jù)不完整。如果單片機多機通訊采用較高的波特率,幾條操作指令的延時就可能超過2位(或1位)數(shù)據(jù)的發(fā)送時間,問題或許不會出現(xiàn)。但是如果采用較低波特率,如9600,發(fā)送一位數(shù)據(jù)需104μs左右,單靠幾條操作指令的延時遠遠不夠,問題就明顯地暴露出來。接收數(shù)據(jù)時也同樣如此,單片機在接收完8個數(shù)據(jù)位后就建立起RXC信號,但此時還未接收到第九位數(shù)據(jù)位(若接收地址幀時)和停止位。所以,接收端必須延時大于2位數(shù)據(jù)位的時間(1位數(shù)據(jù)位時間=1/波特率),再作應答,否則會發(fā)生總線沖突。
?。?) 總線上所連接的各單機的發(fā)送控制信號在時序上完全隔開。
為了保證發(fā)送和接收信號的完整和正確,避免總線上信號的碰撞,對總線的使用權(quán)必須進行分配才能避免競爭,連接到總線上的單機,其發(fā)送控制信號在時間上要完全隔離。
總之,發(fā)送和接收控制信號應該足夠?qū)?,以保證完整地接收一幀數(shù)據(jù),任意兩個單機的發(fā)送控制信號在時間上完全分開,避免總線爭端。
第5章 軟件設(shè)計
5.1 系統(tǒng)結(jié)構(gòu)
該多機通信系統(tǒng)的系統(tǒng)結(jié)構(gòu)圖如圖5-1所示,系統(tǒng)采用半雙工主從通信方式,主機可以讀取從機的數(shù)據(jù)或?qū)憯?shù)據(jù)到從機,并將數(shù)據(jù)送終端進行顯示;從機主要負責對分布的電子設(shè)備進行監(jiān)測或控制,用中斷的方式接收主機發(fā)來的命令并做出回應。
5.2 通信協(xié)議 5.2.1 信息格式
該協(xié)議的信息格式如下:
?。?)編碼格式;二進制代碼。
?。?)波特率:9600 b/s。
?。?)通信方式:半雙工。
?。?)每個字符由u 位組成; 1位:起始位(0); 8位:數(shù)據(jù)位;1位:地址/數(shù)據(jù)識別位(1為地址,o為數(shù)據(jù)); l位:停止位(1)。
?。?) 字符發(fā)送順序;低位在先
(6) 幀結(jié)束標志:通信線路空閑3.5 ms以上
?。?) 幀校驗方式:數(shù)據(jù)和(2字節(jié))
?。?) 主機詢問的一般格式見表5-2:
表5-2 主機詢問的一般格式
從機地址碼:兩字節(jié)二進制數(shù),后一字節(jié)是前一字節(jié)的反碼。 命令碼:一字節(jié)二進制數(shù),O1H代表主機讀,02H代表主機寫。 數(shù)據(jù)個數(shù):表示主機要讀寫的字節(jié)個數(shù),一字節(jié)二進制數(shù)。
校驗和:兩字節(jié)二進制數(shù),是將從機地址碼、命令和數(shù)據(jù)按字節(jié)從頭依次相加,生成兩字節(jié)的校驗和。 從機應答的一般格式(如表5-3)
表5-3 從機應答的一般格式
圖中信息段的定義同圖2
5.2.2 定時與重發(fā)
本通信協(xié)議定時規(guī)定如下:
?。?)幀發(fā)送時限;70 ms.超過此時限結(jié)束發(fā)送。
(2)主機等待從機應答時限:7 ms,超過此時限,酌情重發(fā)。 (3)主機重發(fā)次數(shù):不超過4次,超過后,判通信失敗。
5.2.3 通信過程
一次完整的通信過程分為3個階段:主機詢問、從機應答和鏈路釋放。主機詢問階段,主機以幀的形式將從機地址碼、命令、數(shù)據(jù)和校驗碼傳送到指定從機;從機應答階段,從機解釋接收的命令碼,并組織相應幀信息回送到主機;鏈路釋放階段,從機清除接收緩沖區(qū)及相關(guān)變量,準備與主機下次通信。任何一次完整的通信過程都是由主機方發(fā)起的,從機在被主機尋址前只能處于偵聽狀態(tài),從機在接收到地址碼的第2個字節(jié)后,立即判斷是否尋址自己,如果是.繼續(xù)接受下面的數(shù)據(jù),否則不與理睬。
5.3 通信軟件設(shè)計 5.3.1 從機通信軟件設(shè)計
在該系統(tǒng)中,從機的主要任務是對被檢測設(shè)備進行故障檢測和故障定位,通信軟件的主要功能是接收主機的命令并將檢測的結(jié)果回送主機。從機通信軟件由2部分組成:串行中斷服務程序和定時器TO中斷服務程序。串行中斷服務程序用于接收或發(fā)送數(shù)據(jù);TO中斷服務程序用于當從機接收完一幀信息后進行解釋并啟動通信向主機應答,另外也用于當從機發(fā)送超時后的一些處理。從機上電后處于偵聽狀態(tài),當主機尋址時,便進人中斷服務程序,其程序流程圖如圖5-4所示。
圖5-4 串行通信中斷服務程序流程圖
定時器TO,并置收發(fā)標志為收。當接收完第2個字節(jié)后,各從機立即判斷是否尋址本機,若是,則置SM2為‘
0’,繼續(xù)接收主機送來的數(shù)據(jù);若不是,則禁止T0定時,不在接收后面的數(shù)據(jù)。當被尋址從機接收完一幀信息后,字符間隔定時器會產(chǎn)生定時中斷,進入TO中斷服務程序。圖5-5是TO中斷服務程序流程圖
進入TO中斷服務程序后,首先清除TO中斷請求標志,停止TO定時器,接著判斷是接收完成還是發(fā)送超時,若是接收完成,再判斷校驗和是否正確,若正確,對接收的命令進行解釋,看是主機讀還是主機寫操作,若是主機讀,則將數(shù)據(jù)打包,送到專門用于通信的數(shù)組,接著,禁止接收,置本機為應答工作方式,最后啟動發(fā)送,發(fā)送第一個字節(jié),同時啟動發(fā)送時限定時器TO。當一個字節(jié)發(fā)送完后,便進入通信中斷服務程序,
繼續(xù)發(fā)送余下數(shù)據(jù)。如果在上邊判校驗和時,發(fā)現(xiàn)不正確,則置SM2為‘1’,恢復本機的偵聽狀態(tài),以便接收主機的重發(fā)信息。
5.3.2 主機通信軟件設(shè)計
該系統(tǒng)主機的主要任務是循環(huán)讀取從機的檢測結(jié)果,并送終端顯示,其通信軟件由3部分組成:主程序中負責尋址從機的尋址模塊、通信中斷服務程序和TO中斷服務程序。尋址模塊程序流程圖見圖5-6。
對從機尋址是按照從機的編號順序進行的,即從1號從機開始,主機發(fā)送該從機信息幀的第1個字節(jié)啟動尋址,同時啟動發(fā)送超時定時器TO,然后檢測通信結(jié)束標志.當主機成功的接收到該從機的應答信息后,便會置位該標志,完成與該從機的通信。接下來,尋址下一從機,直到所有從機都被尋址。最后,主機完成其它功能后,又從1號從機開始下一循環(huán)的尋址。通信中斷服務程序和TO中斷服務程的設(shè)計方法與從機的大同小異,在此不再介紹。
第6章 程序設(shè)計
程序是單片機靈魂,沒有對應的程序,單片機系統(tǒng)是無法完成任何動作的,解決所涉及的問題的。編寫程序必須對機器的指令系統(tǒng)非常的熟悉,而且不能脫離具體的機器,因此程序不能在不同的機器上通用。未了使本系統(tǒng)能夠成功運行,程序是必不可少的,所以這次編寫了一個主機程序,兩個從機程序。
6.1 主機程序如下:
#include《reg51.h》 #include《absacc.h》 #include《intrins.h》 unsigned char cort=0; sbit P3_5=P3^5;
/********************************* 按鍵掃描子程序
*********************************/ key_serial() interrupt 0 using 1
{
++cort; }
/********************************* 發(fā)送子程序
*********************************/ void master(void) { if(cort==1) { SBUF=0x01; while(TI!=1);TI=0; P3_5=0; SM2=0;
while (RI!=1);RI=0;
P2=SBUF;
SM2=1; P3_5=1;
}
if(cort==2) {
SBUF=0x02; while(TI!=1);TI=0; SM2=0; P3_5=0;
while(RI!=1);RI=0; P2=SBUF; SM2=1; P3_5=1;
}
if(cort==3)cort=1; SM2=1;
}
/***************主程序****************/ void main(void) {
P2=0xff; TMOD=0x20; TL1=0xfd; TH1=0xfd; PCON=0x00; TR1=1; SCON=0xf8; EA=1; EX0=1; IT0=1; P3_5=1;
while(1) {
master();
//發(fā)送
} }
6.2 從機1程序如下: #include《reg51.h》 #include《absacc.h》 #include《intrins.h》
unsigned char serial_receiver; sbit P3_5=P3^5;
/**************************************** 串行口中斷子程序
****************************************/ void serial (void) interrupt 4 using 1 { ES=0; RI=0;
if(SBUF==0x01)
{
P3_5=1; SM2=0; P1=0x10; SBUF=0x10;
while(TI!=1);TI=0;
}
SM2=1; ES=1;
P3_5=0;
}
/*****************主程序******************/
void main(void) { P1=0x00; TMOD=0x20; TL1=0xfd; TH1=0xfd; PCON=0x00; TR1=1; SCON=0xf0; EA=1; ES=1; P3_5=0; while(1) { _nop_();
}
6.3 從機2程序如下: #include《reg51.h》 #include《absacc.h》 #include《intrins.h》
unsigned char serial_receiver; sbit P3_5=P3^5;
/**************************************** 串行口中斷子程序
****************************************/ void serial (void) interrupt 4 using 1 { ES=0; RI=0;
if(SBUF==0x02)
{
P3_5=1; SM2=0; P1=0x80; SBUF=0x80;
while(TI!=1);TI=0;
} SM2=1; ES=1;
P3_5=0;
}
/*****************主程序******************/ void main(void) { P1=0x00; TMOD=0x20; TL1=0xfd; TH1=0xfd; PCON=0x00; TR1=1; SCON=0xf0; EA=1; ES=1; P3_5=0; while(1) { _nop_();