1
votes

With reference to this link Calculate CRC32 of an String or Byte Array I modified the code in order to calculate the CRC16 instead of CRC32, however I am getting wrong result, can some one point me where is the mistake?

Private Sub Main()
Crc16.ComputeChecksum(Encoding.UTF8.GetBytes("Some string"))
End Sub
    Public Class CRC16
Shared table As UShort()

Shared Sub New()
    Dim poly As UShort = &HA001US 'calculates CRC-16 using A001 polynomial (modbus)
    table = New UShort(255) {}
    Dim temp As UShort = 0
    For i As UShort = 0 To table.Length - 1
        temp = i
        For j As Integer = 8 To 1 Step -1
            If (temp And 1) = 1 Then
                temp = CUShort((temp >> 1) Xor poly)
            Else
                temp >>= 1
            End If
        Next
        table(i) = temp
    Next
End Sub

Public Shared Function ComputeChecksum(ByVal bytes As Byte()) As UShort
    Dim crc As UShort = &H0US ' The calculation start with 0x00
    For i As Integer = 0 To bytes.Length - 1
        Dim index As Byte = CByte(((crc) And &HFF) Xor bytes(i))
        crc = CUShort((crc >> 8) Xor table(index))
    Next
    Return Not crc
End Function
End Class
2

2 Answers

1
votes

Try this, it's working VB6 code for Instrument control. (sCommand is a temp string which contains all Bytes, Result is added to sCommand, Modbus is using LSB first, TextToString and StringToAscii are functions to convert a readable string "FF EE" into ASCII and back, thus they are not of interest here.):

Private Sub cmdCRC16_Click()
Dim sCommand As String
Dim x As Long
Dim y As Long
Dim lCRC As Long
sCommand = TextToString(txtASCII)
'Initial value
lCRC = 65535 '(&HFFFF results in Integer -1)
For x = 1 To Len(sCommand)
    lCRC = lCRC Xor Asc(Mid(sCommand, x, 1))
    For y = 1 To 8
        If (lCRC Mod 2) > 0 Then
            lCRC = (lCRC And 65534) / 2
            lCRC = lCRC Xor 40961 '(&HA001 results in whatever negative integer)
        Else
            lCRC = (lCRC And 65534) / 2
        End If
    Next y
Next x
'Add CRC with LSB first
sCommand = sCommand + Chr(lCRC And 255)
sCommand = sCommand + Chr((lCRC And 65280) / 256)
txtASCII = StringToASCII(sCommand)

End Sub

0
votes

I just came accross the same issue. Simple solution is to omit negation at the end, so just change your "Return Not crc" to "Return crc" and you be fine.

There are various variants of CRC-16, where "CRC-16" notmally refers to the IBM variant, also called "ARC". It uses an XorOut value of zero. See Catalogue of parametrised CRC algorithms with 16 bits.