Checksums and CRC

What a CRC is, how to read Width/Poly/Init/RefIn/RefOut/XorOut/Check, how CRC differs from SUM/XOR/LRC and why the Modbus CRC is sent low byte first.

Why a checksum

The sender computes a short value from the data and appends it to the message. The receiver repeats the calculation: if the result differs, the message is corrupted and discarded. A checksum detects errors; it does not correct them and does not protect against deliberate tampering.

Simple sums

AlgorithmCalculationTypical use
SUM-8sum of bytes modulo 256simple instrument protocols
SUM-16sum of bytes modulo 65,536bootloaders, firmware files
XOR-8exclusive OR of all bytesNMEA 0183, simple protocols
LRCtwo's complement of the byte sumModbus ASCII

Simple sums miss swapped bytes and many double errors. A CRC of the same length is far stronger.

CRC

A CRC is the remainder of dividing the message, treated as a polynomial over GF(2), by a generator polynomial. In practice an algorithm is fully described by the Rocksoft parameter model (Ross Williams), used by the RevEng catalogue and most calculators:

ParameterMeaning
Widthresult size: 8, 16, 32 bit
Polygenerator polynomial without the top bit, in normal (MSB-first) notation
Initinitial register value
RefInwhether the bits of each input byte are reflected (processed LSB first)
RefOutwhether the final result is reflected
XorOutvalue XORed with the result at the end
CheckCRC of the ASCII string 123456789 — reference value for verifying an implementation

The same polynomial with different parameters gives different CRCs: CRC-16/ARC and CRC-16/MODBUS both use 0x8005, but with Init 0x0000 and 0xFFFF. So always name the algorithm fully, not just "CRC16".

Common variants

Name (RevEng)WidthPolyInitRefIn/OutXorOutCheck
CRC-16/MODBUS168005FFFFtrue00004B37
CRC-16/ARC1680050000true0000BB3D
CRC-16/IBM-3740 (CCITT-FALSE)161021FFFFfalse000029B1
CRC-16/XMODEM1610210000false000031C3
CRC-16/KERMIT1610210000true00002189
CRC-32/ISO-HDLC3204C11DB7FFFFFFFFtrueFFFFFFFFCBF43926
CRC-32/ISCSI (CRC-32C)321EDC6F41FFFFFFFFtrueFFFFFFFFE3069283

CRC value vs bytes in the frame

A CRC value is a number. The frame carries it as bytes in the order defined by the protocol. Modbus RTU sends the CRC low byte first:

Request:     01 03 00 00 00 02
CRC-16/MODBUS = 0x0BC4
In the frame: 01 03 00 00 00 02 C4 0B

If the calculator shows 0x0BC4 and the frame contains C4 0B, they are the same thing. This is the most common source of "my CRC doesn't match": comparing the value with bytes in the other order.

A useful property: CRC-16/MODBUS computed over the whole frame including a correctly appended CRC is zero.

Verifying your implementation

  1. Compute the CRC of 123456789 — the result must equal Check from the catalogue.
  2. Compare a real frame against an independent source (RevEng catalogue, crccalc.com, a language library).
  3. Make sure the bytes are appended in the protocol's order.

Tools

Loading the map…

Sources

  1. CRC RevEng — Catalogue of parametrised CRC algorithms — Greg Cook
  2. Ross N. Williams — A Painless Guide to CRC Error Detection Algorithms — zlib.net (mirror)
  3. MODBUS over Serial Line Specification and Implementation Guide V1.02 — Modbus Organization

Updated 2026-10-01