为什么我获取串口数据时有时会乱了呢?

sosoben 2012-09-04 11:01:20
代码如下。我用timer 每1秒分别向下位机获取X Y坐标,但有时数据会少一个位,有时X,Y值会掉转
另:为什么我不用事件触发呢?主要是除了这个命令 我对下位机还有其他命令,我想发一条命令就准确收到其值
我已经不用DOevents了,还会这样
下位机反映速度不用怀疑,都是毫秒级的


MSComm1.Output = "AXI1:POS?" & Chr(13) '对下位机发送位置请求
Dim t As Single
t = Timer
Do
'DoEvents
GetInput = MSComm1.Input
Loop Until GetInput <> "" Or Timer - t > 1 '主要是防止超时导致的死循环
Labelpos.Caption = GetInput '把位置显示出来

MSComm1.Output = "AXI2:POS?" & Chr(13)
t = Timer
Do
'DoEvents
GetInput = MSComm1.Input
Loop Until GetInput <> "" Or Timer - t > 1
Labelposy.Caption = GetInput
...全文
487 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
sosoben 2012-09-05
  • 打赏
  • 举报
回复
用of123的方法可以不怎么修改当前程序的前提下解决我的问题 。但有个问题是我的数据是6位,当是负数的时候是7位,我用 MSComm1.InBufferCount >= 6 的条件竟然也没有错,这是为什么呢?


SupermanKing 的方法较为严谨与详细,我再下次编程时会优先考虑这样的编法 ,谢谢指教!!
现在还是人类 2012-09-04
  • 打赏
  • 举报
回复

Private Sub Timer1_Timer()
Call YourFun(True)
End Sub
现在还是人类 2012-09-04
  • 打赏
  • 举报
回复
你可以用Timer触发输出过程,但不要在Timer里处理接收过程,接收过程需要在串口事件里处理,如果你想做函数等待结果返回,可以设置一个公共变量作为返回状态判断值,在串口事件里完成接收判断过程后设置这个值你的那个过程就可以返回了,如:

Dim cmd_retValue As Long
Dim cmd_IsReturn As Boolean
Dim cmd_Index As Long

Function YourFun(ByVal State As Boolean) As Long
cmd_IsReturn = False
cmd_retValue = 0
cmd_Index = 1
MSComm1.Output = "AXI1:POS?" & vbCr
'......
Do
Doevents
Loop while cmd_IsReturn = False
cmd_Index = 0
YourFun = cmd_retValue
End Function

Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
ReadStr = MSComm1.Input
Select Case cmd_Index
Case 1:
If UCase(ReadStr) = "+OK" & vbCr Then
cmd_retValue = 1
cmd_IsReturn = True
End If
'......
End Select
End If
End Sub

of123 2012-09-04
  • 打赏
  • 举报
回复
可以用查询方式,但你的查询有问题。假定这个命令的返回是 4 字节:

MSComm1.Output = "AXI1:POS?" & Chr(13) '对下位机发送位置请求
Dim t As Single
t = Timer
Do
DoEvents
Loop Until MSComm1.InBufferCount >= 4 Or Timer - t > 1 '主要是防止超时导致的死循环
GetInput = MSComm1.Input
Labelpos.Caption = GetInput '把位置显示出来
现在还是人类 2012-09-04
  • 打赏
  • 举报
回复
笔误

'以下是等待执行
Do
Doevent
Loop While cmd_IsReturn = True
' 也可以换成会略执行
' If cmd_IsReturn = True Then Exit Function
现在还是人类 2012-09-04
  • 打赏
  • 举报
回复
时序的重要性是通讯程序的关键,这个你都没意识到怎么写通讯程序?
你说的“乱”就是没有这种时序理念做出来的东西,怎么会不出“乱”?
你担心的过程冲突问题不就是多几个全局变量识别问题而已吗?
那你看看这样做会有什么问题?

Dim cmd_retValue As Long
Dim cmd_IsReturn As Boolean
Dim cmd_Init As Boolean
Dim cmd_Index As Long
Sub Form1_Load()
cmd_IsReturn = False
cmd_Init = False
On Error Resume Next
' 初始化串口过程,如果失败 直接退出该过程
'.......
cmd_Init = True
End Sub
Function YourFun1(ByVal State As Boolean) As Long
If cmd_Init = False Exit Function
'以下是等待执行
Do
Doevent
Loop While YourFun1=True
' 也可以换成会略执行
' If YourFun1=True Then Exit Function

cmd_IsReturn = False
cmd_retValue = 0
cmd_Index = 1
MSComm1.Output = "CMD1+" & State & vbCr
Do
Doevents
Loop while cmd_IsReturn = False
cmd_Index = 0
YourFun1 = cmd_retValue
End Function
Function YourFun2(ByVal State As Boolean) As Long
If cmd_Init = False Exit Function
'以下是等待执行
Do
Doevent
Loop While YourFun1=True
' 也可以换成会略执行
' If YourFun1=True Then Exit Function
cmd_IsReturn = False
cmd_retValue = 0
cmd_Index = 2
MSComm1.Output = "CMD2+" & State & vbCr
Do
Doevents
Loop while cmd_IsReturn = False
cmd_Index = 0
YourFun2 = cmd_retValue
End Function
Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = comEvReceive Then
ReadStr = MSComm1.Input
Select Case cmd_Index
Case 1:
If ReadStr = "CMD1 OK" Then
cmd_retValue = 1
Else
cmd_retValue = 0
End If
cmd_IsReturn = True
Exit Sub
Case 2:
If ReadStr = "CMD2 OK" & vbCr Then
cmd_retValue = 1
Else
cmd_retValue = 0
End If
cmd_IsReturn = True
Exit Sub
End Select
End If
End Sub
Private Sub Timer1_Timer()
Timer1.Enabled = False
Call YourFun1(True)
Timer1.Enabled = True
End Sub
Private Sub Command1_Click()
Call YourFun2(True)
End Sub
sosoben 2012-09-04
  • 打赏
  • 举报
回复
除了这些问位置的,我可能还会问是否动作啊等等

而且是用timer或用按钮触发的,有没有可能是timer到达doevents的时候我刚好按了按钮 触发了其他发送命令(其他命令可能更改那个 cmd_Index的值啊),然后返回了错误的值呢?

我还没时间调试,但想象的话可能会发生上述情况 请指教

7,765

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