How To Calculate ModBus CheckSum


Thread Starter

Kris Grindstaff

I have to communicate to a ModBus device using Visual Basic. I have done this before with ModBus/TCP. But doing it over Ethernet you don't have to use the checksum. Can someone explain or provide any code on how to calculate this checksum using Visual Basic? Thanks!!!

Alex McPherson

Try This...

Private Function fbyCRC(pbyMsg() As Byte) As Byte()
'adds 2 bytes containing the CRC check to the array pbyMsg
'the message pbyMsg is passed as a Byte array
'the Ubound of the retuned array will be 2 more than Ubound(pbyMsg)
Dim lRef As Long
Dim lData As Long
Dim iRefLen As Integer
Dim byMsg() As Byte
Dim iUbound As Integer
Dim byCRC(1) As Byte
Dim index As Integer
Dim iCount As Integer

'For testing.....
'0B 08 00 00 AA 55 should return 5E 3E as CRC
'01 03 00 00 00 0A should return C5 CD as CRC
'01 03 00 14 00 3C should return 05 DF as CRC

'make a copy of the array
byMsg = pbyMsg
iUbound = UBound(byMsg)
lRef = &HFFFF&

For index = 0 To iUbound
lData = byMsg(index)
lRef = lRef Xor lData
For iCount = 1 To 8
If lRef / 2 <> Int(lRef / 2) Then iRefLen = 1 Else iRefLen = 0
lRef = Int(lRef / 2)
If iRefLen = 1 Then lRef = lRef Xor &HA001&
Next iCount
Next index

ReDim Preserve byMsg(iUbound + 2)
byMsg(iUbound + 1) = lRef And &HFF&
byMsg(iUbound + 2) = lRef \ &H100&
fbyCRC = byMsg
End Function

