CRC-X25 mit 256Byte Tabelle

Im Nebenthema rund um das SML-Protokoll komme ich mit der CRC nicht klar.
Bisher nehme ich ein gesamtes Bytearray und lasse das mit

checken. Das klappt auch. Die CRC's stimmen mit den übermittelten überein.

Nun will ich das gerne nicht erst machen, wenn alle Daten hier sind, sondern bereits beim einlesen.
Ausserdem ist mir die Tabelle mit 1024bytes zu groß.
Eigentlich soll das auch mit 256 bytes gehen.
Aber beim Versuch mit dem entliehenen Code von

static const uint16_t smlCrcTable[256]  =

{
  0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48,
  0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 0x1081, 0x0108,
  0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 0x9CC9, 0x8D40, 0xBFDB,
  0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 0x2102, 0x308B, 0x0210, 0x1399,
  0x6726, 0x76AF, 0x4434, 0x55BD, 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E,
  0xFAE7, 0xC87C, 0xD9F5, 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E,
  0x54B5, 0x453C, 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD,
  0xC974, 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
  0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 0x5285,
  0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 0xDECD, 0xCF44,
  0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 0x6306, 0x728F, 0x4014,
  0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5,
  0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3,
  0x242A, 0x16B1, 0x0738, 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862,
  0x9AF9, 0x8B70, 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E,
  0xF0B7, 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
  0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 0x18C1,
  0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 0xA50A, 0xB483,
  0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 0x2942, 0x38CB, 0x0A50,
  0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 0xB58B, 0xA402, 0x9699, 0x8710,
  0xF3AF, 0xE226, 0xD0BD, 0xC134, 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7,
  0x6E6E, 0x5CF5, 0x4D7C, 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1,
  0xA33A, 0xB2B3, 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72,
  0x3EFB, 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
  0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 0xE70E,
  0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 0x6B46, 0x7ACF,
  0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 0xF78F, 0xE606, 0xD49D,
  0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 0x7BC7, 0x6A4E, 0x58D5, 0x495C,
  0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};

const uint8_t sml[] =
{
  // Start Nachricht
  0x1b, 0x1b, 0x1b, 0x1b,
  0x01, 0x01, 0x01, 0x01,
  // Start Message 1
  0x76, 0x05, 0x00, 0xa0,
  0xd9, 0xb6, 0x62, 0x00,
  0x62, 0x00, 0x72, 0x63,
  0x01, 0x01, 0x76, 0x01,
  0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x05,
  0x00, 0x35, 0x9d, 0xe8,
  0x0b, 0x0a, 0x01, 0x45,
  0x4d, 0x48, 0x00, 0x00,
  0xb9, 0x77, 0x35, 0x72,
  0x62, 0x01, 0x65, 0x00,
  0x23, 0xc9, 0x77, 0x62,
  0x01,
  0x63,            // Ankündigung CRC - das Byte zählt noch mit!
  0x64, 0x16,      // CRC - Achtung die Bytes sind vertauscht!
};

uint16_t crc = 0xFFFF;

void setup()
{
  Serial.begin(115200);
  for (uint16_t i = 8; i < sizeof(sml); i++)
  {
    crc16(sml[i]);
    Serial.print(sml[i]);
    Serial.print(' ');
    Serial.println(crc);
  }
}

void crc16(const byte &myByte)
{
  crc =  smlCrcTable[(myByte ^ crc) & 0xff] ^ (crc >> 8 & 0xff);
}

void loop()
{}

wird das nichts. Ich lese ab Byte [8] aus dem Puffer. Es müsste 2Bytes vor Schluß die CRC 0x1664 ausgegeben werden. Macht es aber nicht.
Setze ich das als Puffer und nehme fastCRC passt es.
Ich würde gern die 256Byte-Variante und im laufenden Lesen nehmen.
Unrichtige Tabelle?

Eigentlich geht es auch ganz ohne Tabelle. Ist dann natürlich langsamer. Als es erfunden wurde, war daran gedacht, dass es bitweise in Hardware geht. Und CRC-16 und CRC-CCITT (auch 16 bit) gibt es in einigen Varianten, wie ich hier gelernt habe.

Test mit ESP32
#include <rom/crc.h>

static const uint16_t smlCrcTable[256]  =
{
  0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48,
  0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 0x1081, 0x0108,
  0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 0x9CC9, 0x8D40, 0xBFDB,
  0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 0x2102, 0x308B, 0x0210, 0x1399,
  0x6726, 0x76AF, 0x4434, 0x55BD, 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E,
  0xFAE7, 0xC87C, 0xD9F5, 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E,
  0x54B5, 0x453C, 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD,
  0xC974, 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
  0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 0x5285,
  0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 0xDECD, 0xCF44,
  0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 0x6306, 0x728F, 0x4014,
  0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5,
  0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3,
  0x242A, 0x16B1, 0x0738, 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862,
  0x9AF9, 0x8B70, 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E,
  0xF0B7, 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
  0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 0x18C1,
  0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 0xA50A, 0xB483,
  0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 0x2942, 0x38CB, 0x0A50,
  0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 0xB58B, 0xA402, 0x9699, 0x8710,
  0xF3AF, 0xE226, 0xD0BD, 0xC134, 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7,
  0x6E6E, 0x5CF5, 0x4D7C, 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1,
  0xA33A, 0xB2B3, 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72,
  0x3EFB, 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
  0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 0xE70E,
  0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 0x6B46, 0x7ACF,
  0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 0xF78F, 0xE606, 0xD49D,
  0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 0x7BC7, 0x6A4E, 0x58D5, 0x495C,
  0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};

