SENT CRC calculation

I am using SENT protocol in my project.

In my SENT implementation, the data nibbles are 3. So 12 bit data, including a status nibble and CRC nibble.

I need to calculate the CRC for 3 data nibbles.

The seed value for CRC calculation is 5 and the polynomial is

$x^{4} + x^{3} + x^2 + 1$

I have done the following for CRC calculation:

char CheckSum, i;
char CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
CheckSum= 5; // initialize checksum with seed "0101"
for (i=0; i<3; i++) {
CheckSum = CheckSum ^ Data[i];
CheckSum = CrcLookup[CheckSum];
}


In SENT analyser, I could see CRC error. The log is as follows

Can anyone tell me how to calculate the CRC for SENT protocol.

Note: I have 0XABC as data nibble and 3 is status nibble.

• Are you applying the data[i] in the correct order using 0 -> 1 -> 2 -> 3 ? It could be that it needs to be: 3 -> 2 -> 1 -> 0 – Michael Karas Feb 3 '17 at 13:24
• yeah, I am sending the data in correct order, MSB is first – Abdul Gafoor Feb 3 '17 at 13:37
• CheckSum = CheckSum^0x0A; I copied your code, but comparing CRC Calc with dsPIC32 built in CRC I had to add CheckSum = CheckSum^0x0A; then my calc of CRC was same as the built in CRC calc. – user203663 Nov 7 '18 at 18:38
• Sorry to write you more than one and a half years after, but... What if Data[i] is greater than 16? Isn't this case going to generate an index out of bounds error? – frarugi87 Nov 21 '18 at 15:32

After a lot of searching, comprising going on the SAE J2716 norm to see exactly what was the implementation like, I found out that the code was wrong. The order of the operations was inverted, and of course you should be sure that you are not accessing items out of bounds, like you would with your code.

The correct implementation should be:

uint8_t calculatedCRC, i;
const uint8_t CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
calculatedCRC = 5; // initialize checksum with seed "0101"

for (i = 0; i < 6; i++)
{
calculatedCRC = CrcLookup[calculatedCRC];
calculatedCRC = (calculatedCRC ^ Data[i]) & 0x0F;
}
// One more round with 0 as input
calculatedCRC = CrcLookup[calculatedCRC];


If you have, like in my case, the complete payload in a 32-bit variable in the format SDDDDDDC (S is the status nibble, C the CRC you have to verify), then the code can be modified in this way:

uint32_t crcData = YourOriginal32BitSentFrame;

uint8_t calculatedCRC, i;
const uint8_t CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
calculatedCRC = 5; // initialize checksum with seed "0101"

for (i = 0; i < 6; i++)
{
uint8_t crcDatum = (crcData >> 24) & 0x0F;

calculatedCRC = CrcLookup[calculatedCRC];
calculatedCRC = calculatedCRC ^ crcDatum;
crcData <<= 4;
}
// One more round with 0 as input
calculatedCRC = CrcLookup[calculatedCRC];


Best regards

According to the document here: http://www.nxp.com/assets/documents/data/en/application-notes/AN4219.pdf

So if you have the status nibble in data[0] you should try just computing CRC over data [1], data [2] and data [3].

• That's right !! as I already said that CRC calculation is for only 3 data nibbles. And I am computing only for data nibbles i.e data[1], data[2] and data[3]. – Abdul Gafoor Feb 3 '17 at 14:13
• @AbdulGafoor - Unless you have changed your code showing in the above question I happen to see a FOR loop that iterates over data[0], data[1] and data[2] instead of what you intended. – Michael Karas Feb 3 '17 at 23:49
• for status I am using another byte. It is not included in the data[], please ignore my above comment. – Abdul Gafoor Feb 6 '17 at 6:45