CRC Calculations


CRC is used to provide extra packet validity.
Calculation of the Cyclic Redundancy Check value is as follows:

Load a word register with 0xFFFF and call it CRCREG
Now repeat the following for each character (byte) in the Modbus packet
{
      XOR the low byte of the word register with the next (or first) character in the buffer
      Repeat the following for the whole character
      {
            Get the state of the lsb of CRCREG Low byte
            Shift the CRCREG right by one bit shifting in a zero in the msb
            If the bit shifted out is a logical 1
            {
                 
XOR CRCREG with 0xA001
            }
      }
}
CRCREG contains the CRC of the packet

Example C Code:

int CalcCRC( char * ModbusBuffer, int StringLength)
{
  unsigned char CRCREGLO = 0xff;
  unsigned char CRCREGHI = 0xff;
  char CarryBit1, CarryBit2;
  int CRC;
  int Index = 0;
  int IndexB = 0;
  if( StringLength == 0)
      return( 0);
  for(Index = 0; Index < StringLength; Index++)
  {
      CRCREGLO ^= (unsigned char) ModbusBuffer[Index];
      for(IndexB = 0; IndexB < 8; IndexB++)
      {
          CarryBit1 = CRCREGHI & 0x01;
          CarryBit2 = CRCREGLO & 0x01;
          CRCREGHI >>= 1;
          CRCREGHI &= 0x7f;
          CRCREGLO >>= 1;
          CRCREGLO &= 0x7f;
          if( CarryBit1 == 1)
                CRCREGLO |= 0x80;
          if( CarryBit2 != 0)
          {
                CRCREGLO ^= 0x01;
                CRCREGHI ^= 0xA0;
          }
      }
  }
  CRC = CRCREGLO;
  CRC <<= 8;
  CRC &= 0xff00;
  CRC |= CRCREGHI;
  return( CRC);
}

Example 2:
Building a packet to send to a slave asking for its ID

int AskForStatusFunction(char * ModbusBuffer, char NodeAddress)
{
  int BytesWritten, BytesToSend, error, CRC;
  BytesToSend = 0;
  ModbusBuffer[BytesToSend++] = NodeAddress;
  ModbusBuffer[BytesToSend++] = 17; // function 17 ID
  CRC = CalcCRC( ModbusBuffer, BytesToSend);
  ModbusBuffer[BytesToSend+1] = (char) CRC;
  CRC >>= 8;
  ModbusBuffer[BytesToSend++] = (char) CRC;
  BytesToSend++;
  BytesWritten = 0;
  while( BytesWritten < BytesToSend)
  {
      error = TransmitCommChar( PortID, ModbusBuffer[BytesWritten]);
      if( error == 0)
      BytesWritten++;
  }
  return( BytesWritten);
}

Example 3:
Checking a received packet's CRC

int CheckReceivedCRC( char * ModbusBuffer, int StringLength)
{
  // Used to calculate the CRC of a received packet
  // returns zero if the CRC is incorrect or 1 if it is correct.
  int CRC;
  if( StringLength < 2)
      return(0);
  StringLength -= 2;
  CRC = CalcCRC( ModbusBuffer, StringLength);
  StringLength++;
  if( ModbusBuffer[ StringLength] != (char)(CRC & 0x00ff))
      return(0);
  StringLength--;
  CRC >>= 8;
  if( ModbusBuffer[ StringLength] != (char)(CRC & 0x00ff))
      return(0);
  return(1);
}