用VB进行串口实时数据采集.docx
《用VB进行串口实时数据采集.docx》由会员分享,可在线阅读,更多相关《用VB进行串口实时数据采集.docx(34页珍藏版)》请在冰豆网上搜索。
用VB进行串口实时数据采集
用VB进行串口实时数据采集
VB-界面速成通道/ChenLL 发表于2007-08-10,20:
28
用VB进行串口实时数据采集
本文介绍VB6.0利用MSComm通信控件,开发微机通过串口对工业仪表进行实时数据采集的编程技术。
给出的程序代码具有通用性,并有详细的注释,可以直接或稍加改动后用于其他数据采集或实时控制程序中。
----一台工业专用实时检测仪表,接高精度位移传感器,用于测量微小形变或微量位移,仪表测量精度为0.01毫米,测量范围最大值为50毫米。
该仪表带有一个9针的RS-232C串口,能与微机进行串口数据通信,实时传送检测数据,通过微机软件处理可实现工业实时监控。
----该仪表的串口数据通信协议是:
数据传输速率为9600bps,1位开始位,8位数据位,1位停止位,无奇偶校验位。
仪表每秒发送50帧检测数据,每帧数据由4个字节组成。
第一个字节定义为二进制常数0F0H,是每帧数据开始的标志字节;后面连续2个字节为数据字节,采用压缩的BCD码编码方式,高位在前,低位在后,即一个字节表示两位十进制数,则两个字节表示四位十进制数,小数点采用固定形式,定义在两字节中间;第四个字节为符号字节,该字节第八位为1,即:
1xxxxxxx 则为负数;第八位为0,即:
0xxxxxxx则为正数。
----例如:
0F0H26H87H80H0F0H34H62H00H表示-26.8734.62。
----通信传输速率为9600bps,则最快速度1.04ms发送一个字节,仪表每秒发送50帧数据,每帧数据有4个字节,即每秒发送200个字节,平均5.0ms发送一个字节,连续读取串口数据时要在程序中添加循环等待程序。
----为了实现实时监测功能,接收数据的读取要尽可能的快速,则设置MSComm1的属性如下:
RThreshold=1
接收缓冲区收到一个字节产生OnComm事件
InputLen=1 每次读取一个字节
----仪表每秒发送50帧数据,微机收到一帧完整数据至少需要20ms时间,然后再进行数据处理。
如果微机在下一帧数据接收前即20ms内能将数据计算处理完毕,则接收缓冲区内只会保存有一帧数据,不会存有两帧以上数据,接收缓冲区的大小不会影响实时监测效果(接收缓冲区>4字节),这时完全可以实现实时监测或实时控制;如果微机在20ms内不能将数据计算处理完毕,接收缓冲区设置得又很大,在数据计算处理完毕前,接收缓冲区内就会保存有两帧以上数据,而且一次工作时间越长,缓冲区内滞留数据帧就越多,数据采集和数据处理之间产生逐渐增大的额外时间差,当接收缓冲区充满后,时间差不再增大,固定在某一值,部分数据因不能及时采集到接收缓冲区中,数据产生丢失现象,真实工作情况就会和微机处理结果产生较大的时间差,对实时监测和实时控制很不利,这种情况下接收缓冲区的大小就会影响实时监测效果,所以接收缓冲区设置不能过大,以保证数据处理的实时性。
----设置接收数据模式采用二进制形式,即InputMode=comInputModeBinary,但用Input属性读取数据时,不能直接赋值给Byte类型变量,只能通过先赋值给一个Variant类型变量,返回一个二进制数据的数组,再转换保存到Byte类型数变量中。
----VB中有Byte类型变量,但没有字节的位处理语句,符号字节的位处理要判断符号字节的值是否大于127,大于127则为负数;压缩的BCD码存入Byte类型变量,VB系统只按十进制数处理,这要通过一个简单算法换算,解压BCD码才能还原成十进制表示数值。
假如a是Byte类型变量,D是Single类型变量,将一个压缩的BCD码存入a中,则算法是:
D=(a\16)*10+a-(a\16)*16
则D=a-(a\16)*6
----程序清单:
----在通用声明中定义程序所用变量:
Dimab(4)AsByte
‘字节数据类型数组,用来存储接收到的一组字节数据
DimavAsVariant‘用来从接收缓冲区读取数据
DimiAsInteger
DimjAsInteger
DimwAsInteger ‘接收数据个数计数器
Dimb1AsSingle
Dimb2AsSingle
DimWWAsSingle ‘十进制检测值
DimMaxWAsSingle ‘最大值
DimMinWAsSingle ‘最小值
----在窗体中添加名为Command1的[开始]按钮和名为MSComm1的MSComm控件。
----[开始]按钮的Click事件处理程序主要是对MSComm1控制的参数初始化设置,程序中大部分参数在设计时可在MSComm1控制的属性窗口中设置:
PrivateSubCommand1_Click()
‘开始按钮
WithMSComm1
.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=FalseThen
‘判断通信口是否打开
.PortOpen=True ‘打开通信口
IfErrThen ‘错误处理
MsgBox“串口通信无效"
ExitSub
EndIf
EndIf
EndWith
EndSub
----为了达到实时数据采集目的,实时数据采集处理程序采用MSComm事件驱动方式。
----MSComm1_OnComm的事件处理程序只处理comEvReceive事件,首先判断帧数据的开始字节,关闭OnComm接收事件,然后接收数据字节,将压缩BCD进行还原转换,再接收符号字节,判断数据符号,判断数据最大最小值,最后打开OnComm接收事件,等待下一次OnComm事件产生:
PrivateSubMSComm1_OnComm()
WithMSComm1
SelectCase.CommEvent
‘判断MSComm1通信事件
CasecomEvReceive
‘收到Rthreshold个字节产生的接收事件
av=.Input
‘读取一个接收字节
ab
(1)=av(0)
‘转换保存到字节数据类型数组
Ifab
(1)=&HF0Then
‘判断是否为数据开始标志
RThreshold=0
‘关闭OnComm事件接收
Do
DoEvents
LoopUntil.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
‘数值组合,标定小数点
Ifab(4)>127ThenWW=WW
‘判断数据符号位
Label1(0)=Format(WW,“0.00")
‘显示毫米单位数值,2位小数
Label1
(1)=Format(WW/25.4,“0.000")
‘显示英寸单位数值,3位小数
IfWW>MaxWAndWW<51Then
----‘判断最大值,仪表在刚开始工作时有干扰,会传导一些乱码,位移传感器有参数偏差,最大值一般都略大于50毫米,所以取51为极限最大值,取-51为极限最小值。
MaxW=WW
Label1
(2)=Format(MaxW,“0.00")
‘显示毫米单位最大值,2位小数
Label1(3)=Format(MaxW/25.4,“0.000")
‘显示英寸单位最大值,3位小数
EndIf
IfWW-51Then
‘判断最小值
MinW=WW
Label1(4)=Format(MinW,“0.00")
‘显示毫米单位最小值,2位小数
Label1(5)=Format(MinW/25.4,“0.000")
‘显示英寸单位最小值,3位小数
EndIf
.RThreshold=1
‘打开MSComm1事件接收
EndIf
CaseElse
EndSelect
EndWith
EndSub
基于VB的串口数据采集
[来源:
机电论文|类别:
技术|时间:
2008-6-2114:
44:
00]
[字体:
大中小]
要求:
用VB编写一个小软件,采集电子数显千分表的数据
数显表接口参数:
数显表的专用接口可与PC机的RS232(9针)相接,其波特率4800,无奇偶校检,8位数据位,1位停止位,以AcsII码发送数据
窗体设计:
1个listbox,1个textbox,1个MSComm控件,2个CommandButton
程序设计:
DimindataAsVariant
Dimdata(100)AsSingle
PrivateSubCommand1_Click()
Statici
i=i+1
data(i)=Text1.Text
List1.AddItemdata(i)
EndSub ‘...按键一次,采集一个数据,并存入List1中
PrivateSubCommand2_Click()
MSComm1.PortOpen=False '….关端口
UnloadMe
EndSub '...退出
PrivateSubForm_Load()
MSComm1.CommPort=1'...使用Com1口
MSComm1.Settings="4800,n,8,1" '...设置通讯参数
MSComm1.RThreshold=10
MSComm1.streshold=10
MSComm1.PortOpen=True'...打开串口
Text1.Text=""
EndSub
PrivateSubMSComm1_OnComm()
SelectCaseMSComm1.CommEvent
CasecomEvReceive'...有接收事件发生
indata=MSComm1.Input
Text2.Text=(indata/10)‘…text1实时显示数显表的数据
MSComm1.InBufferCount=0'...清空输入寄存器
EndSelect
EndSub
我这有一段VB程序是为了画实时采集曲线的。
软件编程我不行,如果大家有看得懂得,请帮我看看。
程序不多
Private Sub MSComm1_OnComm()
Dim Inbyte() As Byte
Dim buffer As String
Dim datatemp(1000) As Single
If num > 199 Then Call renew '刷新绘图区
'读取仪表返回数据串
Select Case MSComm1.CommEvent
Case comEvReceive
Inbyte = MSComm1.Input'这地方看不懂,数组可以这样赋值吗?
For i = LBound(Inbyte) To UBound(Inbyte)
buffer = buffer + Hex(Inbyte(i)) + Chr(32) 'for语句也没看懂,尤其是buffer这赋的是什么值?
Next i
Case comEvSend
End Select
'获取十进制测量数据
’这下面的又是没看懂,应该是将十六进制转换为十进制,怎么转换的呢?
If Len(Trim(Mid(buffer, 1, 2))) = 1 Then
datatemp(num) = Val("&H" & Mid(buffer, 3, 2) & Str("0") & Mid(buffer, 1, 2)) * 0.01
Else
datatemp(num) = Val("&H" & Mid(buffer, 3, 2) & Mid(buffer, 1, 2)) * 0.01
End If
‘绘制曲线
Private Sub draw()
Picture1.Cls
Picture1.DrawWidth = 2
Picture1.BackColor = QBColor(7)
’下面的程序我看不懂,用的是什么原理画的曲线呢?
Picture1.Scale (0, 50)-(200, 0)
For i = 1 To num - 1
X1 = (i - 1):
Y1 = datatemp(i - 1)
X2 = i:
Y2 = datatemp(i)
Picture1.Line (X1, Y1)-(X2, Y2), QBColor
(1)
Next i
End Sub
问题点数:
100 回复次数:
10
修改删除举报引用回复
加为好友
发送私信
在线聊天
∙
CathySun118
∙
∙等级:
∙可用分等级:
富农
∙总技术分:
88266
∙总技术分排名:
66
∙2
发表于:
2007-06-2514:
44:
411楼 得分:
0
连点法阿
修改删除举报引用回复
加为好友
发送私信
在线聊天
∙
Winters_lee
∙
∙等级:
∙可用分等级:
中农
∙总技术分:
1658
∙总技术分排名:
12870
∙
发表于:
2007-06-2609:
41:
372楼 得分:
0
画曲线啊,用这个吧:
'实时曲线左移函数,定义在模块中
Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
'建立一个类,作为画实时曲线
Option Explicit
Public pCurveNUM As Integer
Public pCurveName As String
Public pCurveMax As Double
Public pCurvemin As Double
Private pricCurve As PictureBox
Private priCurvePoint(6) As Integer
Private priCurveData(6) As Double
Private priDrawY0(6) As Double
Private priDrawY1(6) As Double
Private priDrawNMinute As Integer
Private priDrawTMinute As Integer
Private WithEvents priTimerDraw As Timer
Public Property Let ltDrawTimer(ByRef lTimer As Timer)
Set priTimerDraw = lTimer
End Property
Public Property Let ltGiveCurveData(ByVal lDataPoint As Variant)
Dim i%
For i = 1 To pCurveNUM
priCurvePoint(i) = CInt(lDataPoint(i))
Next
End Property