时间:2022-10-14 02:29:17
摘 要: 介绍一种用于简易天线近场测量诊断系统的实时数据采集方法。首先论述串口通信的基本原理,随后结合VB语言介绍基于轮询和事件驱动的两种编程方法,并给出编程实例,最后讨论用于实时采集系统的最佳串口通信方式。
关键词: MSComm;串口通信;轮询;事件驱动
0 前言
串口编程有很多种方法,如MSComm控件、Windows API函数、直接端口读写和DOS下的访问。Visual Basic由于编程功能强大,提供了专为串口通信定制的MSComm控件,实现串口通信更加简单。本文主要针对一套简易天线近场测量诊断系统采用VB6.0编程时,分别使用两种串口通信的查询方式进行了比较。
1 串口通信
串口通信由于使用简便灵活,且大多数的PC都至少有一个RS-232端口,因此在计算机监控和数据传输等方面得到了广泛的应用。
目前,大多数的PC机串口使用一个9针插入式D-sub连接器,也称为DB-9,见图1所示。
图1 RS-232 DB-9连接器
表1 插针DTE使用的9个信号线
当采用两台PC机直接简单互联时,只需要TD、RD、GND 3个基本信号即可。但注意需要交换RD和TD,即连接电缆的DTE和DCE 2、3引脚要进行交换,否则无法进行发送/接收通信。引脚连接图见图2。
图2
2 Visual Basic中的轮询与事件驱动
在串行通信中,发送者或者驱动器依次每次只发送一位数据。串行传输中的数据位可以代表所有的信息,这些信息可以编码成文本数据、2进制、10进制和16进制ASCII码。在实际应用中,我们需要实时检测一个串行端口所引发的事件,从而判断这个事件所包含的信息。通常有两种方法可实现[1]:一是轮询端口,即周期性地读取特征和信号来发现是否有事件发生;二是使用事件驱动,即在事件发生时,让程序自动跳到另一段程序。其中,事件驱动对端口的行为反应很快,不需要浪费事件进行检测,在Visual Basic中,MSComm控件的OnComm事件执行这个功能。而轮询方式则需要确保程序足够频繁地轮询端口,以至于不会丢失信息。这种方式会额外占用CPU的资源,在系统需要同时进行其他工作时,会因此而丢失大量信息。
3 Visual Basic的MSComm控件编程
像VB的其他控件一样,MSComm也包括很多属性[2],简单介绍一下本文要用到的几个主要属性。
表2 MSComm控件属性
本文主要就测量诊断系统实时显示机械位置和采集仪表数据时,对采用事件驱动与轮询两种方式进行了编程[3][4] [5],并进行了二者的实际运行状态的对比。
图3 程序段流程图
3.1 轮询
采用轮询方式时,需要添加一个Timer控件。通过引发Timer事件,可以使Timer控件有规律地隔一段时间执行一次代码。时间间隔的长短由Timer控件的Interval属性来决定。
执行以下程序段表示当按下Command1按钮时,每隔1ms便执行Timer控件里的代码。即间隔1ms判断串口有无收到信息,进行判断确认后实时读取位置信息,对仪表采样并在界面上画图显示出来。
Private Sub Command1_Click()
If mPort 1Then _
MSComm1CommPort = 1
If MSComm1.PortOpen = False Then _
MSComm1.PortOpen = True
Timer1.Interval = 1
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
MSComm1.InputMode=comInputModeBinary
RxString_measurement = MSComm1.Input
If RxString_measurement(0) = &HEE Then
Current_Position=(RxString_measurement_(1)*10000+RxString_measurement(2)*100 _
+RxString_measurement(3)) / 1000
Label1.Caption = Current_Position & "m"
trig_count = trig_count + 1
measurement
display
MSComm1.InBufferCount = 0
If trig_count = Text4.Text Then _
Timer1.Enabled = False
End Sub
运行后,发现丢码情况较为严重,位置信息呈跳跃性显示。
3.2 事件驱动
针对轮询方式产生的丢码现象,将该段程序进行了改进,采用事件驱动的方式触发执行。以下程序段表示当串口接收到信息时,触发OnComm事件,执行该事件中的代码。代码在经过判断,确认所收信息为有用信息后,再进行数据的读取和图形显示。
Private Sub Form_Activate()
If mPort 1 Then _
MSComm1CommPort = 1
If MSComm1.PortOpen = False Then _
MSComm1.PortOpen = True
MSComm1. Rthreshold= 1
End Sub
Private Sub MSComm1_OnComm()
Select Case mEvent
Case comEvReceive
MSComm1.InputMode = comInputModeBinary
RxString_measurement = MSComm1.Input
If RxString_measurement(0) = &HEE Then
Current_Position= (RxString_measurement _ (1) *10000 + RxString_measurement(2) _
* 100 + RxString_measurement(3)) / 1000
Label1.Caption = Current_Position & "m"
trig_count = trig_count + 1
measurement
display
End Select
MSComm1.InBufferCount = 0
If trig_count = Text4.Text Then _
MSComm1.RThreshold = 0
End Sub
运行后,能够较好地完成数据采集和图形显示功能,位置显示也精确连贯。
4 结论
在VB6.0中,对于串口通信,实现同样的功能可以采用不同的方法。本文在程序设计时,考虑到应用的实际情况,对两种通信方式进行比较,最终选择了既能满足要求又可以提高速度的最佳方式。轮询方式适用于系统简单、数据传输量不大、通信频率固定且不高的情况下使用;对于通信频率高且不固定、实时性要求很强的系统来说,采用事件驱动的方式更加可靠。
参考文献:
[1]Jan Axelson,串行端口大全,北京:中国电力出版社,2001,5.
[2]王劲松,中文Visual Basic 5.0编程参考手册,北京:北京航空航天大学出版社,1998,11.
[3]Brian Siler、Jeff Spotts,Visual Basic 6开发使用手册,北京:机械工业出版社,1999,4.
[4]董红政等,基于MSComm控件实现串行通信的方法,微计算机信息,2007,27.
[5]杨朝辉等,基于MSComm控件实现双机的数据通讯,科技信息(科学教研),2007,11.