在做一个报警盒测试软件中,遇到这样的问题:
报警盒采用被动方式与计算机沟通,计算机发送一次查询,报警盒返回当前状态.为了实现自动化,采用了Timer,但是在用到多个Timer时,出现了问题:进入某一Timer时,系统要处理此过程直到该Timer停止,即某一时间内只能运行一个Timer,因而使用Doevents来转移控制权,使得多个Timer能互不干扰.代码如下:Private Sub Timer1_timer()
函数A '报警状态查询并返回值
.... '根据返回值进行相应的处理并在程序界面给出显示 函数B '开关状态查询并返回值
.... '同上
End SubPrivate Sub Timer2_timer()
OverTime = true
End SubPrivate Sub Timer3_timer()
函数C '由一个按钮控制其Enable.需要在Timer1进行的同时进行此操作
End SubPrivate Function 函数A(ByRef 返回值)
发送报警查询命令
FlagIn = False
Timer2.Interval = 150 Do
If OverTime Then
Exit Do
End If
DoEvents
Loop Until FlagIn Timer2.Interval = 0 If FlagIn = True Then
'Oncomm事件被激活,对接受到的数据进行处理
End IfEnd FunctionPrivate Function 函数B(ByRef 返回值)
发送开关查询命令 FlagIn = False
Timer2.Interval = 150 Do
If OverTime Then
Exit Do
End If
DoEvents
Loop Until FlagIn Timer2.Interval = 0 If FlagIn = True Then
'Oncomm事件被激活,对接受到的数据进行处理
End If
End FunctionPrivate Sub MSComm1_OnComm()
'发生Oncomm事件
FlagIn = True
End Sub
现在这样写,程序能运行,并基本上满足需求,各个Timer互不干扰,并能对硬件状态做出同步反应,但是当硬件发生中断时,就出现了问题: 按设计思路,因Doevents的关系,硬件中断后,再次恢复与计算机通讯后,在Oncomm事件过程中,FlagIn状态被改写,为True,此时的True值应该传入函数A或B中,结束函数中的DO循环,并进行处理,但是并未按想法运行,而是进入函数A或B后,FlagIn又被改写成False.在循环一个不确定的时间后,才跳出DO循环.(因为要兼容多种设备,故有多种协议,在A协议中,中断再恢复,不会出现这个问题,但是在B协议中,中断再恢复就有问题,这也是奇怪的地方,如果是程序的问题,应该两者都出错,但是只一种协议有问题,两种协议的处理方式都是一样的) 我分析问题可能出现在Doevents上面,因为MSDN上面关于它的详细解释也是很模糊,很多不可预料的结果.但是要实现自动化,一般都是用Timer,或者创建多线程,多线程我没试过,不知道会不会也出现这种情况. 或者改进我现在处理方式,避免使用Doevents. 我表达的不是很清楚,因为这个问题实在很奇怪,我尽量把我的意思说明白,请大家伸出援助之手~~~
报警盒采用被动方式与计算机沟通,计算机发送一次查询,报警盒返回当前状态.为了实现自动化,采用了Timer,但是在用到多个Timer时,出现了问题:进入某一Timer时,系统要处理此过程直到该Timer停止,即某一时间内只能运行一个Timer,因而使用Doevents来转移控制权,使得多个Timer能互不干扰.代码如下:Private Sub Timer1_timer()
函数A '报警状态查询并返回值
.... '根据返回值进行相应的处理并在程序界面给出显示 函数B '开关状态查询并返回值
.... '同上
End SubPrivate Sub Timer2_timer()
OverTime = true
End SubPrivate Sub Timer3_timer()
函数C '由一个按钮控制其Enable.需要在Timer1进行的同时进行此操作
End SubPrivate Function 函数A(ByRef 返回值)
发送报警查询命令
FlagIn = False
Timer2.Interval = 150 Do
If OverTime Then
Exit Do
End If
DoEvents
Loop Until FlagIn Timer2.Interval = 0 If FlagIn = True Then
'Oncomm事件被激活,对接受到的数据进行处理
End IfEnd FunctionPrivate Function 函数B(ByRef 返回值)
发送开关查询命令 FlagIn = False
Timer2.Interval = 150 Do
If OverTime Then
Exit Do
End If
DoEvents
Loop Until FlagIn Timer2.Interval = 0 If FlagIn = True Then
'Oncomm事件被激活,对接受到的数据进行处理
End If
End FunctionPrivate Sub MSComm1_OnComm()
'发生Oncomm事件
FlagIn = True
End Sub
现在这样写,程序能运行,并基本上满足需求,各个Timer互不干扰,并能对硬件状态做出同步反应,但是当硬件发生中断时,就出现了问题: 按设计思路,因Doevents的关系,硬件中断后,再次恢复与计算机通讯后,在Oncomm事件过程中,FlagIn状态被改写,为True,此时的True值应该传入函数A或B中,结束函数中的DO循环,并进行处理,但是并未按想法运行,而是进入函数A或B后,FlagIn又被改写成False.在循环一个不确定的时间后,才跳出DO循环.(因为要兼容多种设备,故有多种协议,在A协议中,中断再恢复,不会出现这个问题,但是在B协议中,中断再恢复就有问题,这也是奇怪的地方,如果是程序的问题,应该两者都出错,但是只一种协议有问题,两种协议的处理方式都是一样的) 我分析问题可能出现在Doevents上面,因为MSDN上面关于它的详细解释也是很模糊,很多不可预料的结果.但是要实现自动化,一般都是用Timer,或者创建多线程,多线程我没试过,不知道会不会也出现这种情况. 或者改进我现在处理方式,避免使用Doevents. 我表达的不是很清楚,因为这个问题实在很奇怪,我尽量把我的意思说明白,请大家伸出援助之手~~~
声明在窗体顶部.
呵呵,cbm666,你好啊
处理过程是这样的: 发送查询码----报警盒回送识别码---接受并处理
报警盒的发码间隔需要在150ms以上,这样在处理时,为了实现实时报警,必须不间断发查询码(Timer1),但是如果不使用Doevents,则无法激活Oncomm事件(Timer1不能停止).
所以就加了Timer2,来处理Oncomm.cbm666说在一个函数里处理报警和开关两种情况,但是因为我现在要兼容多种设备,各个设备的通讯协议又各不相同(有的甚至同一协议里报警码,开关码,回送码的位数都不一样),写到一起程序可能太长,所以先分开写.老马说的MSCOMM控件内部有单独的线程来进行串口收发,并且已经在VB这边做成了事件驱动,这个事件驱动是什么?我现在是处理的CommEvent(comEvReceive).现在没有在Oncomm里处理数据,是将收到的数据传入函数A or B处理,因回送码一般为一个字节(8位),所以处理起来不会太久,可能问题就出在发码到串口,串口回码的通讯时间上面,因为这时间不能确定.