近来写了个程序,通过modbus协议,读下位机的数据,
在读数据过程序,发现有时数据会跳到0的情况,不知这是不是读的过程序出现丢包?
如果是,怎么处理?

解决方案 »

  1.   

    modbus只是定义了数据格式,并没有定义出错处理,丢包是有可能的,在程序的OnComm代码中,至少应该监控"奇偶错",估计可以发现大部分传输错误。另外,数据会跳到0不一定是数据错,你的读出目标如果为0,则就会读到0!
      

  2.   

    Private Sub Timer1_Timer()              '读存储区数据
    Dim CRC() As Byte
    Dim FGetData As String
    Dim aa() As Byte
    Dim s As String
    Dim str As String
    Dim i As Integer
    Dim bb, cc As String
    ReDim aa(5) As Byte '定义动态数组
          aa(0) = add
          aa(1) = order
          aa(2) = h_add
          aa(3) = l_add
          aa(4) = h_num
          aa(5) = l_num
          CRC = CRC16(aa)
          str = CRC
          s = ""
        For i = 1 To LenB(str)
            s = s + Hex(AscB(MidB(str, i, 1)))
        Next i
        bb = Right(s, 2)
        cc = Mid(s, 1, 2)
        If Len(s) < 4 Then
            cc = Mid(s, 1, 1)
        End If
     ReDim Preserve aa(0 To 7) As Byte
          aa(6) = Val("&H" & bb)
          aa(7) = Val("&H" & cc)
     MSComm1.OutBufferCount = 0                           '清空输出寄存器
     MSComm1.Output = aa
      FGetData = ReceiveData
      Text5.Text = FGetData
                  p11 = Val("&H" & Mid(FGetData, 7, 4))
                  p12 = Val("&H" & Mid(FGetData, 11, 4))
                  p13 = Val("&H" & Mid(FGetData, 15, 4))
                  p14 = Val("&H" & Mid(FGetData, 19, 4))
    'For c_num = 0 To 10 Step 1
    'm_data(c_num) = p12
    'Next
    'p12 = sortdata(m_data())End SubFunction CRC16(Data() As Byte) As String
          Dim CRC16Lo As Byte, CRC16Hi As Byte      'CRC寄存器
          Dim CL As Byte, CH As Byte                '多项式码&HA001
          Dim SaveHi As Byte, SaveLo As Byte
          Dim i As Integer
          Dim Flag As Integer
          CRC16Lo = &HFF
          CRC16Hi = &HFF
          CL = &H1
          CH = &HA0
          For i = 0 To UBound(Data)
            CRC16Lo = CRC16Lo Xor Data(i) '每一个数据与CRC寄存器进行异或
            For Flag = 0 To 7
              SaveHi = CRC16Hi
              SaveLo = CRC16Lo
              CRC16Hi = CRC16Hi \ 2            '高位右移一位
              CRC16Lo = CRC16Lo \ 2            '低位右移一位
              If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1
                CRC16Lo = CRC16Lo Or &H80      '则低位字节右移后前面补1
              End If                           '否则自动补0
              If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或
                CRC16Hi = CRC16Hi Xor CH
                CRC16Lo = CRC16Lo Xor CL
              End If
            Next Flag
          Next i
          Dim ReturnData(1) As Byte
          ReturnData(0) = CRC16Hi              'CRC高位
          ReturnData(1) = CRC16Lo              'CRC低位
          CRC16 = ReturnData
        End Function
        Function ReceiveData() As String    '返回存储器区数据
        Dim FGetData As String
        Dim t1 As Long
        Dim av As Variant
        Dim i As Integer
        Dim ReDataLen As Integer
        
        FGetData = ""
        t1 = GetTickCount()                     '取时间,做延时用
        Do                                      '循环等待接收数据
            DoEvents
            If Form1.MSComm1.InBufferCount > 0 Then          '串口有数据了
                ReDataLen = Form1.MSComm1.InBufferCount      '取数据长度
                av = Form1.MSComm1.Input                     '将串口数据取出来
                    For i = 0 To ReDataLen - 1
                        FGetData = FGetData & Right("00" & Hex(av(i)), 2)
                    Next i
           End If
            If Len(FGetData) >= 6 Then
            
                If Len(FGetData) > Val("&H" & Mid(FGetData, 5, 2)) * 2 + 8 Then
                    ReceiveData = FGetData
                    Exit Function
                End If
            End If
            If GetTickCount - t1 > 300 And c_num <= 20 Then '2秒没收完就不收了
                c_num = c_num + 1
                ReceiveData = Form1.Text5.Text
                Else
                ReceiveData = "0"
                c_num = 0
                Exit Function
            End If
        Loop
    End Function
    这是我读取的数据的代码,大虾们帮我看看是什么问题啊?
      

  3.   

    Private Sub Timer1_Timer() '读存储区数据
    .........
     MSComm1.OutBufferCount = 0 '清空输出寄存器
     MSComm1.Output = aa
    '必须延迟一定时间再接受,当数据发到缓冲区后,发送是在后台的线程中进行,不会马上收到数据  FGetData = ReceiveData
    ........
    End Sub