WINDOWS環(huán)境下PC機與單片機的通信
在自動控制系統(tǒng)中,PC機與單片機組成上位機和下位機,其基本構(gòu)成是:下位機(單片機系統(tǒng))完成信號檢測、A/D轉(zhuǎn)換和簡單的控制功能,通過系統(tǒng)總線(如RS-232、RS-485、USB)與上位機(PC機)相連,進行監(jiān)測、控制,形成主從式結(jié)構(gòu)。下面就上位機和下位機之間目前幾種常用的通訊方法作一些介紹。
1、RS-232的串行通訊
在工業(yè)控制中,串口是常用的計算機與外部串行設(shè)備之間的數(shù)據(jù)傳輸通道,由于串行通信方便易行,成本低,且完全能滿足要求,所以應(yīng)用廣泛。
1.1、利用VC++的標準通信函數(shù)
利用VC++的標準通信函數(shù)_inp和_outp可實現(xiàn)串口通信。下面是一個串口初始化的程序:
Void init_com (PORT)
{char i;
outp(PORT+3,0x80);
outp(PORT,0x0C);
outp(PORT+1,0);
outp(PORT+3 ,0x3a);
outp(PORT+3 ,0x03);
i=inp(PORT+5) && 0xfe;
outp(PORT+5,i);}
1.2、使用串行通信控件MSComm
MSCOMM控件,即Microsoft Communication Control,是Microsoft為簡化Windows下串行通信編程而提供的ActiveX控件。它提供了一系列標準通信命令的使用接口,利用它可以建立與串口的連接,并可以通過串口連接到其他通信設(shè)備(如調(diào)制解調(diào)器),發(fā)出命令,交換數(shù)據(jù)以及監(jiān)視和響應(yīng)串行連接中發(fā)生的事件和錯誤。MSCOMM控件可用于創(chuàng)建電話撥號程序、串口通信程序和功能完備的終端程序。
串行通信控件MSComm32.OCX提供了使用RS-232來進行數(shù)據(jù)通信的所有協(xié)議,VC編程語言為該控件提供了標準的事件處理函數(shù)、過程,并通過屬性和方法提供了串行通信的設(shè)置。它使用戶能夠方便地訪問Windows串行通信驅(qū)動程序的大多數(shù)特性,包括輸入、輸出緩沖區(qū)的大小及決定何時使用流控制命令掛起數(shù)據(jù)傳輸?shù)取?/p>
在ClassWizard中為新創(chuàng)建的通信控件定義成員對象(CMSComm m_Serial),通過該對象便可以對串口屬性進行設(shè)置,MSComm控件共有27個屬性。如果需要通過多個串行口與多臺設(shè)備通信,那么每一個串行口對應(yīng)于一個單獨的MSComm控件。串行口的設(shè)置參數(shù)既可以在對話框編輯器里設(shè)定,也可以在程序代碼中通過調(diào)用CMSComm類的成員函數(shù)設(shè)定。例如,我們可以在MyCOMDlg類的OnInitDialog成員函數(shù)中初始化MSComm控件的參數(shù),代碼如下:
BOOL CMyCOMDlg::OnInitDialog ()
? {
CDialog::OnInitDialog ();
m_wndCOM1.SetCommPort(1);
m_wndCOM1.SetSettings("9600,e,7,1");
m_wndCOM1.SetRThreshold(1);
m_wndCOM1.SetSThreshold(0);?
m_wndCOM1.SetInputLen(1);?
m_wndCOM1.SetPortOpen(TRUE);
Return TRUE
?}
打開所需串口后,我們需要考慮串口通信的時機。在接收或發(fā)送數(shù)據(jù)過程中,可能需要監(jiān)視并響應(yīng)一些事件和錯誤,所以事件驅(qū)動是處理串行端口交互作用的一種非常有效的方法。使用OnComm事件和CommEvent屬性捕捉并檢查通信事件和錯誤的值。發(fā)生通信事件或錯誤時將觸發(fā)OnComm事件,CommEvent屬性的值將被改變,應(yīng)用程序通過檢查CommEvent屬性值并做出相應(yīng)的反應(yīng)。
如圖1是PC機與多個單片機連接的原理圖,圖2是其通信程序流程圖。
1.3、使用API函數(shù)
Windows 應(yīng)用程序要與標準串口通信,Windows函數(shù)庫中提供了24個低級函數(shù),這些函數(shù)為與外部設(shè)備的通信提供了基本的工具,文件輸入和文件輸出函數(shù)為通信資源句柄的打開、關(guān)閉以及執(zhí)行讀寫操作提供了基本的接口,Win32 API也包含一系列訪問通信資源的通信函數(shù),具體工作過程如下:首先打開一個通信資源句柄CreateFile(),接著進行串行通信資源的配置(包括波特率、奇偶校驗、停止位和數(shù)據(jù)位等信息),通過SetCommState()、GetCommState()進行修改和查詢完成初始化設(shè)置;串行通信資源的讀寫通過ReadFile()、WriteFile()來完成收發(fā)數(shù)據(jù),監(jiān)視串行通信資源某些可能發(fā)生的事件可通過WaitCommEvent()來完成,向與某通信資源相關(guān)的設(shè)備驅(qū)動程序發(fā)送控制命令,使驅(qū)動程序執(zhí)行特定任務(wù)。
控件雖然簡單易用,但由于必須拿到對話框中使用,在一些需要在線程中實現(xiàn)通信的應(yīng)用場合下,控件的使用顯得捉襟見肘。API是附帶在Windows內(nèi)部的一個極其重要的組成部分。Windows的32位API主要是一系列很復(fù)雜的函數(shù)和消息集合。它可以看作是Windows系統(tǒng)為在其下運行的各種開發(fā)系統(tǒng)提供的開放式通用功能增強接口。通信程序在CreateFile處指定串口設(shè)備及相關(guān)的操作屬性,再返回一個句柄,該句柄將被用于后續(xù)的通信操作,并貫穿整個通信過程。串口打開后,其屬性被設(shè)置為默認值,根據(jù)具體需要,通過調(diào)用GetCommState(hComm,&&dcb)讀取當前串口設(shè)備控制塊DCB設(shè)置,修改后通過 SetCommState(hComm,&&dcb)將其寫入。運用ReadFile()與WriteFile()這兩個API函數(shù)實現(xiàn)串口讀寫操作,若為異步通信方式,兩函數(shù)中最后一個參數(shù)為指向OVERLAPPED結(jié)構(gòu)的非空指針,在讀寫函數(shù)返回值為FALSE的情況下,調(diào)用 GetLastError()函數(shù),返回值為ERROR_IO_PENDING,表明I/O操作懸掛,即操作轉(zhuǎn)入后臺繼續(xù)執(zhí)行。此時,可以用 WaitForSingleObject()來等待結(jié)束信號并設(shè)置最長等待時間,舉例如下:
BOOL bReadStatus;
bReadStatus = ReadFile (m_hIDComDev, buffer,
dwBytesRead, &&dwBytesRead, &&m_OverlappedRead);
if (! bReadStatus){
if(GetLastError()==ERROR_IO_PENDING){
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
return ((int)dwBytesRead);}
return(0);}
return ((int)dwBytesRead);
1.4、多線程下的串行通信
Windows內(nèi)部的搶先調(diào)度程序在活動的線程之間分配CPU時間,Windows區(qū)分兩種不同類型的線程,一種是用戶界面線程(User Interface Thread),它包含消息循環(huán)或消息泵,用于處理接收到的消息;另一種是工作線程(Work Thread),它沒有消息循環(huán),用于執(zhí)行后臺任務(wù)、監(jiān)視串口事件的線程即為工作線程。多線程程序的編寫在端口的配置、連接部分與單線程的相同,在端口配置完畢后,最重要的是根據(jù)實際情況,建立多線程之間的同步對象,如信號燈、臨界區(qū)和事件等。多線程的實現(xiàn)可以使得各端口獨立,準確地實現(xiàn)串行通信,使串行通信具有更廣泛的靈活性與嚴格性,且充分利用CPU時間。但在具體的實時監(jiān)控系統(tǒng)中如何協(xié)調(diào)多個線程、線程之間以何種方式實現(xiàn)同步,這是多線程串行通信程序?qū)崿F(xiàn)的難點。
2、RS-485的串行通訊
RS-485與RS-232C相類似,其區(qū)別在于它使用了雙端平衡驅(qū)動及半雙工模式,這些措施使RS- 485傳輸距離更遠,同時,RS-485還可以組網(wǎng)。在同一個RS-485網(wǎng)絡(luò)中,可以多達32個模塊,某些器件可以多達256個甚至更多。相應(yīng)的,RS-485具有接收/發(fā)送控制端,RS-485的接收控制端可以在需要接收的時候打開或者一直打開以便無條件的接收線路上的數(shù)據(jù)。RS-485的發(fā)送控制端僅在需要發(fā)送時打開,平時應(yīng)關(guān)閉發(fā)送器,因為在同一RS-485網(wǎng)絡(luò)中在同一時刻僅允許一個發(fā)送器工作。在數(shù)據(jù)發(fā)送完成后關(guān)閉發(fā)送器。這可以通過以下兩種方法實現(xiàn)。①、在數(shù)據(jù)完全移出后,對于PC機為發(fā)送移位寄存器空,以MCS-51系列單片機為例則為TI置位。這些條件既可使用查詢的方法得到,也可以在中斷程序中實現(xiàn)。②、將RS-485的接收器始終打開,這樣一來,所有在RS-485上的數(shù)據(jù)均被接收回來,包括自己發(fā)送出去的數(shù)據(jù)。因此,當自己發(fā)送的數(shù)據(jù)完全被自己接收回來時即可關(guān)閉發(fā)送器。原則上說,這一方法無論是查詢或中斷方式都適用,但實際上,由于RS-485的數(shù)據(jù)通常打包后發(fā)送,因此,使用查詢的方法并不理想。這一方法非常適合中斷方式,尤其是以數(shù)據(jù)包傳送的RS-485通訊。
3、USB接口的通訊:
USB(通用串行總線Universal Serial Bus),其傳輸方式分為4種:控制傳輸,塊傳輸,同步傳輸和中斷傳輸。在實際開發(fā)中使用了控制傳輸和塊傳輸。控制傳輸主要用來完成主機對設(shè)備的各種控制操作,也就是用來實現(xiàn)位于主機上的USB總線驅(qū)動程序(USBD.SYS)以及編寫的功能驅(qū)動程序?qū)υO(shè)備的各種控制操作。塊傳輸主要用來完成主機和設(shè)備間的大批量數(shù)據(jù)傳輸以及對傳輸數(shù)據(jù)進行錯誤檢測(若發(fā)生錯誤,它支持"重傳"功能)。單片機系統(tǒng)控制USB控制器的工作過程可以簡單地概括為:當USB控制器從USB總線檢測到主機啟動的某一傳輸請求后,通過中斷方式將此請求通知單片機系統(tǒng),單片機系統(tǒng)通過訪問USB控制器的狀態(tài)寄存器和數(shù)據(jù)寄存器獲得與此次傳輸有關(guān)的各種參數(shù),并根據(jù)具體的傳輸參數(shù),對USB控制器的控制寄存器和數(shù)據(jù)寄存器進行相應(yīng)的操作,以完成主機的傳輸請求。USB設(shè)備驅(qū)動程序包括如下幾部分:
①初始化模塊提供一個入口函數(shù)DriverEntry(),所有對各種IRP(I/O Request Packet,IRP請求包)的處理例程都在此入口函數(shù)中做出定義。②即插即用管理模塊實現(xiàn)USB設(shè)備的熱拔插及動態(tài)配置。當硬件檢測到USB設(shè)備接入時,Windows查找響應(yīng)的驅(qū)動程序,并調(diào)用它的DriverEntry例程,PnP(即插即用)管理器調(diào)用驅(qū)動程序的AddDevice例程,告訴它添加了一個設(shè)備;在此處理過程中,驅(qū)動程序收到一個設(shè)備啟動請求(IRP_MN_START_DEVICE)的IRP。同理,當要拔除時,PnP管理器會發(fā)出一個設(shè)備刪除請求(IRP_MN_REMOVE_DEVICE)的IRP,由驅(qū)動程序進行處理。通過對這些PnP請求的處理,可支持設(shè)備的熱插拔和即插即用功能。③電源管理模塊負責設(shè)備的掛起與喚醒。④I/O功能實現(xiàn)模塊完成I/O請求的大部分工作。若應(yīng)用程序想對設(shè)備進行I/O操作,它便使用 Windows API函數(shù),對WIN32子系統(tǒng)進行WIN32調(diào)用。此調(diào)用由I/O系統(tǒng)服務(wù)接收并通知I/O管理器,I/O管理器將此請求構(gòu)造成一個合適的I/O請求包 (IRP)并把它傳遞給USB設(shè)備驅(qū)動程序,USB設(shè)備驅(qū)動程序接收到這個IRP以后,根據(jù)IRP中包含的具體操作代碼,構(gòu)造相應(yīng)的USB請求塊并把此 URB(USB請求塊)放到一個新的IRP中,然后把此IRP傳遞到USB總線驅(qū)動程序,USB總線驅(qū)動程序根據(jù)IRP中所含的URB執(zhí)行相應(yīng)的操作(如從USB設(shè)備讀取數(shù)據(jù)等),并把操作結(jié)果通過IRP返還給USB設(shè)備驅(qū)動程序。USB設(shè)備驅(qū)動程序接收到此IRP后,將操作結(jié)果通過IRP返還給I/O管理器,最后I/O管理器將此IRP中操作結(jié)果返還給應(yīng)用程序,至此應(yīng)用程序?qū)SB設(shè)備的一次I/O操作完成。
4、以上幾種通訊模式的比較
對于RS-232和RS-485兩種通訊方式,速度相對而言慢一點,但傳輸?shù)木嚯x遠,完全能滿足工業(yè)控制的要求,因而在工業(yè)控制領(lǐng)域得到了廣泛的應(yīng)用。我們知道PC機的串口個數(shù)是有限的,它在單片機較多的情況下要實現(xiàn)相互通訊有一定的困難。而USB接口的通訊方式是后起之秀,它的通訊速度快,但不能實現(xiàn)遠距離傳輸,而將RS-485與USB結(jié)合能有效地解決這一問題。
參考文獻
1.張念淮,江浩. USB總線接口開發(fā)指南. [M] 北京:國防工業(yè)出版社 .2002
2.李朝青. PC機及單片機數(shù)據(jù)通信技術(shù) [M] .北京:北京航空航天出版社 .2000
3.高登芳,潘承武,朱英杰. 微型計算機實用測控接口技術(shù) [M]. 北京:北京科學(xué)技術(shù)出版社 1990.
4.余永權(quán) 汪明慧 黃英 單片機在控制系統(tǒng)中的應(yīng)用 [M] 北京:電子工業(yè)出版社 2003
5.劉復(fù)華 8098單片機及其應(yīng)用系統(tǒng)設(shè)計 [M] 北京:清華大學(xué)出版社 1991