?? 35.htm
字號:
<p>基于Win95的VB5串口通信程序</p>
<p> </p>
<p></p>
<p>山東省水文水資源勘測局 王 軍</p>
<p></p>
<p> VisualBasic5.0(以下簡稱VB)以其簡單易學(xué)、32位面向?qū)ο蟮某绦蛟O(shè)計(jì)等特點(diǎn),倍受廣大計(jì)算機(jī)開發(fā)者的青睞,已廣泛地應(yīng)用于各個領(lǐng)域;在實(shí)時監(jiān)測系統(tǒng)中串行端口通信是一項(xiàng)基礎(chǔ)功能,因此我們使用VB5編寫了實(shí)時水庫水文自動監(jiān)測系統(tǒng)的后臺機(jī)軟件。本文就Windows95環(huán)境中采用VB5設(shè)計(jì)串行端口通信程序進(jìn)行討論并給出實(shí)例。</p>
<p></p>
<p> 一般用VB開發(fā)串行通信程序有兩種方法:一是利用Windows的通信API函數(shù);另一種是采用VB標(biāo)準(zhǔn)控件Mscomm來實(shí)現(xiàn)。</p>
<p></p>
<p>Windows95的通信API</p>
<p></p>
<p> Windows95中的串口通信API函數(shù)不同于Windows3.x中的OpenComm、CloseComm、ReadComm、WriteComm,而是采用硬件與文件通用的函數(shù)CreateFile、ReadFile、WriteFile、CloseHandle,該類函數(shù)更具有一般性,并且可以用EscapeCommFunction函數(shù)實(shí)現(xiàn)底層硬件操作,比如:SETXOFF、CLRDTR等。</p>
<p> 利用API編寫串口通信程序較為復(fù)雜,需要掌握大量通信知識,其優(yōu)點(diǎn)是可實(shí)現(xiàn)的功能更豐富、應(yīng)用面更廣泛,更適合于編寫較為復(fù)雜的低層次通信程序。采用這種方法編寫串行端口通信程序一般可分為以下幾個過程: </p>
<p></p>
<p> 1.初始化串行端口</p>
<p></p>
<p> 首先用CreateFile函數(shù)打開指定串口,置參數(shù)中訪問類型為GENERIC_READ|GENERIC_WRITE、共享模式為0、創(chuàng)建標(biāo)志為OPEN_EXISTING、模板句柄為NULL。</p>
<p></p>
<p> 2.配置串口</p>
<p></p>
<p> Windows95的串口配置比Windows3.x較為復(fù)雜,但其功能更強(qiáng)大,對一般程序可使用CommConfigDialog函數(shù)以對話框方式設(shè)置波特率、數(shù)據(jù)位、奇偶校驗(yàn)、停止位和流控制方式,并且可以恢復(fù)缺省值。</p>
<p></p>
<p> 3.超時控制</p>
<p></p>
<p> 為了防止意外情況使串口讀寫無休止地等待,Windows95提供了超時設(shè)置,這是由COMMTIMEOUTS結(jié)構(gòu)定義的,通過調(diào)用GetCcommTimeOuts函數(shù)獲得當(dāng)前的設(shè)置,用SetCommTimeOuts函數(shù)來完成設(shè)置。</p>
<p></p>
<p> 4.數(shù)據(jù)傳輸</p>
<p></p>
<p> 讀寫串行端口與讀寫文件采用的函數(shù)相同,即ReadFile、WriteFile,讀寫操作可分四種方式:查詢方式、同步I/O、異步(后臺)I/O和事件驅(qū)動I/O。</p>
<p></p>
<p> 5.關(guān)閉串口</p>
<p></p>
<p> 程序的終止可以自動關(guān)閉串口,也可用函數(shù)CloseHandle(),以便釋放所獨(dú)占資源。</p>
<p></p>
<p>VB通信控件Mscomm</p>
<p></p>
<p> Mscomm控件提供了功能完善的串口數(shù)據(jù)的發(fā)送和接收功能,Mscomm控件具有兩種處理方式:1事件驅(qū)動方式:由Mscomm控件的OnComm事件捕獲并處理通信錯誤及事件;2查詢方式:通過檢查CommEvent屬性的值來判斷事件和錯誤。</p>
<p> Mscomm控件的通信功能實(shí)現(xiàn),實(shí)際上是調(diào)用了API函數(shù),而API函數(shù)是由Comm.drv解釋并傳給設(shè)備驅(qū)動程序執(zhí)行的,對于VB程序開發(fā)者只需知道Mscomm控件的屬性和事件的用法即可以實(shí)現(xiàn)串口的操作。</p>
<p></p>
<p> 以下是Mscomm控件的主要屬性和方法:</p>
<p></p>
<p> 1)CommPort:設(shè)置或返回串行端口號,其取值范圍為1~99,缺省為1。</p>
<p></p>
<p> 2)Setting設(shè)置或返回串行端口的波特率、奇偶校驗(yàn)位、數(shù)據(jù)位數(shù)、停止位。如:Mscomm.Setting="9600,N,8,1"。</p>
<p></p>
<p> 3)PortOpen:打開或關(guān)閉串行端口,格式為:Mscomm.PortOpen={TRUE|FALSE}。</p>
<p></p>
<p> 4)InBufferSize:設(shè)置或返回接收緩沖區(qū)的大小,缺省為1024字節(jié)。</p>
<p></p>
<p> 5)InBufferCount:返回接收緩沖區(qū)內(nèi)的等待讀取的字節(jié)個數(shù),可通過設(shè)置該屬性為0來清除接收緩沖區(qū)。</p>
<p></p>
<p> 6)RThreshold:該屬性為一閥值,它確定當(dāng)接收緩沖區(qū)內(nèi)字節(jié)個數(shù)達(dá)到或超過該值后就產(chǎn)生代碼為MSCOMM_EV_RECEIVE的OnComm事件。</p>
<p></p>
<p> 7)InputLen:設(shè)置或返回接收緩沖區(qū)內(nèi)用Input讀入的個數(shù)。若取0,則INPUT讀取整個緩沖區(qū)的內(nèi)容。</p>
<p></p>
<p> 8)Input:該屬性表示從接收緩沖區(qū)移走一串字符。</p>
<p></p>
<p> 9)OutBufferSize:設(shè)置或返回發(fā)送緩沖區(qū),缺省為512字節(jié)。</p>
<p></p>
<p> 10)OutBufferCounter:返回發(fā)送緩沖區(qū)內(nèi)等待發(fā)送的字符數(shù),可用來清空緩沖區(qū)。</p>
<p></p>
<p> 11)Output:向發(fā)送緩沖區(qū)傳送一字符串。</p>
<p></p>
<p> 12)EOFEnable:若置TRUE,則當(dāng)輸入中出現(xiàn)EOF,就停止輸入并產(chǎn)生OnComm事件。</p>
<p></p>
<p> 如果在通信過程中發(fā)生錯誤或事件,就會引發(fā)OnComm事件并且改變屬性值,由CommEvent屬性代碼反映錯誤類型,在通信程序的設(shè)計(jì)中可根據(jù)該屬性值來執(zhí)行不同的操作,以下是部分屬性常數(shù)值及其含義:</p>
<p></p>
<p> 1)ComEvSend:其值為1,發(fā)送緩沖區(qū)的內(nèi)容少于SThreshold指定的值。</p>
<p></p>
<p> 2)ComEvReceive:其值為2,接收緩沖區(qū)內(nèi)字符數(shù)達(dá)到RThreshold值,該事件在緩沖區(qū)中數(shù)據(jù)被移走前將持續(xù)產(chǎn)生。</p>
<p></p>
<p> 3)ComEventFrame:其值為1004,硬件檢測到幀錯誤。</p>
<p></p>
<p> 4)ComEventRxOver:其值為1008,接收緩沖區(qū)溢出。</p>
<p></p>
<p> 5)ComEventTxFull:其值為1010,發(fā)送緩沖區(qū)溢出。</p>
<p></p>
<p> 6)ComEventRxParity:其值為1009,奇偶校驗(yàn)。</p>
<p></p>
<p> 7)ComEvEOF:其值為7,接收數(shù)據(jù)中出現(xiàn)文件結(jié)束(ASCII碼為26)字符。</p>
<p></p>
<p>程序樣例</p>
<p></p>
<p> 采用Mscomm控件實(shí)現(xiàn)串口通信時,首先添加一Mscomm控件到窗體中,該控件一般不在通用工具窗口中,而是需通過菜單項(xiàng)"工程(P)→部件(O)"進(jìn)入選擇窗口,在控件tab頁中選取MicrosoftCommControl5.0,此時工具窗口中出現(xiàn)Mscomm圖標(biāo),即可被使用。</p>
<p> 以下是事件驅(qū)動方式的接收程序的主要部分:</p>
<p></p>
<p>PrivateSubgetdatafromserial_Click()</p>
<p> CommonDialog1.InitDir="c:\temp"</p>
<p> CommonDialog1.ShowSave</p>
<p> mainfrm.MSComm1.CommPort=1</p>
<p> hfile=FreeFile</p>
<p> '打開存儲接收數(shù)據(jù)的文件</p>
<p> Open CommonDialog1.filename For Output As #hfile</p>
<p> '設(shè)接收緩沖區(qū)的大小,可按量確定</p>
<p> mainfrm.MSComm1.InBufferSize=4096</p>
<p> If Not mainfrm.MSComm1.PortOpen Then'打開串口</p>
<p> mainfrm.MSComm1.PortOpen=True</p>
<p> End If</p>
<p> If Err Then</p>
<p> MsgBox"Communcationportcannotbeopened!!"</p>
<p> '清接收緩沖區(qū)</p>
<p> mainfrm.MSComm1.InBufferCount=0</p>
<p> '設(shè)一次讀入的長度,可根據(jù)數(shù)據(jù)格式設(shè)置</p>
<p> mainfrm.MSComm1.InputLen=77</p>
<p> '設(shè)置接收事件觸發(fā)的閥值</p>
<p> mainfrm.MSComm1.RThreshold=77</p>
<p> counter=Timer+10</p>
<p> Do</p>
<p> If Timer>counter Then</p>
<p> mainfrm.Label1.Caption="正在通信......"</p>
<p> mainfrm.Label1.Refresh</p>
<p> counter=Timer+10</p>
<p> End If</p>
<p> DoEvents</p>
<p> Loop</p>
<p>End Sub</p>
<p></p>
<p> 以下為事件處理子程序,flag為一靜態(tài)變量記錄讀取次數(shù),以便改變接收數(shù)據(jù)的長度,讀者可根據(jù)實(shí)際需要添加其它處理內(nèi)容:</p>
<p></p>
<p>Private Sub MSComm1_OnComm()</p>
<p> Select Case MSComm1.CommEvent</p>
<p> Case comEvReceive</p>
<p> If flag>246 Then</p>
<p> MSComm1.InputLen=0:MSComm1.RThreshold=32</p>
<p> End If</p>
<p> buffer=MSComm1.Input</p>
<p> temp=buffer</p>
<p> Print #hfile,temp</p>
<p> counter=Timer+10</p>
<p> Do While Timer>counter</p>
<p> DoEvents</p>
<p> Loop</p>
<p> flag=flag+1</p>
<p> Case comEvEOF</p>
<p> EVMsg$="檢測到文件結(jié)尾!!!"</p>
<p> Case comFrame</p>
<p> ERMsg$="幀出錯!!!"</p>
<p> Case comRxParity</p>
<p> ERMsg$="奇偶錯!!!"</p>
<p> End Select</p>
<p> If Len(EVMsg$) Then</p>
<p> Text1.Text="Status:"&EVMsg$</p>
<p> ElseIf Len(ERMsg$) Then</p>
<p> Text1.Text="Status:"&ERMsg$</p>
<p> Beep</p>
<p> Ret=MsgBox(ERMsg$,1,"ClickCanceltoquit,OKtoignore.")</p>
<p> MSComm1.PortOpen=False</p>
<p> End If</p>
<p>End Sub</p>
<p></p>
<p> </p>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -