關(guān)于MSCOMM控件的一些說(shuō)明
更新時(shí)間:2007年03月08日 00:00:00 作者:
二、中文Win 95/98下的通信問(wèn)題與解決方法
1.接收的數(shù)據(jù)少于發(fā)送的數(shù)據(jù)
如果通過(guò)MSComm控件一次性傳送較多的二進(jìn)制數(shù)據(jù),那么,很可能收到的數(shù)據(jù)不足。例如在設(shè)置為24oobps傳輸率的情況下,
一次性可以傳輸2048個(gè)字符數(shù)據(jù) 那么在大多數(shù)情況下。一次只能收到1200個(gè)字符左右,這址出為新版的MSComm32.OCX中存在一
個(gè)影響傳輸二進(jìn)制數(shù)據(jù)的臭蟲(chóng)(bug).注意這不是特性。
32位Windows API函數(shù)(以下簡(jiǎn)稱(chēng)API)使用了幾個(gè)用COMMTIMEOUTS結(jié)構(gòu)表示的限時(shí)變量,WriteTotalTimeOutConstant 即是其
中的一個(gè),它被Windows內(nèi)部設(shè)定為5000(即5秒),這個(gè)常量決定了在通信驅(qū)動(dòng)程序停止傳輸之前花費(fèi)在發(fā)送緩沖區(qū)中數(shù)據(jù)的時(shí)間
的長(zhǎng)短,5秒鐘意味著通信速度為1200bps情況下僅能發(fā)送600個(gè)字符,24oobps情況下僅能發(fā)送1200個(gè)左右的字符。事實(shí)上,在一個(gè)
緩沖區(qū)內(nèi)一次性發(fā)送更多的數(shù)據(jù)是非??赡艿摹_@個(gè)bug同樣也能引發(fā)問(wèn)題,甚至在高速串口門(mén)通信情況下,即使系統(tǒng)在使用流控
制,無(wú)論叢軟件流(Xon/XofI)還是硬件流(CTS/RTS)。假如數(shù)據(jù)在發(fā)送緩沖區(qū)中時(shí),流控制停止了傳輸,如果停止時(shí)間超過(guò)5
秒鐘.則數(shù)據(jù)就會(huì)丟失。在某些環(huán)境下,5秒鐘可能相當(dāng)短.不過(guò)也不必?fù)?dān)心, VB 5.0/6.0版本的MSComm控件有一個(gè)新增的重要的
屬性稱(chēng)為CommID, CommID指的是當(dāng)串口被打開(kāi)時(shí),被API所調(diào)用的串口句柄或稱(chēng)標(biāo)志,這也意味著能利用API接口函數(shù)去修改這個(gè)
常量。每次串口關(guān)閉后,Windows會(huì)自動(dòng)將之恢復(fù)為5000,所以,每次打開(kāi)串口后需要重?cái)卦O(shè)定以下API聲明,其代碼見(jiàn)下程序。
Type COMMTIMEOUTS
ReadIntervalTimeout As Long
ReadTotalTimeoutMultiplier As Long
ReadTotalTimeoutConstant As Long
WriteTotalTimeoutMultiplier As Long
WriteTotalTimeoutConstant As Long
End Type
Declare Function SetCommTimeouts Lib "Kernel32"
(BYVal hFile As Long, lpComm TimeoutsAs COMMTIMEOUTS) As Long
Declare Function GetCommTimeouts Lib "Kernel32"
(ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Dim timeouts As COMMEOUTS
Dim Ret As Long
If Comm1.PortOpen = False Then
Comm1.PortOpen = True
End if
Ret=GetCommTimeouts ( Comm1.CommID , timeouts )
'Set some default timeouts
timeOuts.ReadIntervalTimeout = 1
timeouts.ReadTotalTimeoutMultiplier =1
timeouts.ReadTotalTimeoutConstant =1
timeouts.WriteTotalTimeoutMultiplier =1
timeouts.WriteTotalTimeoutConstant=
( Comm1.OutBufferSize\Val(Comm1.Settings))*10000+1000
Ret=SetCommTimeouts( Comm1.CommID , timeouts )
( 程序2)
2.如何發(fā)送大于128的字符數(shù)據(jù)
在通信程序中,以單字符方式逐個(gè)發(fā)送數(shù)據(jù)時(shí),每一個(gè)數(shù)據(jù)范圍 0-255(即十六進(jìn)制的00-FF)。在單字符版本的英文Win95或
DOS版的BASIC程序中,只需要將相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成相應(yīng)的字符發(fā)送到通信端口即可。但在中文Win95/98下卻行不通,假設(shè)在中文
Win95/98下運(yùn)行以下程序:
Dim i
For i=0 to 255
MSComm1.Output=chr(i)
Next i
希望在接收端得到預(yù)期的0-255之間的數(shù)據(jù),結(jié)果卻是:前129個(gè)數(shù)據(jù)接收正確,為0-128,后面127個(gè)數(shù)據(jù)為126個(gè)0和一個(gè)255,
造成這種給果的原因在于中文Windows使用的是雙字節(jié)字符集(DBCS)系統(tǒng)。DBCS系統(tǒng)使用0-128之間的數(shù)字表示ASCII字符,大于
128的數(shù)字僅作為前導(dǎo)字符,它只是顯示是一個(gè)非拉丁語(yǔ)系的字符,而并不代表實(shí)際意義。上述程序在調(diào)用CHR()函數(shù)時(shí)用到了
DBCS字符集,岡此產(chǎn)生了此類(lèi)錯(cuò)誤。那么,如何發(fā)送人于128的數(shù)據(jù)呢?答案是使用字符數(shù)組,將以上程序改為:
Dim cc(255) As Byte
For i = 0 To 255
cc(i) = i
Next i
MSComm1.Output = cc
Do
DoEvents
Loop Until MSComm1.OutBufferCount = 0
'接收過(guò)程 MSComm1_OnComm()
Select Case MSComm1.CommEvent
Case comEvReceive
Dim Buffer As Variant, b1,i
MSComm1.InputMode=comInputModeBinery
MSComm1.InputLen = 0
Buffer = MSComm1.Input
For i=LBound (Buffer) To UBound (Buffer )
Debug.Print Buffer ( i ) ;
Next i
Case . . . . .
3.如何發(fā)送0字符(00H,NULL)
在VisuaI C++中使用串口控件發(fā)送0字符有些麻煩,但在VB5.0/6.0中只要注意以下兩點(diǎn)即可:
(1)設(shè)置MSComm控件的屬性 NullDiscard=False;。
(2)使用二進(jìn)制接收,即用 MSComm1.InputMode=ComInputModeBinary便可以解決問(wèn)題;
4.如何發(fā)送遞中文字符串(DBcS字符)
VB5.0/6.0的各種參考書(shū)上均指明MSComm通信控件不能發(fā)送或接收雙字節(jié)字符集系統(tǒng)DBCS)的二進(jìn)制數(shù)據(jù),這對(duì)于我國(guó)及亞洲一些
使用DBCS字符集的國(guó)家不能不說(shuō)是一大人遺憾。但是我在實(shí)踐中發(fā)現(xiàn),用MSComm控件也可以發(fā)送中文字符,具體方法有以下兩種:
(1)直接發(fā)送
直接發(fā)送即把中文字符等同于英文字符。如:MSComm1.Intput= " 這是一行中文數(shù)據(jù)!" ,但這種方法發(fā)送的中文數(shù)據(jù)不能太
長(zhǎng),發(fā)送緩沖區(qū)和接收緩沖區(qū)的大小需設(shè)定為中文字符的兩倍以上,而且發(fā)送與接收系統(tǒng)所處的操作系統(tǒng)版本最好要一致,否則會(huì)
出現(xiàn)接收或發(fā)送緩沖區(qū)溢出之類(lèi)的錯(cuò)誤。這種方法時(shí)用于一般要求不太高的場(chǎng)合。
(2)間接發(fā)送
在發(fā)送端將漢字或字符轉(zhuǎn)換為機(jī)器內(nèi)碼或區(qū)位碼數(shù)據(jù)數(shù)組,然后將詠轉(zhuǎn)換后的數(shù)據(jù)發(fā)送到串口,在接收端接收到數(shù)據(jù)后,按照
相反的順序得到的數(shù)據(jù)轉(zhuǎn)換為相應(yīng)的漢字或字符,在轉(zhuǎn)換過(guò)程中.要用到位運(yùn)算,如取得漢字的內(nèi)碼后需要將高字節(jié)和低字節(jié)分開(kāi),
而VB5.0/6.0中并沒(méi)有提供此類(lèi)函數(shù),以下是求整數(shù)高、低字節(jié)的函數(shù)。
Public Function HiByte(a As Integer )
Dim b
b= a And &HFF00
b = b / 256
If b<0 Then b = b + 256
HiByte = b
End Function
Public Function LowByte(a As Integ`er)
Dim b
b = a And &HFF
LowByte = b
End Function
5.如何用單機(jī)進(jìn)行通信測(cè)試
通常在寫(xiě)好了通信程序后需要兩臺(tái)PC或一臺(tái)Pc、一臺(tái)單片機(jī).將通信口連接后進(jìn)行測(cè)試,但很多時(shí)侯因條件限制僅有單臺(tái)PC機(jī),
測(cè)試項(xiàng)目很簡(jiǎn)單,那么能否測(cè)試呢?當(dāng)然可以,而且方法也很簡(jiǎn)單。對(duì)于九針的串口,找一個(gè)廢棄的串口鼠標(biāo),剝外鼠標(biāo)線,將連
接2、3針的線對(duì)接即可;對(duì)于25針的串口,找一枚曲別針(最好有塑料外套的)將它扯直,剝削去兩頭的塑料后在兩頭各彎一個(gè)圓
圈,中間對(duì)忻后直接套接在串口的2、3針上即可。如果但心不夠安全,則可以將5針按地。
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
關(guān)于mscomm的用法,提高篇......[mgwmj]©
MSCOMM控件是個(gè)好東西,如果您能夠充分了解他,他會(huì)為您衷心的效勞。
大致看了一下下午有關(guān)討論MSCOMM的話題,覺(jué)得有必要說(shuō)說(shuō)我的心得,我一般只做硬件,沒(méi)有系統(tǒng)的學(xué)過(guò)軟件,只是業(yè)余時(shí)間
學(xué)學(xué)用用,多少掌握了一點(diǎn),也在此拿出來(lái)玩玩,不知有錯(cuò)沒(méi)有,我可是以為我已經(jīng)做的很好了^_^
這是一個(gè)VB通用串口事件驅(qū)動(dòng)接收程序。一次性接收一個(gè)數(shù)據(jù)包,數(shù)據(jù)包可以為任意字節(jié),保證不會(huì)丟失一個(gè)數(shù)據(jù)!
Private Sub MSComm_OnComm()
Dim S() As Byte
Dim SS(1024) As Byte
Static N As Long
Static T As Variant
If (MSComm.CommEvent = comEvReceive) Then
S = MSComm.Input '只要有數(shù)據(jù)就收進(jìn)來(lái),哪怕只是一個(gè)
If (Timer - T > 0.01) Then '間隔10MS以上就認(rèn)為是一個(gè)新的包
text1="" 'text1用于搜集和顯示接收(HEX格式)
N = 0
End If
T = Timer
For i = 0 To UBound(S) '一個(gè)數(shù)據(jù)包可能產(chǎn)生若干個(gè)oncomm事件
Text1.Text = Text1.Text & Right("0" & Hex(S(i)) & "H", 3) + " "
SS(N+i)=S(i) '接收數(shù)據(jù)包緩存于SS()
N=N+UBound(S)
Next i
End If
End Sub
相關(guān)文章
VB簡(jiǎn)單實(shí)現(xiàn)防止文件被改寫(xiě)
這篇文章主要介紹了VB簡(jiǎn)單實(shí)現(xiàn)防止文件被改寫(xiě)的方法,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2015-06-06VB的32位程序在64位系統(tǒng)中出現(xiàn)文件和注冊(cè)表自動(dòng)轉(zhuǎn)向的解決方法
這篇文章主要介紹了VB的32位程序在64位系統(tǒng)中出現(xiàn)文件和注冊(cè)表自動(dòng)轉(zhuǎn)向的解決方法,需要的朋友可以參考下2014-07-07VB中使用WMI獲取系統(tǒng)硬件和軟件有關(guān)信息
WMI是英文Windows Management Instrumentation的簡(jiǎn)寫(xiě),它的功能主要是:訪問(wèn)本地主機(jī)的一些信息和服務(wù),可以管理遠(yuǎn)程計(jì)算機(jī)(當(dāng)然你必須要擁有足夠的權(quán)限),比如:重啟,關(guān)機(jī),關(guān)閉進(jìn)程,創(chuàng)建進(jìn)程等2019-04-04VBA中連接SQLSERVER數(shù)據(jù)庫(kù)例子
這篇文章主要介紹了VBA中連接SQLSERVER數(shù)據(jù)庫(kù)例子,VBA是指Visual Basic for Applications,是Visual Basic的一種宏語(yǔ)言,需要的朋友可以參考下2014-07-07VB使用shell函數(shù)打開(kāi)外部exe程序的實(shí)現(xiàn)方法
這篇文章主要介紹了VB使用shell函數(shù)打開(kāi)外部exe程序的實(shí)現(xiàn)方法,是非常實(shí)用的一個(gè)功能,需要的朋友可以參考下2014-07-07VB使用ADO操作Access數(shù)據(jù)庫(kù)
這篇文章主要介紹了VB使用ADO操作Access數(shù)據(jù)庫(kù)的相關(guān)資料,需要的朋友可以參考下2015-06-06VB使用XMLHTTP實(shí)現(xiàn)Post與Get的方法
這篇文章主要介紹了VB使用XMLHTTP實(shí)現(xiàn)Post與Get的方法,有一定的借鑒價(jià)值,需要的朋友可以參考下2014-07-07