----在通用声明中定义程序所用变量:
Dim ab(4) As Byte
‘字节数据类型数组,用来存储接收到的一组字节数据
Dim av As Variant ‘用来从接收缓冲区读取数据
Dim i As Integer
Dim j As Integer
Dim w As Integer ‘接收数据个数计数器
Dim b1 As Single
Dim b2 As Single
Dim WW As Single ‘十进制检测值
Dim MaxW As Single ‘最大值
Dim MinW As Single ‘最小值
----在窗体中添加名为Command1的[开始]按钮和名为 MSComm1的MSComm控件。
---- [开始]按钮的Click事件处理程序主要是对MSComm1控制的参数初始化设置,程序中大部分参数在设计时可在MSComm1控制的属性窗口中设置:
Private Sub Command1_Click()
‘开始按钮
With MSComm1
.CommPort=2 ‘使用COM2
.Setting=“9600,N,8,1" ‘设置通信口参数
.InBufferSize=40
‘设置MSComm1接收缓冲区为40字节
.OutBufferSize=2
‘设置MSComm1发送缓冲区为2字节
.InputMode = comInputModeBinary
‘设置接收数据模式为二进制形式
.InputLen = 1
‘设置Input 一次从接收缓冲读取字节数为1
.SThreshold = 1
‘设置Output 一次从发送缓冲读取字节数为1
.InBufferCount = 0 ‘清除接收缓冲区
.OutBufferCount = 0 ‘清除发送缓冲区
MaxW = -99
‘最大值赋初值
MinW = 99 ‘最小值赋初值
w = 0
‘数据个数计数器清零
.RThreshold = 1
‘设置接收一个字节产生OnComm事件
If .PortOpen = False Then
‘判断通信口是否打开
.PortOpen = True ‘打开通信口
If Err Then ‘错误处理
MsgBox “串口通信无效"
Exit Sub
End If
End If
End With
End Sub
----为了达到实时数据采集目的,实时数据采集处理程序采用MSComm事件驱动方式。
----MSComm1_OnComm的事件处理程序只处理 comEvReceive事件,首先判断帧数据的开始字节,关闭OnComm接收事件,然后接收数据字节,将压缩BCD进行还原转换,再接收符号字节,判断数据符号,判断数据最大最小值,最后打开OnComm接收事件,等待下一次OnComm事件产生:
Private Sub MSComm1_OnComm()
With MSComm1
Select Case .CommEvent
‘判断MSComm1通信事件
Case comEvReceive
‘收到Rthreshold个字节产生的接收事件
av = .Input
‘读取一个接收字节
ab(1) = av(0)
‘转换保存到字节数据类型数组
If ab(1) = &HF0 Then
‘判断是否为数据开始标志
RThreshold = 0
‘关闭OnComm事件接收
Do
DoEvents
Loop Until .InBufferCount >= 3
‘循环等待MSComm1接收缓冲区>=3个字节
w = w + 1 ‘计数器累加计数
av = .Input
‘读取第二个数据字节(BCD码高位字节)
ab(2) = av(0)
‘转换保存到字节数据类型数组
av = .Input
‘读取第三个数据字节(BCD码低位字节)
ab(3) = av(0)
‘转换保存到字节数据类型数组
av = .Input
‘读取第四个数据字节(符号位字节)
ab(4) = av(0)
‘转换保存到字节数据类型数组
b1 = ab(2) - 6 * (ab(2)\16)
‘高位字节压缩BCD码转换为实数
b2 = ab(3) - 6 * (ab(3)\16)
‘低位字节压缩BCD码转换为实数
WW = b1 + b2 / 100
‘数值组合,标定小数点
If ab(4) > 127 Then WW=?WW
‘判断数据符号位
Label1(0) = Format(WW, “0.00")
‘显示毫米单位数值,2位小数
Label1(1) =Format(WW /25.4, “0.000")
‘显示英寸单位数值,3位小数
If WW > MaxW And WW < 51 Then
----‘判断最大值,仪表在刚开始工作时有干扰,会传导一些乱码,位移传感器有参数偏差,最大值一般都略大于50毫米,所以取51为极限最大值,取-51为极限最小值。
MaxW = WW
Label1(2) = Format(MaxW, “0.00")
‘显示毫米单位最大值,2位小数
Label1(3) = Format(MaxW/25.4,“0.000")
‘显示英寸单位最大值,3位小数
End If
If WW < MinW And WW > -51 Then
‘判断最小值
MinW = WW
Label1(4) = Format(MinW, “0.00")
‘显示毫米单位最小值,2位小数
Label1(5) = Format(MinW/25.4,“0.000")
‘显示英寸单位最小值,3位小数
End If
.RThreshold = 1
‘打开MSComm1事件接收
End If
Case Else
End Select
End With
End Sub
VB有一个例子在Samples\CompTool\Mscomm中。你可以利用这个例子来学习串口编程。
打开串口先设置CommPort属性(端口号),使用PortOpen=True就可以了。
串口数据保存在MSComm的Input属性中。你可以使用下面的代码:
Dim v As Variant
v = MSComm1.Input
For i = 0 To MSComm1.InBufferCount - 1
Debug.Print v(i)
Next
现有电子秤一台,使用串口与计算机进行通讯。编写VB程序来访问串口,达到读取电子秤上显示的数据。该电子秤为BE01型仪表,输出为RS-232C标准接口,波特率为300-9600、偶校验、7个数据位、2个停止位。所有字符均发送11位ASCII码,一个起始位。在VB中与串口通讯需要引入控件MSComm串口通讯控件(在Microsoft Comm Control 6.0中)。具体程序如下:控件简称:MSC
Dim Out(12) As Byte '接收var中的值
Dim var As Variant '接收MSC.input中的数值
Dim nRece As Integer '计算MSC.inputbuffer的个数
Dim i As Integer, j As Integer '随即变量,计算循环
Private Sub ClearText()
Text3.Text = ""
Text2.Text = "5"
Text1.Text = ""
End Sub
Private Sub Command1_Click()
ClearText
' nRece = 0 '计数器清零
With MSC
.InputMode = comInputModeBinary '设置数据接收模式为二进制形式
.InBufferCount = 0 '清除接收缓冲区
If Not .PortOpen Then
.PortOpen = True '打开通信端口
End If
End With
End Sub
Private Sub MSC_OnComm()
DelayTime ‘用来延续时间
ClearText
With MSC
Select Case .CommEvent '判断通信事件
Case comEvReceive: '收到Rthreshold个字节产生的接收事件
SwichVar 1
If Out(1) = 2 Then '判断是否为数据的开始标志
.RThreshold = 0 '关闭OnComm事件接收
End If
Do
DoEvents
Loop Until .InBufferCount >= 3 '循环等待接收缓冲区>=3个字节
' 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
' 错误
Case comEventBreak ' 收到 Break。
Case comEventCDTO ' CD (RLSD) 超时。
Case comEventCTSTO ' CTS Timeout。
Case comEventDSRTO ' DSR Timeout。
Case comEventFrame ' Framing Error
Case comEventOverrun '数据丢失。
Case comEventRxOver'接收缓冲区溢出。
Case comEventRxParity' Parity 错误。
Case comEventTxFull '传输缓冲区已满。
Case comEventDCB '获取 DCB] 时意外错误
' 事件
Case comEvCD ' CD 线状态变化。
Case comEvCTS ' CTS 线状态变化。
Case comEvDSR ' DSR 线状态变化。
Case comEvRing ' Ring Indicator 变化。
Case comEvReceive ' 收到 RThreshold # of chars.
Case comEvSend ' 传输缓冲区有 Sthreshold 个字符 '
Case comEvEof ' 输入数据流中发现 EOF 字符
Private Sub TmrComm_Timer()
'采用轮循法采集数据
Dim Rx_buff() As Byte
Dim okstring As String
Dim ReceivedLen As Integer
On Error GoTo ErrorHandler
TmrComm.Enabled = False '关闭定时器
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 '打开定时器
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 函数,挂起当前进程一段时间
Loop Until comReceive.InBufferCount = nReceiveCount
If comReceive.PortOpen = True Then
sComm = comReceive.Input
End If
End Function
注:此函数参照了xth一文。
此法一般是能确保数据接收的正确,但由于WINDOWS是多任务操作系统,当有耗时的进程运行时会丢失数据。如果系统会出现这种情况,可增大函数sleep()的参数值。
JY
1999.10
A:经CHR(206)+CHR(210)转换后实际上变成了两个UNICODE字符,四个字节了。汉字的收发必须用BINARY方式。下面的程序能实现汉字收发。
发:
Dim ytemp() As Byte
Dim stemp As String
stemp = "你好!"
ytemp = StrConv(stemp, vbFromUnicode)
Debug.Print UBound(ytemp)
MSComm1.Output = ytemp
收:
Private Sub mscTest_OnComm()
'中文收发
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