關于MSCOMM控件的一些說明第2/2頁
更新時間:2007年03月08日 00:00:00 作者:
二、中文Win 95/98下的通信問題與解決方法
1.接收的數據少于發(fā)送的數據
如果通過MSComm控件一次性傳送較多的二進制數據,那么,很可能收到的數據不足。例如在設置為24oobps傳輸率的情況下,
一次性可以傳輸2048個字符數據 那么在大多數情況下。一次只能收到1200個字符左右,這址出為新版的MSComm32.OCX中存在一
個影響傳輸二進制數據的臭蟲(bug).注意這不是特性。
32位Windows API函數(以下簡稱API)使用了幾個用COMMTIMEOUTS結構表示的限時變量,WriteTotalTimeOutConstant 即是其
中的一個,它被Windows內部設定為5000(即5秒),這個常量決定了在通信驅動程序停止傳輸之前花費在發(fā)送緩沖區(qū)中數據的時間
的長短,5秒鐘意味著通信速度為1200bps情況下僅能發(fā)送600個字符,24oobps情況下僅能發(fā)送1200個左右的字符。事實上,在一個
緩沖區(qū)內一次性發(fā)送更多的數據是非??赡艿摹_@個bug同樣也能引發(fā)問題,甚至在高速串口門通信情況下,即使系統在使用流控
制,無論叢軟件流(Xon/XofI)還是硬件流(CTS/RTS)。假如數據在發(fā)送緩沖區(qū)中時,流控制停止了傳輸,如果停止時間超過5
秒鐘.則數據就會丟失。在某些環(huán)境下,5秒鐘可能相當短.不過也不必擔心, VB 5.0/6.0版本的MSComm控件有一個新增的重要的
屬性稱為CommID, CommID指的是當串口被打開時,被API所調用的串口句柄或稱標志,這也意味著能利用API接口函數去修改這個
常量。每次串口關閉后,Windows會自動將之恢復為5000,所以,每次打開串口后需要重斬設定以下API聲明,其代碼見下程序。
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的字符數據
在通信程序中,以單字符方式逐個發(fā)送數據時,每一個數據范圍 0-255(即十六進制的00-FF)。在單字符版本的英文Win95或
DOS版的BASIC程序中,只需要將相應的數據轉換成相應的字符發(fā)送到通信端口即可。但在中文Win95/98下卻行不通,假設在中文
Win95/98下運行以下程序:
Dim i
For i=0 to 255
MSComm1.Output=chr(i)
Next i
希望在接收端得到預期的0-255之間的數據,結果卻是:前129個數據接收正確,為0-128,后面127個數據為126個0和一個255,
造成這種給果的原因在于中文Windows使用的是雙字節(jié)字符集(DBCS)系統。DBCS系統使用0-128之間的數字表示ASCII字符,大于
128的數字僅作為前導字符,它只是顯示是一個非拉丁語系的字符,而并不代表實際意義。上述程序在調用CHR()函數時用到了
DBCS字符集,岡此產生了此類錯誤。那么,如何發(fā)送人于128的數據呢?答案是使用字符數組,將以上程序改為:
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
'接收過程 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中只要注意以下兩點即可:
(1)設置MSComm控件的屬性 NullDiscard=False;。
(2)使用二進制接收,即用 MSComm1.InputMode=ComInputModeBinary便可以解決問題;
4.如何發(fā)送遞中文字符串(DBcS字符)
VB5.0/6.0的各種參考書上均指明MSComm通信控件不能發(fā)送或接收雙字節(jié)字符集系統DBCS)的二進制數據,這對于我國及亞洲一些
使用DBCS字符集的國家不能不說是一大人遺憾。但是我在實踐中發(fā)現,用MSComm控件也可以發(fā)送中文字符,具體方法有以下兩種:
(1)直接發(fā)送
直接發(fā)送即把中文字符等同于英文字符。如:MSComm1.Intput= " 這是一行中文數據!" ,但這種方法發(fā)送的中文數據不能太
長,發(fā)送緩沖區(qū)和接收緩沖區(qū)的大小需設定為中文字符的兩倍以上,而且發(fā)送與接收系統所處的操作系統版本最好要一致,否則會
出現接收或發(fā)送緩沖區(qū)溢出之類的錯誤。這種方法時用于一般要求不太高的場合。
(2)間接發(fā)送
在發(fā)送端將漢字或字符轉換為機器內碼或區(qū)位碼數據數組,然后將詠轉換后的數據發(fā)送到串口,在接收端接收到數據后,按照
相反的順序得到的數據轉換為相應的漢字或字符,在轉換過程中.要用到位運算,如取得漢字的內碼后需要將高字節(jié)和低字節(jié)分開,
而VB5.0/6.0中并沒有提供此類函數,以下是求整數高、低字節(jié)的函數。
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.如何用單機進行通信測試
通常在寫好了通信程序后需要兩臺PC或一臺Pc、一臺單片機.將通信口連接后進行測試,但很多時侯因條件限制僅有單臺PC機,
測試項目很簡單,那么能否測試呢?當然可以,而且方法也很簡單。對于九針的串口,找一個廢棄的串口鼠標,剝外鼠標線,將連
接2、3針的線對接即可;對于25針的串口,找一枚曲別針(最好有塑料外套的)將它扯直,剝削去兩頭的塑料后在兩頭各彎一個圓
圈,中間對忻后直接套接在串口的2、3針上即可。如果但心不夠安全,則可以將5針按地。
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
關于mscomm的用法,提高篇......[mgwmj]©
MSCOMM控件是個好東西,如果您能夠充分了解他,他會為您衷心的效勞。
大致看了一下下午有關討論MSCOMM的話題,覺得有必要說說我的心得,我一般只做硬件,沒有系統的學過軟件,只是業(yè)余時間
學學用用,多少掌握了一點,也在此拿出來玩玩,不知有錯沒有,我可是以為我已經做的很好了^_^
這是一個VB通用串口事件驅動接收程序。一次性接收一個數據包,數據包可以為任意字節(jié),保證不會丟失一個數據!
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 '只要有數據就收進來,哪怕只是一個
If (Timer - T > 0.01) Then '間隔10MS以上就認為是一個新的包
text1="" 'text1用于搜集和顯示接收(HEX格式)
N = 0
End If
T = Timer
For i = 0 To UBound(S) '一個數據包可能產生若干個oncomm事件
Text1.Text = Text1.Text & Right("0" & Hex(S(i)) & "H", 3) + " "
SS(N+i)=S(i) '接收數據包緩存于SS()
N=N+UBound(S)
Next i
End If
End Sub
相關文章
VB的32位程序在64位系統中出現文件和注冊表自動轉向的解決方法
這篇文章主要介紹了VB的32位程序在64位系統中出現文件和注冊表自動轉向的解決方法,需要的朋友可以參考下2014-07-07