我需要接收下位机上传过来的数据,每条数据最长不超过32个字节,但是每条数据每隔20ms上传一次,所以我接收到数据后再处理保存需要在20ms内完成。但是我现在使用下边的代码接收数据,发现一条数据没有接收完整就进行了保存(一条数据被分成2次保存起来),现在请论坛的朋友帮我看看我的代码在什么地方需要改进,能够等一条数据全部进来以后在进行保存啊?
Select Case MSComm1.CommEvent
        Case comEvReceive
            MSComm1.RThreshold = 0              '禁止在处理数据时再触发OnComm事件,而干扰了数据处理
            inByte = MSComm1.Input
        For i = 0 To UBound(inByte)
        If Len(Hex(inByte(i))) = 1 Then
            str1 = 0 & Hex(inByte(i))
        Else
            str1 = Hex(inByte(i))
        End If
            strData = strData & str1
        Next
            MSComm1.InBufferCount = 0       '清空缓冲区数据,避免下次通信出错。
            Text6 = strData
            MSComm1.RThreshold = 1          '恢复每次读一个触发一次OnComm事件
End Select
sqlinsert = "insert into [客车列尾运行数据] ([主机编号]) values ('" + Text6.Text + "')"
        Dim rs_suminsert As New ADODB.Recordset
        rs_suminsert.CursorLocation = adUseClient
        rs_suminsert.Open sqlinsert, conn, adOpenKeyset, adLockPessimisticMSComm1控件的属性设置如下:
 With MSComm1
        .CommPort = 1
        .Settings = "9600,n,8,1"
        .InBufferCount = 0
        .InputLen = 0
        .RThreshold = 1
        .InputMode = comInputModeBinary '以2进制接收
        .PortOpen = True

解决方案 »

  1.   

    .RThreshold = 1 说明一字节一触发事件。
    事件触发后用MSComm1.RThreshold = 0关闭事件触发似没有必要,你一次最多32字节,也是32个事件,要不了多长时间。
    用一个静态变量(static icount)或全局变量,来累计次数,icount为32时,保存并清0.你可以试一下,时间是否够用。如果不够用可设置.RThreshold = 32,也就是说32字节一触发事件,事件触发后读了数据就直接存盘。
      

  2.   

    猴哥,我接收的数据不是等长的,还有很多不到32个字节的,可能也就10多个字节。如果我改成RThreshold = 32以后,如果我接收的数据没有达到32个字节还会触发读取吗?
      

  3.   

    猴哥,我刚才将RThreshold = 32设置成这样,运行的时候发现还是将下位机发送的一条数据分成2次或3次记录了,但只有一条好像是完整记录的。
      

  4.   

    哦,你是不定长数据,这样不能用RThreshold = 32这样只能考虑延时,用延时解决问题,程序结构考虑做以下变动:
    Select Case MSComm1.CommEvent
        Case comEvReceive
            MSComm1.RThreshold = 0
            t = Timer
            While Timer - t < 0.01 '从0.01到0.02(20sm)做延时,自己调试
            Wend
            inByte = MSComm1.Input
            For i = 0 To UBound(inByte)
                strData = strData + Format(Hex(inByte(i)), "00")
            Next
            Text6 = strData
            MSComm1.RThreshold = 1          '恢复每次读一个触发一次OnComm事件
    End Select
      

  5.   

    修改一下猴哥的代码:
    Select Case MSComm1.CommEvent 
        Case comEvReceive 
            MSComm1.RThreshold = 0 
            Sleep 10
            inByte = MSComm1.Input 
            For i = 0 To UBound(inByte) 
                strData = strData + Format(Hex(inByte(i)), "00") 
            Next 
            Text6 = strData 
            MSComm1.RThreshold = 1          '恢复每次读一个触发一次OnComm事件 
    End Select
    把strData定义为全局的,此外你需要对你接收到的数据(strData的内容)进行分解,寻找起始,再寻找结束的,把这个字符串截取出来,存入数据库,余下的内容等待下一次触发了OnComm事件后,在处理
      

  6.   

    Private Sub MSComm1_OnComm()
        Select Case MSComm1.CommEvent
            Case comEvReceive
                MSComm1.RThreshold = 0
                Sleep 10        '延迟10ms,等待数据接收
                inByte = MSComm1.Input
                For i = 0 To UBound(inByte)
                    strData = strData + Format(Hex(inByte(i)), "00")
                Next
                Text6 = strData
                MSComm1.RThreshold = 1          '恢复每次读一个触发一次OnComm事件
        End Select
    End Sub
    '数据存储处理过程
    Sub subSaveString()
        Dim strP As String
        Dim intStart As String
        Dim intEnd As String
        intStart = InStr(1, strData, "1002")    '查找起始字符串的位置
        intEnd = InStr(1, strData, "1003")      '查找结束字符串的位置
        If intStart > 0 And intEnd > 0 And intEnd > intStart Then
            strP = Mid(strData, intStart, intEnd - intStart + 5)    'strP就是你要保存的一条数据,起始是1002 结束是 1003
            Replace strData, strP, "", intStart, 1, vbTextCompare   '将strdata中的strP去掉
        End If
    End Sub
      

  7.   


    为你做了一个模拟程序,程序结构大体如下,自己改改即可:Option Explicit
    Dim iStr As StringPrivate Sub Command1_Click()
         ss Val(Text1) '模拟mscomm一次传送一字节
    End SubSub ss(a As Byte) '模拟OnComm
       Static num As Integer
       Static start As String
       If num <= 1 Then
          start = start + Format(Hex(a), "00")
          Text2 = start '调试用,此句可删除
          num = num + 1
       ElseIf num = 2 And start = "1002" Then
          iStr = iStr + Format(Hex(a), "00")
          Text3 = iStr '调试用,此句可删除
          If InStr(iStr, "1003") Then
             iStr = Left(iStr, Len(iStr) - 4)
             Text2 = Text2 + "1003" '调试用,此句可删除
             Text3 = iStr '调试用,此句可删除
             num = 0
             start = ""
             MsgBox iStr '这里调用数据存盘程序。istr不包含字头(1002)与字尾(1003)
          End If
       Else
             num = 0
             start = ""
             Text1 = "" '调试用,此句可删除
             Text2 = "" '调试用,此句可删除
             
       End If
       
    End Sub
      

  8.   

    以上程序在用mscomm调试时要求MSComm1.RThreshold = 1,也就一字节一触发事件,不要用MSComm1.RThreshold = 0来关闭事件的触发。
      

  9.   

    我用这种处理方法,为什么有的时候我数据后边会多个1啊?比如正常接收到的数据是100255F90806272AA7DB1123452FFA1003
    但是有的时候就会在数据的后边多了一个1
    100255F90806272AA7DB1123452FFA10031'数据存储处理过程
    Sub subSaveString()
        Dim strP As String
        Dim intStart As String
        Dim intEnd As String
        intStart = InStr(1, strData, "1002")    '查找起始字符串的位置
        intEnd = InStr(1, strData, "1003")      '查找结束字符串的位置
        If intStart > 0 And intEnd > 0 And intEnd > intStart Then
            strP = Mid(strData, intStart, intEnd - intStart + 5)    'strP就是你要保存的一条数据,起始是1002 结束是 1003
            Replace strData, strP, "", intStart, 1, vbTextCompare   '将strdata中的strP去掉
        End If
    End Sub