const uint8_t sml[] =
{
  0x76, 0x05, 0x00, 0xa0,
  0xd9, 0xb6, 0x62, 0x00,
  0x62, 0x00, 0x72, 0x63,
  0x01, 0x01, 0x76, 0x01,
  0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x05,
  0x00, 0x35, 0x9d, 0xe8,
  0x0b, 0x0a, 0x01, 0x45,
  0x4d, 0x48, 0x00, 0x00,
  0xb9, 0x77, 0x35, 0x72,
  0x62, 0x01, 0x65, 0x00,
  0x23, 0xc9, 0x77, 0x62,
  0x01,
  0x63             // Ankündigung CRC - das Byte zählt noch mit!
};
//  0x64, 0x16,      // CRC - Achtung die Bytes sind vertauscht!

uint16_t crc = 0xFFFF;
uint16_t crcWert = 0;

void setup()
{
  Serial.begin(115200);
  delay(500);
  for (uint16_t i = 0; i < sizeof(sml); i++)
  {
    // CRC-16/X25, poly = 0x1021, init = 0xffff, refin = true, refout = true, xorout = 0xffff
    crcWert = (~crc16_le((uint16_t)~(0xffff), sml, i + 1 )) ^ 0xffff;

    crc16(sml[i]);
    Serial.printf("%3u %02X %04X %04X\n", i, sml[i], crc, crcWert);
  }
}

void crc16(const byte &myByte)
{
  crc =  smlCrcTable[(myByte ^ crc) & 0xff] ^ (crc >> 8 & 0xff);
}

void loop()
{}
Ergebnis
  0 76 1936 E6C9
  1 05 0301 FCFE
  2 00 118A EE75
  3 A0 8E49 71B6
  4 D9 9407 6BF8
  5 B6 A496 5B69
  6 62 B10F 4EF0
  7 00 F846 07B9
  8 62 67DE 9821
  9 00 3F94 C06B
 10 72 8207 7DF8
 11 63 25A0 DA5F
 12 01 B4A6 4B59
 13 01 D101 2EFE
 14 76 07E9 F816
 15 01 6B41 94BE
 16 07 2759 D8A6
 17 FF C01B 3FE4
 18 FF A1EA 5E15
 19 FF 478D B872
 20 FF 50D2 AF2D
 21 FF FAB7 0548
 22 FF CEB6 3149
 23 05 87DE 7821
 24 00 3F74 C08B
 25 35 53B2 AC4D
 26 9D D9A6 2659
 27 E8 ABA3 545C
 28 0B 29E9 D616
 29 0A D5BC 2A43
 30 01 6EBB 9144
 31 45 1E9F E160
 32 4D F581 0A7E
 33 48 5B38 A4C7
 34 00 BD90 426F
 35 00 9434 6BCB
 36 B9 5F79 A086
 37 77 E921 16DE
 38 35 564C A9B3
 39 72 D8AB 2754
 40 62 5B15 A4EA
 41 01 56FE A901
 42 65 2A0C D5F3
 43 00 CA46 35B9
 44 23 3461 CB9E
 45 C9 2976 D689
 46 77 11A0 EE5F
 47 62 E50F 1AF0
 48 01 E99B 1664  ←
 49 63 7B2E 84D1

Zielwert siehe Pfeil, paßt nicht zu "Ankündigung CRC - das Byte zählt noch mit!"

Guten Morgen,

Die Erfahrung musste ich auch machen.
Und auch da ist die Doku nicht ganz unschuldig dran.
Denn es heißt, es werden alle Bytes gezählt, ausser die 2 Byte der CRC selbst.

Danke fürs bauen.

Mal sehen, was draus wird. Lese mich gerade in class ein. Nachdem ich das vorher schön versucht habe in structs zu packen und das recht einfach war, bin ich der Überzeugung man kann die ganze Aufteilerei mit Methoden handeln. Die Anzahl der (notwendigen) Instanzen kann man ja während der Laufzeit ermitteln....

Dann stimmt das ja, was ich gemacht habe :slightly_smiling_face:

Hast Du CRC gelöst oder suchst Du noch nach einer passenden Tabelle?

