Private Sub MSComm1_OnComm()
Static cnt As Integer
Dim receive_cnt As Integer
Dim i As Integer
Dim Pr As Byte
Dim Buffer As Variant
Dim Arr() As Byte
Dim s As String
Select Case MSComm1.CommEvent
Case comEvReceive
receive_cnt = MSComm1.InBufferCount '接收缓冲区的字节数
' 往暂存区存二进位资料
Buffer = MSComm1.Input
' 指定给位元组阵列以便处理
Arr = Buffer
s = ""
For i = 0 To receive_cnt - 1
If Arr(i) > 15 Then
s = s + Hex(Arr(i)) + " "
Else
s = s + "0" + Hex(Arr(i)) + " "
End If
cnt = cnt + 1
Next i
Text1.Text = Text1.Text & s
Erase Arr
If cnt >= 300 Then
Text1.Text = ""
cnt = 0
Exit Sub
End If
If Pr <> Arr(18) Then '校验正确
If Arr(17) = &H0 Then
Shape2.FillColor = RGB(0, 255, 0)
Shape3.FillColor = RGB(0, 255, 0)
Shape4.FillColor = RGB(0, 255, 0)
Shape5.FillColor = RGB(0, 255, 0)
Shape6.FillColor = RGB(0, 255, 0) '测试OK
Else
If Arr(17) And &H1 = &H1 Then '电压校准
Shape2.FillColor = RGB(0, 255, 0)
Else
Shape2.FillColor = RGB(255, 0, 0)
End If
If Arr(17) And &H2 = &H2 Then '电压测试
Shape3.FillColor = RGB(0, 255, 0)
Else
Shape3.FillColor = RGB(255, 0, 0)
End If
If Arr(17) And &H4 = &H4 Then '写内部EEPROM
Shape4.FillColor = RGB(0, 255, 0)
Else
Shape4.FillColor = RGB(255, 0, 0)
End If
If Arr(17) And &H8 = &H8 Then ' 脉冲检测
Shape5.FillColor = RGB(0, 255, 0)
Else
Shape5.FillColor = RGB(255, 0, 0)
End If
If Arr(17) And &H10 = &H10 Then ' 电机开关
Shape6.FillColor = RGB(0, 255, 0)
Else
Shape6.FillColor = RGB(255, 0, 0)
End If
End If
Else
MsgBox "校验失败,请重新测试"
End If
Case comEvSend
End Select
End Sub
你的问题是刚寄出通讯的时候经常犯的错。
你认为你的协议是每次传18个字节,因此通讯过来的数据肯定是18字节,这个是不对的。
通讯的过程很复杂,期间可能有位的缺失、甚至字节的缺失。因此一个通讯过来的数据未必如你所想是18个字节。
假设它小于18字节,那么你上面的代码肯定会出现下标越界。
解决方法两个:
第一种,如果过来的数据不是18字节,直接抛弃(或者记录日志后抛弃)
第二种,把每次接受到的数据凭借起来,每18个字节进行一次分析。
具体采取哪种方式,要看你的协议。建议对于能自己纠正错误的协议,使用第二种;固定长度的协议,采用第一种
Arr本来有10个元素,你非要访问第11个元素,所以越界,断点调试,看看当时Arr有多少元素,你访问的对不对
For i = 0 To receive_cnt - 1
If Arr(i) > 15 Then
改成
For i = 0 To UBOUND(Arr)
If Arr(i) > 15 Then
用Redim在重新定义一下数组,此时要给数组明确的大小。
Dim Arr() As Byte只是使用Redim之前的声明,表示该数组大小尚未定义,以后碰到Redim时,来确定数组的长度。
不过,以后可若干次使用Redim,每次的数组大小按个人意愿