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);
}
|