----在通用聲明中定義程序所用變量:
Dim ab(4) As Byte
‘字節(jié)數(shù)據(jù)類型數(shù)組,用來存儲(chǔ)接收到的一組字節(jié)數(shù)據(jù)
Dim av As Variant ‘用來從接收緩沖區(qū)讀取數(shù)據(jù)
Dim i As Integer
Dim j As Integer
Dim w As Integer ‘接收數(shù)據(jù)個(gè)數(shù)計(jì)數(shù)器
Dim b1 As Single
Dim b2 As Single
Dim WW As Single ‘十進(jìn)制檢測(cè)值
Dim MaxW As Single ‘最大值
Dim MinW As Single ‘最小值
----在窗體中添加名為Command1的[開始]按鈕和名為 MSComm1的MSComm控件。
---- [開始]按鈕的Click事件處理程序主要是對(duì)MSComm1控制的參數(shù)初始化設(shè)置,程序中大部分參數(shù)在設(shè)計(jì)時(shí)可在MSComm1控制的屬性窗口中設(shè)置:
Private Sub Command1_Click()
‘開始按鈕
With MSComm1
.CommPort=2 ‘使用COM2
.Setting=“9600,N,8,1" ‘設(shè)置通信口參數(shù)
.InBufferSize=40
‘設(shè)置MSComm1接收緩沖區(qū)為40字節(jié)
.OutBufferSize=2
‘設(shè)置MSComm1發(fā)送緩沖區(qū)為2字節(jié)
.InputMode = comInputModeBinary
‘設(shè)置接收數(shù)據(jù)模式為二進(jìn)制形式
.InputLen = 1
‘設(shè)置Input 一次從接收緩沖讀取字節(jié)數(shù)為1
.SThreshold = 1
‘設(shè)置Output 一次從發(fā)送緩沖讀取字節(jié)數(shù)為1
.InBufferCount = 0 ‘清除接收緩沖區(qū)
.OutBufferCount = 0 ‘清除發(fā)送緩沖區(qū)
MaxW = -99
‘最大值賦初值
MinW = 99 ‘最小值賦初值
w = 0
‘?dāng)?shù)據(jù)個(gè)數(shù)計(jì)數(shù)器清零
.RThreshold = 1
‘設(shè)置接收一個(gè)字節(jié)產(chǎn)生OnComm事件
If .PortOpen = False Then
‘判斷通信口是否打開
.PortOpen = True ‘打開通信口
If Err Then ‘錯(cuò)誤處理
MsgBox “串口通信無效"
Exit Sub
End If
End If
End With
End Sub
----MSComm1_OnComm的事件處理程序只處理 comEvReceive事件,首先判斷幀數(shù)據(jù)的開始字節(jié),關(guān)閉OnComm接收事件,然后接收數(shù)據(jù)字節(jié),將壓縮BCD進(jìn)行還原轉(zhuǎn)換,再接收符號(hào)字節(jié),判斷數(shù)據(jù)符號(hào),判斷數(shù)據(jù)最大最小值,最后打開OnComm接收事件,等待下一次OnComm事件產(chǎn)生:
Private Sub MSComm1_OnComm()
With MSComm1
Select Case .CommEvent
‘判斷MSComm1通信事件
Case comEvReceive
‘收到Rthreshold個(gè)字節(jié)產(chǎn)生的接收事件
av = .Input
‘讀取一個(gè)接收字節(jié)
ab(1) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
If ab(1) = &HF0 Then
‘判斷是否為數(shù)據(jù)開始標(biāo)志
RThreshold = 0
‘關(guān)閉OnComm事件接收
Do
DoEvents
Loop Until .InBufferCount >= 3
‘循環(huán)等待MSComm1接收緩沖區(qū)>=3個(gè)字節(jié)
w = w + 1 ‘計(jì)數(shù)器累加計(jì)數(shù)
av = .Input
‘讀取第二個(gè)數(shù)據(jù)字節(jié)(BCD碼高位字節(jié))
ab(2) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .Input
‘讀取第三個(gè)數(shù)據(jù)字節(jié)(BCD碼低位字節(jié))
ab(3) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .Input
‘讀取第四個(gè)數(shù)據(jù)字節(jié)(符號(hào)位字節(jié))
ab(4) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
b1 = ab(2) - 6 * (ab(2)\16)
‘高位字節(jié)壓縮BCD碼轉(zhuǎn)換為實(shí)數(shù)
b2 = ab(3) - 6 * (ab(3)\16)
‘低位字節(jié)壓縮BCD碼轉(zhuǎn)換為實(shí)數(shù)
WW = b1 + b2 / 100
‘?dāng)?shù)值組合,標(biāo)定小數(shù)點(diǎn)
If ab(4) > 127 Then WW=?WW
‘判斷數(shù)據(jù)符號(hào)位
Label1(0) = Format(WW, “0.00")
‘顯示毫米單位數(shù)值,2位小數(shù)
Label1(1) =Format(WW /25.4, “0.000")
‘顯示英寸單位數(shù)值,3位小數(shù)
If WW > MaxW And WW < 51 Then
----‘判斷最大值,儀表在剛開始工作時(shí)有干擾,會(huì)傳導(dǎo)一些亂碼,位移傳感器有參數(shù)偏差,最大值一般都略大于50毫米,所以取51為極限最大值,取-51為極限最小值。
MaxW = WW
Label1(2) = Format(MaxW, “0.00")
‘顯示毫米單位最大值,2位小數(shù)
Label1(3) = Format(MaxW/25.4,“0.000")
‘顯示英寸單位最大值,3位小數(shù)
End If
If WW < MinW And WW > -51 Then
‘判斷最小值
MinW = WW
Label1(4) = Format(MinW, “0.00")
‘顯示毫米單位最小值,2位小數(shù)
Label1(5) = Format(MinW/25.4,“0.000")
‘顯示英寸單位最小值,3位小數(shù)
End If
.RThreshold = 1
‘打開MSComm1事件接收
End If
Case Else
End Select
End With
End Sub
VB有一個(gè)例子在Samples\CompTool\Mscomm中。你可以利用這個(gè)例子來學(xué)習(xí)串口編程。
打開串口先設(shè)置CommPort屬性(端口號(hào)),使用PortOpen=True就可以了。
串口數(shù)據(jù)保存在MSComm的Input屬性中。你可以使用下面的代碼:
Dim v As Variant
v = MSComm1.Input
For i = 0 To MSComm1.InBufferCount - 1
Debug.Print v(i)
Next
現(xiàn)有電子秤一臺(tái),使用串口與計(jì)算機(jī)進(jìn)行通訊。編寫VB程序來訪問串口,達(dá)到讀取電子秤上顯示的數(shù)據(jù)。該電子秤為BE01型儀表,輸出為RS-232C標(biāo)準(zhǔn)接口,波特率為300-9600、偶校驗(yàn)、7個(gè)數(shù)據(jù)位、2個(gè)停止位。所有字符均發(fā)送11位ASCII碼,一個(gè)起始位。在VB中與串口通訊需要引入控件MSComm串口通訊控件(在Microsoft Comm Control 6.0中)。具體程序如下:控件簡稱:MSC
Dim Out(12) As Byte '接收var中的值
Dim var As Variant '接收MSC.input中的數(shù)值
Dim nRece As Integer '計(jì)算MSC.inputbuffer的個(gè)數(shù)
Dim i As Integer, j As Integer '隨即變量,計(jì)算循環(huán)
Private Sub ClearText()
Text3.Text = ""
Text2.Text = "5"
Text1.Text = ""
End Sub
Private Sub Command1_Click()
ClearText
' nRece = 0 '計(jì)數(shù)器清零
With MSC
.InputMode = comInputModeBinary '設(shè)置數(shù)據(jù)接收模式為二進(jìn)制形式
.InBufferCount = 0 '清除接收緩沖區(qū)
If Not .PortOpen Then
.PortOpen = True '打開通信端口
End If
End With
End Sub
Private Sub MSC_OnComm()
DelayTime ‘用來延續(xù)時(shí)間
ClearText
With MSC
Select Case .CommEvent '判斷通信事件
Case comEvReceive: '收到Rthreshold個(gè)字節(jié)產(chǎn)生的接收事件
SwichVar 1
If Out(1) = 2 Then '判斷是否為數(shù)據(jù)的開始標(biāo)志
.RThreshold = 0 '關(guān)閉OnComm事件接收
End If
Do
DoEvents
Loop Until .InBufferCount >= 3 '循環(huán)等待接收緩沖區(qū)>=3個(gè)字節(jié)
' nRece = nRece + 1
For i = 2 To 12
SwichVar i
Text1.Text = Text1.Text & Chr(Out(i))
Next
Text1.Text = LTrim(Text1.Text)
Text2.Text = Text2.Text & CStr(nRece)
.RThreshold = 1 '打開MSComm事件接收
Case Else
' .PortOpen = False
End Select
End With
Private Sub MSComm_OnComm ()
Select Case MSComm1.CommEvent
' 錯(cuò)誤
Case comEventBreak ' 收到 Break。
Case comEventCDTO ' CD (RLSD) 超時(shí)。
Case comEventCTSTO ' CTS Timeout。
Case comEventDSRTO ' DSR Timeout。
Case comEventFrame ' Framing Error
Case comEventOverrun '數(shù)據(jù)丟失。
Case comEventRxOver'接收緩沖區(qū)溢出。
Case comEventRxParity' Parity 錯(cuò)誤。
Case comEventTxFull '傳輸緩沖區(qū)已滿。
Case comEventDCB '獲取 DCB] 時(shí)意外錯(cuò)誤
' 事件
Case comEvCD ' CD 線狀態(tài)變化。
Case comEvCTS ' CTS 線狀態(tài)變化。
Case comEvDSR ' DSR 線狀態(tài)變化。
Case comEvRing ' Ring Indicator 變化。
Case comEvReceive ' 收到 RThreshold # of chars.
Case comEvSend ' 傳輸緩沖區(qū)有 Sthreshold 個(gè)字符 '
Case comEvEof ' 輸入數(shù)據(jù)流中發(fā)現(xiàn) EOF 字符
Private Sub TmrComm_Timer()
'采用輪循法采集數(shù)據(jù)
Dim Rx_buff() As Byte
Dim okstring As String
Dim ReceivedLen As Integer
On Error GoTo ErrorHandler
TmrComm.Enabled = False '關(guān)閉定時(shí)器
If commport.InBufferCount > 0 Then
ReceivedLen = commport.InBufferCount
Rx_buff = commport.Input
okstring = StrConv(tempbyte, vbUnicode)
If ReceivedLen = 6 Then
If Chr(tempbyte(0)) = ":" And tempbyte(3) = &h0a Then
....
End If
If Instr(okstring ,":@END*",vbBinaryCompare) Then
....
End If
End If
TmrComm.Enabled = True '打開定時(shí)器
End Sub
Function sComm(sCommand As String, comReceive As MSComm) As String
Dim nReceiveCount As Integer
If comReceive.PortOpen = False Then
comReceive.PortOpen = True
End If
comReceive.Output = sCommand
Do
nReceiveCount = comReceive.InBufferCount
sleep (2) 'API 函數(shù),掛起當(dāng)前進(jìn)程一段時(shí)間
Loop Until comReceive.InBufferCount = nReceiveCount
If comReceive.PortOpen = True Then
sComm = comReceive.Input
End If
End Function
注:此函數(shù)參照了xth一文。
此法一般是能確保數(shù)據(jù)接收的正確,但由于WINDOWS是多任務(wù)操作系統(tǒng),當(dāng)有耗時(shí)的進(jìn)程運(yùn)行時(shí)會(huì)丟失數(shù)據(jù)。如果系統(tǒng)會(huì)出現(xiàn)這種情況,可增大函數(shù)sleep()的參數(shù)值。
JY
1999.10
A:經(jīng)CHR(206)+CHR(210)轉(zhuǎn)換后實(shí)際上變成了兩個(gè)UNICODE字符,四個(gè)字節(jié)了。漢字的收發(fā)必須用BINARY方式。下面的程序能實(shí)現(xiàn)漢字收發(fā)。
發(fā):
Dim ytemp() As Byte
Dim stemp As String
stemp = "你好!"
ytemp = StrConv(stemp, vbFromUnicode)
Debug.Print UBound(ytemp)
MSComm1.Output = ytemp
收:
Private Sub mscTest_OnComm()
'中文收發(fā)
Dim yTemp() As Byte
Dim stemp As String
Dim i As Integer
If mscTest.InBufferCount > 0 Then
i = mscTest.InBufferCount
yTemp = mscTest.Input
stemp = StrConv(yTemp, vbUnicode)
txtTest1.Text = stemp
End If
End Sub