MSComm控件在中文Windows下的通信問題與處理方法_第1頁
MSComm控件在中文Windows下的通信問題與處理方法_第2頁
MSComm控件在中文Windows下的通信問題與處理方法_第3頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

MSComm控件在中文Windows下的通信問題與處理方法

摘要VB5.0/6.0的MSComm通信控件提供了一系列標(biāo)準(zhǔn)通信命令的接口,它允許建立串口連接,但在實際通信軟件設(shè)計過程中,MSComm控件并非像想像中那樣完美和容易控制,特別是在中文Windows下通信時更會出現(xiàn)問題。本文就MSComm控件在實際應(yīng)用中可能出現(xiàn)的問題以及編程技巧進(jìn)行探討。關(guān)鍵詞MsComm控件串口通信

處理1.MSComm控件的基礎(chǔ)理論一般說來,計算機都有一個或多個串行端口,它們依次為Com1、Com2、...。這些串口還提供了外部設(shè)備與PC進(jìn)行數(shù)據(jù)傳輸和通信的通道,這些串口在CPU和外設(shè)之間充當(dāng)解釋器的角色。當(dāng)字符數(shù)據(jù)從CPU發(fā)送給外設(shè)時,這些字符數(shù)據(jù)將被轉(zhuǎn)換成串行比特流數(shù)據(jù);當(dāng)接收數(shù)據(jù)時,比特流數(shù)據(jù)被轉(zhuǎn)換為字符數(shù)據(jù)傳遞給CPU。再進(jìn)一步說,在操作系統(tǒng)方面,Windows用通信驅(qū)動程序(COMM.DRV)調(diào)用API函數(shù)發(fā)送和接收數(shù)據(jù)。當(dāng)用通信控件或聲明調(diào)用API函數(shù)時,它們由COMM.DRV解釋并傳遞給設(shè)備驅(qū)動程序。作為一個VB程序員,要編寫通信程序,只需知道通信控件提供給Windows通信API函數(shù)的接口即可,換句話說,只需設(shè)定和監(jiān)視通信控件的屬性和事件即可。2.利用MSComm控件進(jìn)行數(shù)據(jù)的接收和發(fā)送搞清楚以上基本屬性和事件后就可以開始編寫通信程序了:在VB5.0/6.0中新建一個工程文件,添加MicrosoftCommcontrol5.0組件,在窗體Form1中加入Command命令按鈕并取名為cmdTest,MSComm控件取名為MSComm1,寫入以下代碼:PrivateSubcmdTest_Click()MSComm1.CommPort=1'設(shè)定Com1口IfMSComm1.PortOpen=FalseThen

MSComm1.Settings="9600,N,8,1"

'9600波特率,無校驗,8位數(shù)據(jù)位,1位停止位

MSComm1.PortOpen=True

'打開串口EndIfMSComm1.OutBufferCount=0

'清空發(fā)送緩沖區(qū)MSComm1.InBufferCount=0

'清空接收緩沖區(qū)'發(fā)送字符數(shù)據(jù),注意必須用回車符(vbCr)結(jié)束MSComm1.Output="Thisisagoodbook!"&vbCr'撥打電話號碼或發(fā)送AT命令MSComm1.Output="ATDT0294563622"&vbCr'發(fā)送字符數(shù)組數(shù)據(jù),注意ByteArray必須事先定義賦值DimByteArrayasbyte()

'定義動態(tài)數(shù)組

ReDimByteArray(1)'重定義數(shù)組大小

ByteArray(0)=0

ByteArray(1)=1

MSComm1.Output=ByteArray'發(fā)送字符數(shù)組數(shù)據(jù)EndSubPrivateSubMSComm1_OnComm()SelectCaseMSComm1.CommEvent

CasecomEvReceive'接收字符數(shù)據(jù)DimBufferAsVariantMSComm1.InputLen=0'當(dāng)InputMode屬性值為0(文本模式)時,變量中含String型數(shù)據(jù)。'當(dāng)InputMode屬性值為1(二進(jìn)制模式)時,變量中含Byte型數(shù)組數(shù)據(jù)。MSComm1.InputMode=comInputModeBinaryBuffer=MSComm1.Input

'接收二進(jìn)制數(shù)據(jù)MSComm1.InputMode=comInputModeTextBuffer=MSComm1.Input

CaseelseEndSelectEndSub3.中文Windows下的通信問題與解決方法3.1接收的數(shù)據(jù)少于發(fā)送的數(shù)據(jù)如果通過MSComm控件一次性傳送較多的二進(jìn)制數(shù)據(jù),那么,很可能收到的數(shù)據(jù)不足。例如在設(shè)置為2400bps傳輸率的情況下,一次性可以傳輸2048個字符數(shù)據(jù),那么在大多數(shù)情況下一次只能收到1200個字符左右,這是因為新版的MSComm32.OCX中存在一個影響傳輸二進(jìn)制數(shù)據(jù)的Bug。32位WindowsAPI函數(shù)使用了幾個用COMMTIMEOUTS結(jié)構(gòu)表示的限時變量,WriteTotalTimeOutConstant即是其中的一個,它被Windows內(nèi)部設(shè)定為5000(即5秒),這個常量決定了在通信驅(qū)動程序停止傳輸之前花費在發(fā)送緩沖區(qū)中數(shù)據(jù)的時間的長短。5秒鐘意味著通信速度為1200bps情況下僅能發(fā)送600個字符,2400bps情況下僅能發(fā)送1200個左右的字符。事實上,在一個緩沖區(qū)內(nèi)一次性發(fā)送更多的數(shù)據(jù)是非??赡艿摹B5.0/6.0版本的MSComm控件有一個新增的重要的屬性稱為CommID,CommID指的是當(dāng)串口被打開時,被API所調(diào)用的串口句柄(或標(biāo)志),這也意味著能利用API接口函數(shù)去修改這個常量。每次串口關(guān)閉后,Windows會自動將之恢復(fù)為5000,所以,每次打開串口后需要重新設(shè)定。以下是API聲明代碼:TypeCOMMTIMEOUTSReadIntervalTimeoutAsLongReadTotalTimeoutMultiplierAsLong

