本人对CRC校验不是很了解!下面我把我的通讯协议发下,大家帮看看!我的这个程序怎么改!读仪表当前累计  STX 地  址 D T M CRC CR LF
   02    30 31    44       54       4d       32 38     0D       0A
其中:
STX  — — 起始符, 02H
秤号  — — 地址2 位。如秤号为01 时, 即: 30H 31H
D    — — 44H
T    — — 54H
M    — — 4DH
CRC — — 校验和,即其前面所有数值相加并转换为十进制, 然后取后两位并转为ASCII 码。( 其中十位在前、个位在后;其他传输数据都是高位在前)
CR — — 回车 0DH
LF — — 换行 0AH
程序里这样用的: Call Lrc_Fun(SendStr, LRC_TMP, 5)  
  SendStr(6) = LRC_TMP(0)
  SendStr(7) = LRC_TMP(1)定义的FUN:Public Function Lrc_Fun(SendStr() As Byte, Lrc_data() As Byte, data_long As Byte)
    Dim Lrc_DD As Long
    Dim Lrc_byte As Byte
    Dim lRC_ll As Byte
    Dim Lrc_hl As Byte
    Lrc_DD = 0
    For i = 0 To data_long Step 2
        Lrc_DD = Lrc_DD + AsciiToDec(SendStr(i)) * 16 + AsciiToDec(SendStr(i + 1))
    Next i
    Lrc_byte = Lrc_DD Mod &H100
    Lrc_byte = Not Lrc_byte
    Lrc_byte = (Lrc_byte + 1) Mod &H100
    lRC_ll = Lrc_byte \ 16
    Lrc_hl = Lrc_byte Mod 16
    Lrc_data(0) = DecToAscii(lRC_ll)
    Lrc_data(1) = DecToAscii(Lrc_hl)
End Function
哪位帮我看看,问题出在哪里!!我试了!校验一直不对!!帮改改!非常感谢!