Carlos Araya \(PLC INT'L\)

We made a function in VB for MODBUS-RTU CRC calculation...

This function in VB, recieve the modbus buffer and produce the CRC in 2 bytes. DialString is an string with the modbus buffer, the function returns an string of 2 bytes with the CRC.
' Calculo de CRC polinomio grado 16.
' Recibe el string a verificar
' Returna un string de dos bytes con el CRC calculado
Function CRC(DialString As String)
Dim G As Long, A As Long, AUX As Long
Dim ALow As Long, AHigh As Long, AL As Long, Carry As Integer
Dim i As Integer, j As Integer, cA As Long, cHex As String
A = 65535
G = 40961
i = 0
Do While i < Len(DialString$)
j = 0
ALow = Int(A / 256)
ALow = ALow * 256
ALow = A - ALow
AHigh = Int(A / 256) * 256
cA = Asc(Mid$(DialString, i + 1, 1))
AL = Int(cA Xor ALow)
AUX = Int(AHigh + AL)
Do While j < 8
j = j + 1
A = Int(A / 2)
Carry = AUX Mod 2
If Carry = 1 Then
A = Int(G Xor A)
End If
i = i + 1
ALow = A - Int(A / 256) * 256
AHigh = Int(A / 256)
CRC = Chr(ALow) + Chr(AHigh)
End Function

Good luck!!

Carlos Araya Mackenney
Automation Manager - PLC International S.A.
Phone (562) 269.8727 Fax (562) 269.8728
Santiago de Chile

Gleb Chikalo

I have checked up algorithm from page "": (steps 1 - 7). It works incorrectly. That is the result is not equal to result
on an output of function CRC16 from the same page. Suggest, whether somebody knows
as by hardware (the triggers and XOR-adders) possible to generate CRC for MODBUS messages.
The function CRC16 does not approach me as it requires availability of the tables, and size of program memory at the microcontroller is

Alex Pavloff

This following code DOES work (is working in current applications). I suspect the code on the Modicon page works also -- but keep in mind that the Modbus byte order is different than an i386 PC.

This code is C++ code, so you'll have to change it if all you've got is a C compiler.

unsigned short Crc16Modbus(const char *pData, size_t length )
unsigned short crc = 0xFFFF;
for(size_t n=0;n<length;++n)
unsigned char comb_val = (crc>>8) ^ pData[n];
crc = (crc<<8) ^ modbus_16_tbl[comb_val & 0x00FF];
return crc;

static unsigned short modbus_16_tbl[] =

static unsigned short modbus_16_tbl[] =
0x0000, 0xC1C0, 0x81C1, 0x4001, 0x01C3, 0xC003, 0x8002, 0x41C2,
0x01C6, 0xC006, 0x8007, 0x41C7, 0x0005, 0xC1C5, 0x81C4, 0x4004,
0x01CC, 0xC00C, 0x800D, 0x41CD, 0x000F, 0xC1CF, 0x81CE, 0x400E,
0x000A, 0xC1CA, 0x81CB, 0x400B, 0x01C9, 0xC009, 0x8008, 0x41C8,
0x01D8, 0xC018, 0x8019, 0x41D9, 0x001B, 0xC1DB, 0x81DA, 0x401A,
0x001E, 0xC1DE, 0x81DF, 0x401F, 0x01DD, 0xC01D, 0x801C, 0x41DC,
0x0014, 0xC1D4, 0x81D5, 0x4015, 0x01D7, 0xC017, 0x8016, 0x41D6,
0x01D2, 0xC012, 0x8013, 0x41D3, 0x0011, 0xC1D1, 0x81D0, 0x4010,
0x01F0, 0xC030, 0x8031, 0x41F1, 0x0033, 0xC1F3, 0x81F2, 0x4032,
0x0036, 0xC1F6, 0x81F7, 0x4037, 0x01F5, 0xC035, 0x8034, 0x41F4,
0x003C, 0xC1FC, 0x81FD, 0x403D, 0x01FF, 0xC03F, 0x803E, 0x41FE,
0x01FA, 0xC03A, 0x803B, 0x41FB, 0x0039, 0xC1F9, 0x81F8, 0x4038,
0x0028, 0xC1E8, 0x81E9, 0x4029, 0x01EB, 0xC02B, 0x802A, 0x41EA,
0x01EE, 0xC02E, 0x802F, 0x41EF, 0x002D, 0xC1ED, 0x81EC, 0x402C,
0x01E4, 0xC024, 0x8025, 0x41E5, 0x0027, 0xC1E7, 0x81E6, 0x4026,
0x0022, 0xC1E2, 0x81E3, 0x4023, 0x01E1, 0xC021, 0x8020, 0x41E0,
0x01A0, 0xC060, 0x8061, 0x41A1, 0x0063, 0xC1A3, 0x81A2, 0x4062,
0x0066, 0xC1A6, 0x81A7, 0x4067, 0x01A5, 0xC065, 0x8064, 0x41A4,
0x006C, 0xC1AC, 0x81AD, 0x406D, 0x01AF, 0xC06F, 0x806E, 0x41AE,
0x01AA, 0xC06A, 0x806B, 0x41AB, 0x0069, 0xC1A9, 0x81A8, 0x4068,
0x0078, 0xC1B8, 0x81B9, 0x4079, 0x01BB, 0xC07B, 0x807A, 0x41BA,
0x01BE, 0xC07E, 0x807F, 0x41BF, 0x007D, 0xC1BD, 0x81BC, 0x407C,
0x01B4, 0xC074, 0x8075, 0x41B5, 0x0077, 0xC1B7, 0x81B6, 0x4076,
0x0072, 0xC1B2, 0x81B3, 0x4073, 0x01B1, 0xC071, 0x8070, 0x41B0,
0x0050, 0xC190, 0x8191, 0x4051, 0x0193, 0xC053, 0x8052, 0x4192,
0x0196, 0xC056, 0x8057, 0x4197, 0x0055, 0xC195, 0x8194, 0x4054,
0x019C, 0xC05C, 0x805D, 0x419D, 0x005F, 0xC19F, 0x819E, 0x405E,
0x005A, 0xC19A, 0x819B, 0x405B, 0x0199, 0xC059, 0x8058, 0x4198,
0x0188, 0xC048, 0x8049, 0x4189, 0x004B, 0xC18B, 0x818A, 0x404A,
0x004E, 0xC18E, 0x818F, 0x404F, 0x018D, 0xC04D, 0x804C, 0x418C,
0x0044, 0xC184, 0x8185, 0x4045, 0x0187, 0xC047, 0x8046, 0x4186,
0x0182, 0xC042, 0x8043, 0x4183, 0x0041, 0xC181, 0x8180, 0x4040

Good luck

Alex Pavloff
Software Engineer
Eason Technology