tmc2209步进驱动IC如何计算CRC?

How is tmc2209 stepper driver IC calculating CRC?

我有tmc2209步进驱动。我打算使用 UART 进行通信。通信协议看起来很简单,但我不知道如何计算这个该死的 CRC。多项式是 CRC-8 0x07。对于消息 0x05 0x00 0x00,正确的 CRC 是 0x48,对于消息 0x05 0x00 0x06,正确的 CRC 是 0x6F。我知道这一点是因为我已经暴力破解了这些消息的所有可能组合以及正确的 CRC tmc2209 响应。当我为这些消息手动计算 CRC 时,它不匹配。他们在数据表中有一些 CRC 示例计算,但这段代码对我来说看起来很糟糕。这是数据表: https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2209_Datasheet_V103.pdf UART从第15页开始,CRC计算在第17页。

您 link 的文档说:

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

起始值为0

甚至提供代码

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
}

CRC located in last byte of message,在最后一个方法上加上return datagram[datagramLength - 1];,你会得到那个crc值。看看这个:

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

结果:

crc1: 48
crc2: 6F