Funktionen legen Daten auf den Stack, wenn sie "rekursieren", daher hätte ich Dir im anderen Thema Methoden empfohlen, möglicherweise können die das ja auch. Allerdings ergab sich für mich noch keine Notwendigkeit, das zu probieren. Nichts Genaues weiß ich also nicht :crazy_face:

Ich hab gestern mittlerweile einige Versuche mit der "onTheFly"-Rechnerei durch und bin nicht vorwärts gekommen.
Mit der FastCRC stimmt es.
Versuche ich was anderes, kommt nur Murks bei raus.
Letzter Einstieg war
https://www.researchgate.net/post/How_to_calculate_CRC-16_X-25
Und ich komm da auf keinen grünen Zweig.
Hab das dann sein gelassen und mich dem lesen hingeben.

Test mit ESP32
#include <rom/crc.h>

static const uint16_t smlCrcTable[256]  =
{ // Quelle: https://postmodern.github.io/docs/crc.cr/CRC/CRC16X25.html
  0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 
  0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 
  0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 
  0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 
  0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, 
  0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, 
  0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, 
  0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, 
  0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, 
  0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 
  0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 
  0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 
  0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 
  0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 
  0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, 
  0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, 
  0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, 
  0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, 
  0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 
  0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 
  0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 
  0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 
  0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, 
  0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, 
  0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, 
  0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, 
  0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, 
  0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 
  0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 
  0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 
  0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 
  0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};

const uint8_t sml[] =
{
  0x76, 0x05, 0x00, 0xa0,
  0xd9, 0xb6, 0x62, 0x00,
  0x62, 0x00, 0x72, 0x63,
  0x01, 0x01, 0x76, 0x01,
  0x07, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x05,
  0x00, 0x35, 0x9d, 0xe8,
  0x0b, 0x0a, 0x01, 0x45,
  0x4d, 0x48, 0x00, 0x00,
  0xb9, 0x77, 0x35, 0x72,
  0x62, 0x01, 0x65, 0x00,
  0x23, 0xc9, 0x77, 0x62,
  0x01,
};
//  0x64, 0x16,      // CRC - Achtung die Bytes sind vertauscht!

uint8_t s[1] = {0};


uint16_t crc = 0xFFFF;
uint16_t crcWert = 0;

void setup()
{
  Serial.begin(115200);
  delay(500);
  for (uint16_t i = 0; i < sizeof(sml); i++)
  {
    // CRC-16/X25, poly = 0x1021, init = 0xffff, refin = true, refout = true, xorout = 0xffff
    crcWert = (~crc16_le((uint16_t)~(0xffff), sml, i + 1 )) ^ 0xffff;

    Serial.printf("%3u %02X %04X %04X\n", i, sml[i], crc16(sml[i]), crcWert);
  }
}

uint16_t crc16(const byte &myByte)
{
  crc = smlCrcTable[(myByte ^ crc) & 0xff] ^ (crc >> 8 & 0xff);
  return ~crc;
}

void loop()
{}
Ergebnis
  0 76 E6C9 E6C9
  1 05 FCFE FCFE
  2 00 EE75 EE75
  3 A0 71B6 71B6
  4 D9 6BF8 6BF8
  5 B6 5B69 5B69
  6 62 4EF0 4EF0
  7 00 07B9 07B9
  8 62 9821 9821
  9 00 C06B C06B
 10 72 7DF8 7DF8
 11 63 DA5F DA5F
 12 01 4B59 4B59
 13 01 2EFE 2EFE
 14 76 F816 F816
 15 01 94BE 94BE
 16 07 D8A6 D8A6
 17 FF 3FE4 3FE4
 18 FF 5E15 5E15
 19 FF B872 B872
 20 FF AF2D AF2D
 21 FF 0548 0548
 22 FF 3149 3149
 23 05 7821 7821
 24 00 C08B C08B
 25 35 AC4D AC4D
 26 9D 2659 2659
 27 E8 545C 545C
 28 0B D616 D616
 29 0A 2A43 2A43
 30 01 9144 9144
 31 45 E160 E160
 32 4D 0A7E 0A7E
 33 48 A4C7 A4C7
 34 00 426F 426F
 35 00 6BCB 6BCB
 36 B9 A086 A086
 37 77 16DE 16DE
 38 35 A9B3 A9B3
 39 72 2754 2754
 40 62 A4EA A4EA
 41 01 A901 A901
 42 65 D5F3 D5F3
 43 00 35B9 35B9
 44 23 CB9E CB9E
 45 C9 D689 D689
 46 77 EE5F EE5F
 47 62 1AF0 1AF0
 48 01 1664 1664

Der Trick liegt darin, die invertierte CRC nicht für die Berechnung zu verwenden, sondern erst am Schluß für den Vergleich.

Bringt Dich das weiter?

1 Like

Muss ich nachher sehen, wenn ich Zeit habe und nen Monitor mit dem Code bespassen kann.
Danke.
Ps: unter [details] kannst auch noch [code] drunter schreiben - nur druaf achten, das Du [/code] dann vor [/details] schreiben musst.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.