Welcome Guest, you are in: Login

Fruit Of The Shed

Navigation (MMBasic)






Search the wiki

»


Modbus CRC uses the bit by bit method

Modified on 2018/12/13 06:03 by Bill Categorized as Communications
Introduction:
This CRC (Cyclic Redundancy Check) is for the Modbus RTU protocol as used in RS232 and RS485 communications. The CRC is a 16 bit word that is calculated from all of the data in a message. It cannot correct any data corruption but it will indicate if a message has been corrupted in some way. This program uses the bit-by-bit method to calculate the CRC.

PLEASE NOTE:
Although this is a Modbus CRC it is in no way restricted to be only used for the Modbus protocol. Any message structure consisting of a stream of 8-bit data bytes can utilise it. For example:
Msg$ = “The quick brown fox jumps over the lazy dog”

Acknowledgements:
This function was written by two members of The Back Shed forum:

TassyJim wrote the MMBasic version of the function.
Phil23 converted it to a string function to make it more user friendly.

I made a few tweaks to improve speed.
Bill McKinley

An example a Modbus message (in Hex) could look like:
Slave Address             18
Function Code             03
Start Address (Hi)        0B
Start Address (Lo)        B9
Number of points (Hi)     00
Number of points (Lo)     01
CRC (Lo)                  55
CRC (Hi)                  C2

Note that the High/Low order of bytes in the CRC is the reverse of that used for the data. I don’t know why.

In MMBasic without the CRC, that message would look like:

TxMsg$ = CHR$(&H18)+CHR$(&H03)+CHR$(&H0B)+CHR$(&HB9)+CHR$(&H00)+CHR$(&H01)

Add the CRC to the message by:

TxMsg$ = TxMsg$ + CrcStr(TxMsg$)

Performing a CRC check on a message that already includes a valid CRC will produce a 'CRC' of &h000 so:
Check the received message (eg RxMsg) by:

IF CrcStr(RxMsg$) = CHR$(0) + CHR$(0) THEN ' CRC is OK
' Process the response
ELSE
' Bad CRC - do nothing - don't respond
END IF

Assumptions:
None

The Function:
FUNCTION CrcStr(a$) AS STRING
  LOCAL ErrorWord% = &HFFFF, n, j, LSB AS INTEGER
  FOR n = 1 TO LEN(A$)
    ByteVal = ASC(MID$(a$, n, 1))
    ErrorWord% = (ErrorWord% AND &HFFFF) XOR ASC(MID$(a$, n, 1))
    FOR j = 1 TO 8
      LSB = ErrorWord% AND &H0001
      IF LSB = 1 THEN ErrorWord% = ErrorWord% - 1
      ErrorWord% = ErrorWord% / 2
      IF LSB = 1 THEN ErrorWord% = ErrorWord% XOR &HA001
    NEXT j
  NEXT n
  CrcStr = CHR$(ErrorWord% AND &HFF) + CHR$(ErrorWord% >> 8)
END FUNCTION