1.前言
实时数据采集系统过去在DOS操作系统下一般是采用汇编语言开发制作。随着Windows操作系统的普及应用,数据采集及工业控制等软件的开发也上升到 Windows环境下。可视化软件开发平台的出现,为软件开发提供了强大的图形界面功能,使得开发出来的各种应用软件具有良好的人机交互功能。汇编语言的特点是功能强、运行速度快,但编程复杂、调试难,而高级语言具有良好的可读性及方便的调试手段。
Visual Basic 是Windows环境下简单、易学、高效的可视化编程语言开发系统,以其所见即所得的可视化界面设计风格和32位面向对象的程序设计等特点,已广泛地应用于各个领域,是很多计算机软件开发人员采用的开发工具。VB不但提供了良好的界面设计能力,而且在微机串口通信方面也有很强的功能。采用 VB开发Winodws下的数据采集和工业控制应用软件十分方便,尤其软件界面设计非常便捷,编程工作量较小,开发周期短,特别适合非计算机专业的工程技术人员掌握和使用。
2.MSComm控件特点
MSComm控件是Microsoft提供的扩展控件,用于支持 VB程序对串口的访问,该控制“隐藏”了大部分串口通讯的底层运行过程和许多烦琐的处理过程,同时支持查询方法和事件驱动通讯的机制,事件驱动通讯是交互方式处理串口事务的一种非常有效的方法,特别适合 Windows程序的编写。在串口通讯过程中,当发送数据、收到数据或产生传输错误时,触发MSComm控件的OnComm事件,然后可以通过判断 CommEvent属性值获得事件类型,再根据事件类型进行相应数据处理。因此用其实现微机串口的数据通讯相当简单,以很少的程序代码就可以轻松实现串口的访问和数据通讯。
3.实时数据采集示例程序
下面给出的应用实例,通过对一台工业八通道实时检测仪表数据通讯协议进行分析,利用VB6.0开发微机通过串口对多通道工业仪表进行实时数据采集的编程技术。给出的程序代码具有通用性,并有详示,可以直接或稍加改动后用于其它数据采集或实时控制程序中。
3.1 仪表及其数据通讯协议
这台工业用八通道实时检测仪表,最多可同时接八路高精度位移传感器,用于测量多点微小形变或微量位移,仪表测量精度为0.01毫米,测量范围最大值为50毫米。该仪表带有一个9针的RS-232C串口,能与微机进行串口数据通讯,实时传送检测数据,通过微机软件处理可实现工业实时监控。
该仪表的串口数据通讯协议是:数据传输速率为9600bps,1位开始位,8位数据位,1位停止位,无奇偶校验位。仪表每秒通过串口发送200个字节数据,由于接入的位移传感器数量在 1-8路可调,所以发送的每帧数据长度不定长,随传感器数量多少而变化。仪表数据传输首先发送每帧数据的开始标志字节,该字节定义为二进制常数0FAH;然后发送1个字节的通道状态字节,该字节按位顺序每位代表相应的一路通道状态,某位是1则代表该通道接有位移传感器,某位是0则代表该通道未接位移传感器;从第三个字节开始按位移传感器接通的通道顺序发送采集数据字节,每道数据有三个字节,前2个数据字节采用压缩的BCD码编码方式,第1个数据字节是高位,第2个数据字节是低位,即一个字节表示两位十进制数,则两个字节表示四位十进制数,小数点采用固定形式,定义在两字节中间;第3个数据字节为符号字节,该字节第八位为1,即1xxxxxxx则为负数,第八位为0,即0xxxxxxx则为正数。
例如发送的字节数据为:0FAH 0B1H 26H 87H 8H 34H 62H 00H 37H 76H 0H 42H 53H 80H
0FAH为帧开始标志字节,第一道,第五道,第六道,第八道接有位移传感器,表示 -26.87 34.62 37.76 -42.53。
3.2 部分参数的技术分析
3.2.1 仪表通讯传输速率为9600bps,则最快速度为1.0417ms发送一个字节;仪表每秒发送200个字节,平均5.0ms发送一个字节,在查询方式或连续读取串口数据时要在程序中添加循环等待程序,等待接收缓冲区收到足够的字节才能进行数据处理。
3.2.2 仪表发送每帧数据长度不定长,为了实现实时监测功能,接收数据的读取要尽可能的快速,则在程序开始运行时设置MSComm1的属性
RThreshold = 26 接收缓冲区收到26个字节产生OnComm事件
InputLen = 1 Input每次读取一个字节
等到程序接收到一帧完整数据后,计算出当前帧数据长度,再将Rthreshold属性修改为帧长度,则接收缓冲区在收到一帧数据后,MSComm控件才会触发一个OnComm事件,这样就会有更多的时间进行数据的计算和处理。
3.2.3 仪表每秒发送200个字节数据,微机收到一完整帧数据至少需要t(ms)时间(只接一道传感器t=25ms;接八道传感器t=130ms),然后再进行数据处理。如果微机在下一帧数据接收前即t ms内能将数据计算处理完毕,则接收缓冲区内只会保存有一帧数据,不会存有两帧以上数据,接收缓冲区的大小不会影响实时监测效果(接收缓冲区>=一完整帧长度),这时完全可以实现实时监测或实时控制;如果微机在t ms内不能将数据计算处理完毕,接收缓冲区设置的又很大,在数据计算处理完毕前,接收缓冲区内就会保存有两帧以上数据,而且一次工作时间越长,缓冲区内滞留数据帧就越多,数据采集和数据处理之间产生逐渐增大的额外时间差,当接收缓冲区充满后,时间差不再增大,固定在某一值,部分数据因不能及时采集到接收缓冲区中,数据产生丢失现象,真实工作情况就会和微机处理结果产生较大的时间差,对实时监测和实时控制很不利,这种情况下接收缓冲区的大小就会影响实时监测效果,所以接收缓冲区设置不能过大,让部分数据丢失,以保证数据处理的实时性。
3.2.4 设置MSComm控件的接收数据模式采用二进制方式,即 InputMode=comInputModeBinary,但用Input属性读取数据时,不能直接赋值给 Byte 类型变量,只能通过先赋值给一个 Variant 类型变量,返回一个二进制数据的数组,再转换保存到Byte类型数变量中。
3.2.5 VB中有 Byte类型变量,但没有字节的位处理语句。通道状态字节的位处理要通过对该字节的值运算进行判断,符号字节的位处理则要判断符号字节的值是否大于127,大于127则为负数;压缩的BCD码存入Byte类型变量,VB系统只按十进制数处理,这要通过一个简单算法换算,解压BCD码才能还原成十进制表示数值。假如a是Byte类型变量,W是Single类型变量,将一个压缩的BCD码存入 a中,则算法是:
W=(a\16)*10 + a-(a\16)*16
则W=a-(a\16)*6
3.3 程序代码
在(通用)(声明)中定义程序所用变量:
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 TD(8) as Boolean ‘通道状态数组
Dim Wmax(8) As Single ‘最大值数组
Dim Wmin(8) 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 ‘清除发送缓冲区
For i=1 to 8
Wmax(i) = -99 ‘最大值赋初值
Wmin(i) = 99 ‘最小值赋初值
Next i
w = 0 ‘数据个数计数器清零
.RThreshold = 1 ‘设置接收一个字节产生OnComm事件
On Error Resume Next ‘改变错误处理的方式。
Err.Clear
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) = 170 Then ‘判断是否为数据开始标志,0FAH=170
.RThreshold = 0 ‘关闭OnComm事件接收
W=W+1 ‘计数器加1
av = .Input ‘读取通道状态字节
ab(0) = av(0) ‘转换保存到字节数据类型数
For i = 1 To 8 ‘通道状态数组复位
TD(i) = False
Next i
cn = 2 ‘帧长度赋初值,一个开始字,一个状态字
If ab(0) >= 128 Then ‘判断第八通状态
TD(8) = True ‘第八道是真
ab(0) = ab(0) - 128 ‘第7位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 64 Then ‘判断第七通状态
TD(7) = True ‘第七道是真
ab(0) = ab(0) - 64 ‘第6位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 32 Then ‘判断第六通状态
TD(6) = True ‘第六道是真
ab(0) = ab(0) - 32 ‘第5位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 16 Then ‘判断第五通状态
TD(5) = True ‘第五道是真
ab(0) = ab(0) - 16 ‘第4位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 8 Then ‘判断第四通状态
TD(4) = True ‘第四道是真
ab(0) = ab(0) - 8 ‘第3位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 4 Then ‘判断第三通状态
TD(3) = True ‘第三道是真
ab(0) = ab(0) - 4 ‘第2位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 2 Then ‘判断第二通状态
TD(2) = True ‘第二道是真
ab(0) = ab(0) - 2 ‘第0位置零
cn = cn + 3 ‘帧长度加3个字节
End If
If ab(0) >= 1 Then ‘判断第一通状态
TD(1) = True ‘第一道是真
cn = cn + 3 ‘帧长度加3个字节
End If
For i = 1 To 8 ‘
If TD(i) = True Then
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 = b2 + b1 / 100 ‘数值组合,标定小数点
If ab(4) > 127 Then WW = -WW ‘判断数据符号位
Label1(i-1) = Format(WW,"0.00") ‘显示毫米单位数值,2位小数
If WW>Wmax(i) And WW<51 Then ‘判断最大值,仪表在刚开始工作时有干扰,会传导一些乱码,位移传感器有参数偏差,最大值一般都略大于50毫米,所以取51为极限最大值,取-51为极限最小值。
Wmax(i) = WW
Label2(i-1)=Format(Wmax(i),"0.00") ‘显示最大值
End If
If WW -51 Then ‘判断最小值
Wmin(i) = WW
Label3(i-1)=Format(Wmin(i),"0.00") ‘显示最小值
End If
End If
Next i
.RThreshold = cn ‘打开MSComm1事件接收
Else
.RThreshold = 1
End If
Case Else
End Select
End With
End Sub |