ReadTotalTimeoutConstantAsLong

WriteTotalTimeoutMultiplierAsLong

WriteTotalTimeoutConstantAsLongEndTypeDeclareFunctionSetCommTimeoutsLib"Kernel32"(ByValhFileAsLong,_lpCommTimeoutsAsCOMMTIMEOUTS)AsLongDeclareFunctionGetCommTimeoutsLib"Kernel32"(ByValhFileAsLong,_lpCommTimeoutsAsCOMMTIMEOUTS)AsLongDimtimeoutsAsCOMMTIMEOUTSDimRetAsLongIfComm1.PortOpen=FalseThen

Comm1.PortOpen=TrueEndIf'打開串口后重新設(shè)定串口句柄Ret=GetCommTimeouts(Comm1.CommID,timeouts)'Setsomedefaulttimeoutstimeouts.ReadIntervalTimeout=1timeouts.ReadTotalTimeoutMultiplier=1timeouts.ReadTotalTimeoutConstant=1timeouts.WriteTotalTimeoutMultiplier=1timeouts.WriteTotalTimeoutConstant=(Comm1.OutBufferSize\Val(Comm1.Settings))*10000+1000Ret=SetCommTimeouts(Comm1.CommID,timeouts)3.2如何發(fā)送大于128的字符數(shù)據(jù)在通信程序中,以單字符方式逐個發(fā)送數(shù)據(jù)時,每一個數(shù)據(jù)范圍為0-255(即十六進(jìn)制的00-FF)。在單字符版本的英文Windows或DOS版的BASIC程序中,只需要將相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成相應(yīng)的字符發(fā)送到通信端口即可。但在中文Windows下卻行不通,假設(shè)在中文Windows下運行以下程序:DimiasIntegerFori=0To255

MSComm1.Output=chr(i)Nexti希望在接收端得到預(yù)期的0-255之間的數(shù)據(jù),結(jié)果卻是:前129個數(shù)據(jù)接收正確,為0-128,后面127個數(shù)據(jù)為126個0和一個255。造成這種結(jié)果的原因在于中文Windows使用的是雙字節(jié)字符集(DBCS)系統(tǒng)。DBCS系統(tǒng)使用0-128之間的數(shù)字表示ASCII字符,大于128的數(shù)字僅作為前導(dǎo)字符,它只是顯示是一個非拉丁語系的字符,而并不代表實際意義。上述程序在調(diào)用CHR()函數(shù)時用到了DBCS字符集,因此產(chǎn)生了此類錯誤。那么,如何發(fā)送大于128的數(shù)據(jù)呢?答案是使用字節(jié)數(shù)組,將以上程序改為:DimMyData(255)AsByteFori=0To255

MyData(i)=iNextiMSComm1.Output=MyDataDo

DoEventsLoopUntilMSComm1.OutBufferCount=0'接收過程PrivateSubMSComm1_OnComm()

SelectCaseMSComm1.CommEventCasecomEvReceive

DimBufferAsVariant

MSComm1.InputMode=comInputModeBinary

MSComm1.InputLen=0

Buffer=MSComm1.Input

Fori=LBound(Buffer)ToUBound(Buffer)Text1.Text=Buffer(i);NextiCaseElseEndSelectEndSub3.3如何發(fā)送中文字符串VB5.0/6.0中可以直接把中文字符等同于英文字符發(fā)送,如:MSComm1.output="現(xiàn)在發(fā)送中文數(shù)據(jù)!",但這種方法發(fā)送的中文數(shù)據(jù)不能太長,發(fā)送緩沖區(qū)和接收緩沖區(qū)的大小需設(shè)定為中文字符的兩倍以上,而且發(fā)送與接收系統(tǒng)所處的操作系統(tǒng)版本最好要一致,否則會出現(xiàn)接收或發(fā)送緩沖區(qū)溢出之類的錯誤。這種方法可用于一般要求不太高的場合。除了上述方法外,還可以采用間接方式發(fā)送中文字符串。在發(fā)送端將漢字或字符轉(zhuǎn)換為機器內(nèi)碼或區(qū)位碼數(shù)據(jù)數(shù)組,然后將轉(zhuǎn)換后的數(shù)據(jù)發(fā)送到串口,在接收端接收到數(shù)據(jù)后,按照相反的順序?qū)⒌玫降臄?shù)據(jù)轉(zhuǎn)換為相應(yīng)的漢字或字符。在轉(zhuǎn)換過程中,要用到位運算,如取得漢字的內(nèi)碼后需要將高字節(jié)和低字節(jié)分開,而VB5.0/6.0中并沒有提供此類函數(shù),以下是求整數(shù)高、低字節(jié)的函數(shù)。PublicFunctionHiByte(aAsInteger)

DimbAsInteger

b=aAnd&HFF00

b=b/256

Ifb<0Thenb=b+256

HiByte=bEndFunction

PublicFunctionLowByte(aAsInteger)

DimbAsInteger

b=aAnd&HFF

LowByte=bEndFunction3.4如何在通信過程中進(jìn)行延時在某些通信過程中,常常需要在發(fā)送完一組數(shù)據(jù)后進(jìn)行一段延時,以等待對方處理上組數(shù)據(jù),以下是延時函數(shù)代碼。PublicSubDelay(PauseTimeAsSingle)

DimStartStart=Timer

'設(shè)定開始時間DoWhileTimer<Sta

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論