I have tmc2209 stepper driver. I am planning to use UART for communication. The communication protocol looks pretty simple, but I can't figure out how to calculate this damn CRC. The polynomial is CRC-8 0x07. For the message 0x05 0x00 0x00 the correct CRC is 0x48 and for message 0x05 0x00 0x06 is correct CRC 0x6F. I know this because I have brute forced all possible combinations for these messages and with correct CRC tmc2209 responses. When I calculate CRC manually for these messages it doesn't match. They have some CRC example calculation in datasheet but this code looks broken for me. Here is the datasheet: https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2209_Datasheet_V103.pdf UART starts at page 15 and CRC calculation is on page 17.
Asked
Active
Viewed 458 times
2 Answers
4
CRC located in last byte of message
, add return datagram[datagramLength - 1];
on last method, you will get that crc
value. Look at this:
#include <stdio.h>
#include <stdint.h>
uint8_t swuart_calcCRC (uint8_t * datagram, uint8_t datagramLength) {
int i, j;
uint8_t *crc = datagram + (datagramLength - 1); // CRC located in last byte of message
uint8_t currentByte;
*crc = 0;
for (i = 0; i < (datagramLength - 1); i++) { // Execute for all bytes of a message
currentByte = datagram[i]; // Retrieve a byte to be sent from Array
for (j = 0; j < 8; j++) {
if ((*crc >> 7) ^ (currentByte & 0x01)) { // update CRC based result of XOR operation
*crc = (*crc << 1) ^ 0x07;
}
else {
*crc = (*crc << 1);
}
currentByte = currentByte >> 1;
} // for CRC bit
} // for message byte
return datagram[datagramLength - 1];
}
int main () {
uint8_t datagram1[] = { 0x05, 0x00, 0x00, 0x00 };
uint8_t datagram2[] = { 0x05, 0x00, 0x06, 0x00 };
uint8_t length = 4;
uint8_t crc1 = swuart_calcCRC (datagram1, length);
printf ("crc1: %02X\n", crc1);
uint8_t crc2 = swuart_calcCRC (datagram2, length);
printf ("crc2: %02X\n", crc2);
return 0;
}
Result:
crc1: 48
crc2: 6F

Ihdina
- 950
- 6
- 21
3
Documentation from your link says:
An 8 bit CRC polynomial is used for checking both read and write access. It allows detection of up to eight single bit errors. The CRC8-ATM polynomial with an initial value of zero is applied LSB to MSB, including the sync- and addressing byte. The sync nibble is assumed to always be correct. The TMC2209 responds only to correctly transmitted datagrams containing its own slave address. It increases its datagram counter for each correctly received write access datagram.
X^8 + X^2 + X^1 + X^0
And start value is 0
And even code is provided
void swuart_calcCRC(UCHAR* datagram, UCHAR datagramLength)
{
int i,j;
UCHAR* crc = datagram + (datagramLength-1); // CRC located in last byte of message
UCHAR currentByte;
*crc = 0;
for (i=0; i<(datagramLength-1); i++) { // Execute for all bytes of a message
currentByte = datagram[i]; // Retrieve a byte to be sent from Array
for (j=0; j<8; j++) {
if ((*crc >> 7) ^ (currentByte&0x01)) // update CRC based result of XOR operation
{
*crc = (*crc << 1) ^ 0x07;
}
else
{
*crc = (*crc << 1);
}
currentByte = currentByte >> 1;
} // for CRC bit
} // for message byte
}

unalignedmemoryaccess
- 7,246
- 2
- 25
- 40
-
Fair enough, when I have added one more field to array it spited right answer. But this is not "true" CRC. CRC is calculated from start to end and if you append CRC result to the message end you should get 0. Not in their approach.. They should not call it CRC. Thanks for answer. – andz Feb 05 '22 at 19:02