用 vb 開(kāi)發(fā) 通信軟件 一、PC串行通信程序機(jī)制 常用的PC串行通信程序大多利用BIOSINT14H中斷,以查詢(xún)I/O方式完成異步串行通信,
用vb開(kāi)發(fā)通信軟件VB
。 Windows系統(tǒng) 提供中斷方式驅(qū)動(dòng)的串行通信驅(qū)動(dòng)程序COMM.DRV。通信程序無(wú)需直接對(duì)串行端口進(jìn)行操作,而是通過(guò)驅(qū)動(dòng)程序這一編程接
用vb開(kāi)發(fā)通信軟件
一、PC串行通信程序機(jī)制
常用的PC串行通信程序大多利用BIOSINT14H中斷,以查詢(xún)I/O方式完成異步串行通信。
Windows系統(tǒng)提供中斷方式驅(qū)動(dòng)的串行通信驅(qū)動(dòng)程序COMM.DRV。通信程序無(wú)需直接對(duì)串行端口進(jìn)行操作,而是通過(guò)驅(qū)動(dòng)程序這一編程接口進(jìn)行間接操作。
Windows操作系統(tǒng)中,串行通信采用“事件通知”方式,支持?jǐn)?shù)據(jù)按塊傳送。進(jìn)行通信時(shí),Windows開(kāi)辟一個(gè)用戶(hù)定義的輸入輸出緩沖區(qū),每接收一個(gè)字符就產(chǎn)生一個(gè)低級(jí)硬件中斷,串行驅(qū)動(dòng)程序立即取得控制權(quán),并將字符放入輸入數(shù)據(jù)緩沖區(qū),然后將控制權(quán)返還正在運(yùn)行的應(yīng)用程序。如果輸入數(shù)據(jù)緩沖區(qū)滿(mǎn)了,驅(qū)動(dòng)程序用當(dāng)前定義的流控制機(jī)制通知發(fā)送方停止發(fā)送數(shù)據(jù)。發(fā)送數(shù)據(jù)也采用類(lèi)似的處理方式,應(yīng)用程序?qū)⑿枰l(fā)送的數(shù)據(jù)放入輸出數(shù)據(jù)緩沖區(qū),串口每發(fā)送一個(gè)字符就產(chǎn)生一個(gè)低級(jí)硬件中斷。
二、PC串行口遠(yuǎn)程通信的硬件配置
串行通信數(shù)據(jù)鏈中,計(jì)算機(jī)一端稱(chēng)為DTE,即數(shù)據(jù)終端設(shè)備;調(diào)制解調(diào)器一端稱(chēng)為DCE,即數(shù)據(jù)通信設(shè)備。PC串行通信的硬件連接方式分為零Modem連接和Modem連接。
零Modem連接即直接用調(diào)制解調(diào)器電纜將兩臺(tái)設(shè)備連接起來(lái),Modem連接則通過(guò)DCE(Modem)將兩臺(tái)PC連接起來(lái)。
零Modem連接用于距離15m內(nèi)兩臺(tái)DTE或DCE設(shè)備之間的連接。而Modem連接則通過(guò)電話(huà)網(wǎng)或?qū)>(xiàn)用于長(zhǎng)距離的通信。
TXD和RXD信號(hào)線(xiàn)用于計(jì)算機(jī)和Modem間傳輸數(shù)據(jù)信息;RTS從計(jì)算機(jī)端發(fā)送信號(hào)到Modem,表示希望把數(shù)據(jù)傳給Modem,若Modem能接收這個(gè)數(shù)據(jù),它將發(fā)送CTS信號(hào)給計(jì)算機(jī);DTR從計(jì)算機(jī)端發(fā)送信號(hào)到Modem,表示計(jì)算機(jī)已作好通信準(zhǔn)備,Modem將DTR信號(hào)作為初始化自己的信號(hào),然后給計(jì)算機(jī)回送數(shù)據(jù)設(shè)置就緒信號(hào)DSR;當(dāng)本地Modem接收到遠(yuǎn)地Modem的呼叫,則發(fā)送RING信號(hào)給計(jì)算機(jī);Modem應(yīng)答呼叫后,發(fā)送數(shù)據(jù)載波檢測(cè)DCD信號(hào)到計(jì)算機(jī),表示已建立連接。
Modem的工作狀態(tài)分為命令狀態(tài)和在線(xiàn)狀態(tài)。處于命令狀態(tài)時(shí),Modem對(duì)串口發(fā)送的信息進(jìn)行解釋?zhuān)赏ㄟ^(guò)PC串口向Modem發(fā)送AT命令對(duì)其進(jìn)行初始化、設(shè)置和操作。
例如,初始化命令為:“ATQOV1WOSOΚ1&C1&D2&YO&WO”,其含義為:
QO:返回結(jié)果碼;
V1:以字符形式顯示結(jié)果碼;
WO:不返回協(xié)商進(jìn)程結(jié)果碼;
SOΚ1:振鈴一次,即應(yīng)答;
&C1:追蹤數(shù)據(jù)載波信號(hào)CD;
&D2當(dāng)DTR從開(kāi)到關(guān)時(shí),Modem掛機(jī)進(jìn)入命令狀態(tài);
&YO:Modem上電時(shí)重新調(diào)出用戶(hù)方案;
&WO:將以上設(shè)置存為動(dòng)態(tài)設(shè)置用戶(hù)方案0;
一旦本地Modem與遠(yuǎn)地Modem建立連接,Modem即處于在線(xiàn)狀態(tài),可進(jìn)行數(shù)據(jù)傳輸。此時(shí),Modem不響應(yīng)AT命令,直接傳送所收到的數(shù)據(jù)。
三、Modem連接遠(yuǎn)程通信軟件的編制
通信過(guò)程中大部分的工作由串行通信驅(qū)動(dòng)軟件承擔(dān)。
本文軟件的運(yùn)行環(huán)境為AST+4/66d,Hayes公司的ACCURA144+FAX144Modem,Windows3.2,VB3.0專(zhuān)業(yè)版。VB3.0專(zhuān)業(yè)版中提供了一個(gè)MSCOMM.VBX通信控件。它使用戶(hù)能很方便地通過(guò)對(duì)控件屬性的設(shè)置、檢測(cè),訪(fǎng)問(wèn)串行通信驅(qū)動(dòng)程序的大多數(shù)特性,而不必考慮其實(shí)現(xiàn)細(xì)節(jié)。該控件為“事件驅(qū)動(dòng)”,只響應(yīng)“OnComm”事件,該事件可對(duì)已發(fā)生的事件或錯(cuò)誤進(jìn)行處理,與CommEvent屬性緊密相關(guān)。
通信軟件、通信驅(qū)動(dòng)軟件和Modem之間的通信關(guān)系
以下程序?qū)崿F(xiàn)了通信的基本過(guò)程。包括初始化串口和Modem,上位機(jī)撥號(hào)呼叫下位機(jī),下位機(jī)應(yīng)答并開(kāi)始定時(shí)傳輸數(shù)據(jù),掛機(jī)停止傳輸?shù)裙δ堋?/p>
VB3.0編制的通信軟件清單如下:
上位機(jī)控件清單:
控件名稱(chēng) 屬性
Form1Form1Caption ″上位機(jī)通信″
MsComm comm1
CommandButton1CallCaption ″撥號(hào)″
CommandButton2hangCaption ″掛機(jī)″
CommandButton3ExitCaption ″退出″
下位機(jī)控件清單
控件名稱(chēng) 屬性
Form1Form1Caption ″下位機(jī)通信″
MsComm comm1
CommandButton1hangCaption ″掛機(jī)″
CommandButton2ExitCaption ″退出″
Timer1Timer1Interval 3000
Text(i)Text(i)
1.串口初始化、設(shè)置程序
在程序初始化時(shí),先對(duì)串口初始化。因?yàn)槭褂肦TS/CTS握手信號(hào)的硬件設(shè)備只有RTS信號(hào)置為高才能接收數(shù)據(jù),所以需將MSCOMM通信控件的RTSenable屬性設(shè)為T(mén)RUE。由于Modem在處于命令狀態(tài)時(shí),通過(guò)串口發(fā)送的命令以及命令結(jié)果均會(huì)回顯在輸入緩沖區(qū)中,因此在進(jìn)入在線(xiàn)狀態(tài)前,禁止產(chǎn)生EV-RECEIVE事件,避免數(shù)據(jù)誤處理。
由于Windows是多任務(wù)系統(tǒng),在進(jìn)行數(shù)據(jù)收發(fā)循環(huán)處理時(shí),應(yīng)調(diào)用DOEVENTS事件,將控制權(quán)交還系統(tǒng),允許Windows執(zhí)行其他任務(wù)。但應(yīng)注意,在處理OnComm事件時(shí)小心使用DOEVENTS,避免系統(tǒng)又產(chǎn)生OnComm事件,造成嵌套,出現(xiàn)堆棧溢出錯(cuò)誤。
Sub Form-Load()
comm1.CommportΚ1′COM1口通信
comm1.SettingsΚ″9600,N,8,1″′波特率9600,無(wú)校驗(yàn),8位數(shù)據(jù)位1位停止位
comm1.OutBufferSizeΚOUTPACK′設(shè)置輸出緩沖區(qū)大小
comm1.InBufferSizeΚINPACK′設(shè)置輸入緩沖區(qū)大小
comm1.InputLenΚ1′每次從輸入緩沖區(qū)中取一個(gè)字符
comm1.RTSenableΚ-1′RTS信號(hào)為高
comm1.RthresholdΚ0′不產(chǎn)生MSCOMM-EV-RECEIVE事件
comm1.PortOpenΚ-1′打開(kāi)串口
cdΚcomm1.CDHolding′取載波檢測(cè)信號(hào)線(xiàn)原始狀態(tài)
comm1.outputΚ″ATQOV1WOSOΚ1&C1&D2&YOWO″′初始化Modem
Do DoEventsLoopUntilcomm1.OutBufferCountΚ0
End Sub
2.上位機(jī)撥號(hào)呼叫下位機(jī)
SubCallcom-Click()
Comm1.OutPutΚ″ATDT″&Phonnum$&chr$(13)′向Modem發(fā)撥號(hào)命令
Do DoEventsLoopUntilcomm1.OutBufferCountΚ0
End Sub
3.下位機(jī)Modem應(yīng)答,連通后開(kāi)始定時(shí)傳輸數(shù)據(jù)
下位機(jī)檢測(cè)CD,判斷是否連通:
Sub Comm1-OnComm()
Select Casecomm1.CommEvent
Case5 ′MSCOMM-EV-CD
Timer1.EnabledΚ-1′啟動(dòng)定時(shí)器
End Select
End Sub
VB傳送定長(zhǎng)字符串,數(shù)據(jù)接收處理相對(duì)簡(jiǎn)單,
電腦資料
《用vb開(kāi)發(fā)通信軟件VB》(http://www.lotusphilosophies.com)。但在發(fā)送實(shí)時(shí)數(shù)據(jù)時(shí),若將數(shù)據(jù)轉(zhuǎn)換成定長(zhǎng)字符串,這樣會(huì)大大降低傳輸效率。在接收端,通知程序從輸入緩沖區(qū)中取字符有兩種方法:一是用輪詢(xún)方法循環(huán)判斷InBufferCount是否為0;另外就是利用Rthreshold屬性觸發(fā)“OnComm”事件及“CommEvent”屬性中EV-RECEIVE事件。當(dāng)Rthreshold的值不為0時(shí),允許產(chǎn)生EV-RECEIVE事件。該屬性設(shè)置和返回在通信控件設(shè)定CommEvent特性為接收和產(chǎn)生OnComm事件之前要接收的字符數(shù)。VB傳送變長(zhǎng)字符串時(shí),接收端的Rthreshold值要作相應(yīng)的改變,以確保接收數(shù)據(jù)及時(shí)準(zhǔn)確。下位機(jī)定時(shí)發(fā)送字符串“strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$”。strin1$為當(dāng)前字符串,strin2$為上一字符串。上位機(jī)根據(jù)接收strin3$中Len(strin1$),相應(yīng)改變RthresholdΚLen(strin1$)+4。這樣,通過(guò)提前發(fā)送字符串長(zhǎng)度,改變Rthreshold值可實(shí)現(xiàn)發(fā)送變長(zhǎng)數(shù)據(jù)。
Windows串行通信驅(qū)動(dòng)程序的事件驅(qū)動(dòng)特性仍有不穩(wěn)定的缺陷。如InputLenΚ0時(shí),有可能取出不完整的數(shù)據(jù)。為保證可靠,采取降低處理速率的方法,保證下位機(jī)發(fā)送的數(shù)據(jù)流完整地進(jìn)入輸入緩沖區(qū)。設(shè)InputLenΚ1,即每次從緩沖區(qū)中取一個(gè)字符。也可采用輪詢(xún)方法,定時(shí)檢測(cè)輸入緩沖區(qū)。下位機(jī)定時(shí)發(fā)送數(shù)據(jù):
Sub Timer1-Timer()
If comm1.CDHoldingΙΛcdThen
str1$-text1(i).Text
strin2$Κstrin1$′上一字符串
strin1$Κstr1$′當(dāng)前字符串
strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$
′傳送當(dāng)前字符串長(zhǎng)度,以及上一字符串內(nèi)容
com m1.OutPutΚstrin3$
Do DoEventsLoopUntilcomm1.OutBufferCountΚ0
Else
Timer1.EnabledΚ0
End If
End Sub
上位機(jī)檢測(cè)CD狀態(tài),判斷是否連通、并接收處理數(shù)據(jù)。
Sub Comm1-OnComm()
Select Case comm1.CommEvent
Case5 ′MSCOMM-EV-CD檢測(cè)CD狀態(tài),判斷是否連通
comm1.InBufferCountΚ0′清輸入緩沖區(qū)
comm1.RThresholdΚ4′當(dāng)輸入緩沖區(qū)中有五個(gè)字符,
Case2′MSCOMM-EV-RECEIVE產(chǎn)生EV-RECEIVE事件,接收處理數(shù)據(jù)
Do DoEvents
Ifcomm1.InBufferCountThen′循環(huán)從緩沖區(qū)中取數(shù)據(jù)
str1$Κstr1$+comm1.Input
Else
Exit Do
End If
Loop
len2Κ1en1′當(dāng)前字符串長(zhǎng)度
len1ΚVa1(Left$(str1$,5))′即將發(fā)送的字符串長(zhǎng)度
comm1.RThresholdΚlen1+4
strin$ΚRight$(str1$,len2)′數(shù)據(jù)處理
……
End Select
str1$Κ″″
End Sub
4.根據(jù)設(shè)置的AT命令“&D2”,當(dāng)置DTR信號(hào)為低時(shí),Modem掛機(jī)進(jìn)入命令狀態(tài)。也可通過(guò)串口輸出““+++ATH”+chr$(13)”字符串掛機(jī)。
Sub Hang-click()
If comm1.CDHoldingΙΛcdThen′檢測(cè)CD,判斷是否掛機(jī)
comm1.DTRenableΚ0
comm1.DTRenableΚ-1′置DTR信號(hào)為高,為下一次通信準(zhǔn)備
End If
End Sub
5.退出程序時(shí),一定要關(guān)閉串口
Sub Exitcomm()
comm1.PortOpenΚfalse
End
End Sub
四、Windows通信機(jī)制和VB3.0通信控件潛在缺陷
在通信軟件編制過(guò)程中,我們發(fā)現(xiàn)Windows下通信機(jī)制采用的“事件驅(qū)動(dòng)”在實(shí)際運(yùn)行中不穩(wěn)定。如在文件傳輸過(guò)程中,誤碼和數(shù)據(jù)丟失的情況時(shí)有發(fā)生;若串口波特率過(guò)高,會(huì)產(chǎn)生無(wú)法通信或在通信過(guò)程中隨機(jī)掛機(jī)的情況。這主要是由于Windows本身通信機(jī)制和通信線(xiàn)路介質(zhì)及質(zhì)量的影響。為保證數(shù)據(jù)傳輸穩(wěn)定可靠,可采用通信協(xié)議如XModem-CRC或YModem。在MSCOMM.VBX通信控件中,Rthreshold屬性值大小與輸入緩沖區(qū)InBufferSize大小有關(guān),當(dāng)Rthreshold值較接近InBufferSize值時(shí),有可能不產(chǎn)生EV-RECEIVE事件,為保證產(chǎn)生該事件,可將InBufferSize值取得較大。
原文轉(zhuǎn)自:http://www.ltesting.net