Forum: PC-Programmierung AVR CRC-16 CCITT mit HxD berechnen?


von Werner (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

in der AVR libc gibt es die Funktion
1
_crc_ccitt_update (uint16_t __crc, uint8_t __data)
die ich häufig benutze. Weiß jemand was man im HxD (Hexeditor) 
einstellen muss um auf das gleiche Ergebnis zu kommen?

Grüße
Werner

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Der Code sagt, dass das Polynom 0x8048 ist. Letztlich das gleiche wie 
die 0x1021 von Xmodem bit-swapped.

Aber: das Bit-Swapping bei CCITT ist nicht nur beim Polynom, sondern 
generell. (Hängt damit zusammen, dass Kommunikationsprotokolle immer Bit 
0 zuerst senden.) Musst du mal gucken, ob eine der "Reflektion"-Optionen 
(oder beide?) dann genau das bewirken.

Schieb doch einfach mal einen Testvektor da durch. Aus 802.15.4 kenne 
ich den hier:
1
0x02 0x00 0x6A 0xE4 0x79

Im Original liest der sich:
1
   0100 0000 0000 0000 0101 0110
2
b0 ............................b23
3
FCS:
4
   0010 0111 1001 1110
5
r0 ..................r15

: Bearbeitet durch Moderator
von Werner (Gast)


Lesenswert?

Danke Jörg,

bin weitergekommen. Ich habe mal Deinen Testvektor genommen:
1
#include <iostream>
2
3
using namespace std;
4
5
void updateCCITTCrc(uint16_t &crc, const void* buf, size_t len) {
6
  uint8_t b;
7
  uint8_t *ptr = (uint8_t*) buf;
8
9
  while (len--) {
10
    b = *ptr++ ^ (crc & 0xFF);
11
    b ^= b << 4;
12
    crc = ((((uint16_t)b << 8) | (crc >> 8)) ^ (uint8_t)(b >> 4) ^ ((uint16_t)b << 3));
13
  }
14
}
15
16
int main() {
17
    uint8_t testvect[] = {0x02, 0x00, 0x6A, 0xE4, 0x79};
18
    uint16_t crc = 0xFFFF;
19
    
20
    updateCCITTCrc(crc, testvect, sizeof(testvect));
21
    
22
    cout << hex << crc << endl; //-> 0x3088
23
24
    return 0;
25
}

Da kommt 0x3088 als Ergebnis raus. Dann mal diesen Testvektor z. B. hier 
einhacken:

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

Einstellungen:
CRC 16, Polynom 0x1021, Init Value 0xFFFF, Input- & Resultreflect 
aktiviert, dann kommt man auf das selbe Ergebnis.

Im HxD gilt das gleiche:
CRC 16,
Polynom 0x1021,
Startwert 0xFFFF,
Ein-/Ausgang reflektieren

Vielen Dank!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Werner schrieb:
> Da kommt 0x3088 als Ergebnis raus

Seltsam. Es sollte 0 rauskommen.

Ich hatte das vor Jahrzehnten mal geschrieben (als ich bei Atmel mit 
IEEE-802.15.4-Transceivern gearbeitet habe), leider finde ich den 
Sourcecode gerade nicht mehr, aber das Binary funktioniert noch:
1
% ./bin/gencrc 0x02 0x00 0x6A 0xE4 0x79
2
CRC = 0x0000
3
% ./bin/gencrc 0x02 0x00 0x6A 
4
CRC = 0x79e4

Ich glaube, der Unterschied ist, dass der Startvektor nicht 0xFFFF 
sondern 0x0000 ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> leider finde ich den Sourcecode gerade nicht mehr

Ah, doch noch gefunden.
1
#include <stdint.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <unistd.h>
5
6
uint16_t crc_ccitt_update (uint16_t crc, uint8_t data)
7
{
8
    data ^= crc & 0xff;
9
    data ^= data << 4;
10
11
    return ((((uint16_t)data << 8) | ((crc & 0xff00) >> 8))
12
            ^ (uint8_t)(data >> 4)
13
            ^ ((uint16_t)data << 3));
14
}
15
16
static void
17
usage(void)
18
{
19
    fprintf(stderr, "usage: gencrc [-b base] number...\n");
20
    exit(64);
21
}
22
23
int
24
main(int argc, char **argv)
25
{
26
    long i;
27
    int c, base;
28
    uint16_t crc = 0;
29
    uint8_t byte;
30
31
    base = 0;
32
    while ((c = getopt(argc, argv, "b:")) != -1)
33
        switch (c)
34
        {
35
        case 'b':
36
            base = strtol(optarg, 0, 0);
37
            break;
38
39
        default:
40
            usage();
41
        }
42
    argc -= optind;
43
    argv += optind;
44
45
    while (argc-- > 0) {
46
        i = strtol(argv[0], 0, base);
47
        byte = (uint8_t)i;
48
        crc = crc_ccitt_update(crc, byte);
49
        argv++;
50
    }
51
    printf("CRC = 0x%04x\n", crc);
52
    return 0;
53
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.