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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
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
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.