Modbus CRC in VB

Here is an example of Modbus CRC calculation in VB (tested with success).
Enjoy.
Pascal

'-------------------------------------------------
Public Function CRC(buf() As Byte, lbuf As Integer) As Integer
'-------------------------------------------------

' returns the MODBUS CRC of the lbuf first bytes of "buf" buffer (buf is a global array of bytes)
Dim CRC1 As Integer

CRC1 = &HFFFF ' init CRC
For i = 0 To lbuf - 1 Step 1 ' for each byte
CRC1 = CRC1 Xor buf(i)
For j = 0 To 7 Step 1 ' for each bit
k = CRC1 And 1 ' memo bit 0 state
CRC1 = ((CRC1 And &HFFFE) / 2) And H7FFF ' Shift right with 0 at left
If k > 0 Then CRC1 = CRC1 Xor &HA001 ' Bocuse
Next j
Next i
CRC = CRC1
End Function
 
B
Here is the routine that I use in Basic-X which is a subset of VB. Changing the variable types should be all thats required to make it run in VB. I start by setting iCurrentCRC (module level variable) to FFFF. As I assemble each byte of the Modbus message, I pass each byte thrugh this routine. Once the message is complete, the iCurrentCRC is appended to the end of the message in this order:
(iCurrentCRC Mod 256)
(iCurrentCRC \ 256)

Good luck!
Brad Watts.

Public Sub GetCRC(ByVal bValue As Byte)
Dim iValue As New UnsignedInteger
Dim CRCTemp As New UnsignedInteger
Dim Bit As Byte

iValue = CuInt(bValue)
CRCTemp = iCurrentCRC Xor iValue
For Bit = 0 To 7
If (CRCTemp And 1) = 1 Then
CRCTemp = CRCTemp \ 2
CRCTemp = CRCTemp Xor 40961
Else
CRCTemp = CRCTemp \ 2
End If
Next
iCurrentCRC = CRCTemp

End Sub
 
R

Richard Mahn

For those that may be interested, here's a more compact way to create the crc table in VB.

Dim usCRC(0 To 255) As Long

Sub mbus_FillCRCTable()
usCRC(0) = &H0: usCRC(1) = &HC0C1: usCRC(2) = &HC181: usCRC(3) = &H140
usCRC(4) = &HC301: usCRC(5) = &H3C0: usCRC(6) = &H280: usCRC(7) = &HC241
For i = 0 To 127
If i < 8 Then usCRC(8 + i) = usCRC(i) Xor &HC601 ' 8 through 15
If i < 16 Then usCRC(16 + i) = usCRC(i) Xor &HCC01 '16 through 31
If i < 32 Then usCRC(32 + i) = usCRC(i) Xor &HD801 '32 through 63
If i < 64 Then usCRC(64 + i) = usCRC(i) Xor &HF001 '64 through 127
usCRC(128 + i) = usCRC(i) Xor &HA001 '128 through 255
Next
End Sub
 
I had the same problem when dealing with VB and unsigned ints. During my bit shifting I used the "/" sign for the division. I noticed in Brad's code that he used the other "\" sign. I changed it and this corrected my overflow problems immediately!
 
T

Terry Shores

Thanks for posting this function! I needed to communicate with a Modbus unit and was having trouble getting the checksum right .... Your code works GREAT.

Terry V. Shores
 
Better to use two Bytes to hold the lo and hi parts of the CRC, then you don't have to mask the longs.
 
I have 1 Multimeter MFM383A C of Selec. But not knowing Frame transmission and reception. Who documentary about MFM383A C can give me. Many thanks
 
Top