解决方案 »

  1.   

    CRC分CRC32 CRC16 CRC8,而且Google一下代码很多。
      

  2.   

    你搞得太复杂了,给你一段我给你修改的代码看看:Private Sub Command1_Click()
        Dim sendStr() As Byte
        Dim L As Integer, i As Integer
        Dim S As String
        S = "02303144544d32380D0A"
        L = Len(S) / 2 - 1
        ReDim sendStr(L)
        For i = 0 To L
            sendStr(i) = "&H" & Mid(S, i * 2 + 1, 2)
        Next
        Dim LRC_TMP(1) As Byte
        Lrc_Fun sendStr, LRC_TMP
        sendStr(6) = LRC_TMP(0)
        sendStr(7) = LRC_TMP(1)End SubPublic Function Lrc_Fun(sendStr() As Byte, Lrc_data() As Byte)
    'CRC — — 校验和,即其前面所有数值相加并转换为十进制, 然后取后两位并转为ASCII 码。
    '( 其中十位在前、个位在后;其他传输数据都是高位在前)
        Dim Lrc_DD As Long
        Dim iNum As String
        For i = 0 To UBound(sendStr) - 4
            Lrc_DD = Lrc_DD + sendStr(i)
        Next i
        iNum = IIf(Lrc_DD < 10, Format(Lrc_DD, "00"), Right(Format(Lrc_DD), 2))
        Lrc_data(0) = Asc(Left(iNum, 1))
        Lrc_data(1) = Asc(Right(iNum, 1))
    End Function
      

  3.   

    Public Function Lrc_Fun(SendStr() As Byte, Lrc_data() As Byte, data_long As Byte)
        Dim Lrc_DD As Long
        Dim Lrc_byte As Byte
        Dim lRC_ll As Byte
        Dim Lrc_hl As Byte
        Dim i As Long
        Lrc_DD = 0
        For i = 0 To data_long - 1 Step 2 '多算了一次'
            Lrc_DD = Lrc_DD + AsciiToDec(SendStr(i)) * 16 + AsciiToDec(SendStr(i + 1))
        Next i
        '既然是按照十进制计算的……'
        Lrc_byte = Lrc_DD Mod 100
        lRC_ll = Lrc_byte \ 10
        Lrc_hl = Lrc_byte Mod 10    Lrc_data(0) = DecToAscii(lRC_ll)
        Lrc_data(1) = DecToAscii(Lrc_hl)
    End Function
      

  4.   

    Tiger_zhao 你好!
    你发的那个我用不了!这个是我发帖的那天晚上弄出来的!只要是因为那个仪表给出的是ASCII码,但是发送的是16进制捣鼓的我有点晕!我是用了一个土的办法自己捣鼓出来的!另那个数据To data_long - 1 Step 2 '多算了一次' 此处不能用step2 因为校验前的数据长度是不等的!分别对输入输出校验! 其实我知道一个更简单的方法!发送的时候MSCOMM设置为2进制,接收时为文本!那收到的就是ASCII的字符串了!我还发现这个一般的返回很不稳定是不是就多出一个数据位!一般都是第一位多了一个非可见字符,如果这样校验就失败了!我看看吧!是在不行就改成文本接收!否则通讯质量太低,如果文本可以直接查找命令字符和回车,只要中间数据符合了就没有问题!!尽管如此!还是希望这种方式能捣鼓好!下面发下我自己做的! 看看怎么优化下! Public Function Lrc_Fun_GM(SendStr() As Byte, Lrc_data() As Byte, data_long As Byte)
        Dim Lrc_DD As Long
        Dim lRC_ll As Byte
        Dim Lrc_hl As Byte
        Dim i As Long
        Lrc_DD = 0
        For i = 0 To data_long Step 1
            Lrc_DD = Lrc_DD + SendStr(i)
        Next i
         Lrc_byteDD = Right(Lrc_DD, 2)
        lRC_ll = Lrc_byteDD \ 10
        Lrc_hl = Lrc_byteDD Mod 10
        Lrc_data(0) = DecToAscii(lRC_ll)
        Lrc_data(1) = DecToAscii(Lrc_hl)
    End Function
      

  5.   

    我发的那个命令是偶数字节的!但是好多命令是奇数字节的!所以STEP 2不可行!只能STEP1来累加
      

  6.   


    他这里不是真正的 CRC 算法,仅仅是一个自定义的校验和算法。2 + &H30 + &H31 + &H44 + &H54 + &H4d = &H148 = 328    Lrc_DD = 0 
        For i = 0 To data_long Step 2 
            Lrc_DD = Lrc_DD + Val("&H" & SendStr(i)) 
        Next i     strTmp = Right(CString(Lrc_DD), 2)
        Lrc_data(0) = Asc(Left(strTmp, 1))
        Lrc_data(0) = Asc(Right(strTmp, 1))
     
      

  7.   

    7楼说的没错,只是个简单的校验和算法,不是CRC
      

  8.   

    Private Sub Command1_Click()
    '初始化一个测试数据
        Dim sendstr(10) As Byte
        sendstr(0) = &H2
        sendstr(1) = &H30
        sendstr(2) = &H31
        sendstr(3) = &H44
        sendstr(4) = &H54
        sendstr(5) = &H4D
        sendstr(6) = 0
        sendstr(7) = 0
        sendstr(8) = &HD
        sendstr(9) = &HA
        
    '计算校验和
        Call Lrc_Fun(sendstr, 5)
    End SubPublic Function Lrc_Fun(ByRef sendstr() As Byte, data_long As Byte)
        Dim xx As Long, tmp As Long, tmp1 As Long
        tmp = 0
        tmp1 = 0
        
        For xx = 0 To data_long
            tmp = tmp + sendstr(xx)
        Next    tmp = tmp Mod 100
        tmp1 = tmp Mod 10
        tmp = tmp \ 10
        
        sendstr(data_long + 1) = 30 + tmp
        sendstr(data_long + 2) = 30 + tmp1
    End Function
      

  9.   

    谢谢9楼的!你的那个其实是我4楼发的是一样的!只不过你用的mod!! 我感觉你的那个不对!!呵呵
    !!也就tiger_ZHAO真正看明白了!! Lrc_byteDD = Right(Lrc_DD, 2) 
    我回头改成mod试试!!
      

  10.   

    对不对试试不就知道了,你原先通过Lrc_data()数组返回计算结果,然后再填到SendStr的对应位置,偶在Lrc_Fun函数里算完就后就直接填到SendStr的对应位置里了。