Hallo, Wintermonate sind SW-Spielmonate. Ich will bei meinem Datenprotokoll die bisherige 16bit Checksum durch CRC16 nach CCITT erstezen. Aber das funzt nicht. Ich will nicht nerven, habe auch fleißig rumgegoogelt und auch hier im Forum gesucht, aber ich stehe auf dem Schlauch. Nehmen wir mal an, die Nachricht besteht nur aus $55, $AA, dann müßte die CRC laut "Breitbandkatze" sowie laut http://www.lammertbies.nl/comm/info/crc-calculation.html übereinstimmend 0xF8E5 ergeben. Aber die Nutzung Funktion des AVR-libc: _crc_ccitt_update (crc16, data) ergibt 0x57a7. Parallel habe ich das LIBC-Beispiel auf VB-express implementiert. Die Funktion: Private Function crc_ccitt_update(ByVal crc As UInt16, ByVal idata As Byte) As UInt16 Dim xdata As UInt16 xdata = idata xdata = xdata Xor (crc And &HFF) xdata = (xdata Xor (xdata << 4)) And &HFF crc = (((xdata << 8) Or (crc And &HFF00)) Xor (xdata >> 4) Xor (xdata << 3)) Return crc ' data ^= lo8 (crc); ' data ^= data << 4; ' return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) ' ^ ((uint16_t)data << 3)); End Function ergibt den Wert: 0xFDD5 Dieser stimmt weder mit dem ergebnis der ASM-Implementierung der libc laut crc16.h überein noch mit Breitbandkatze. Eine Implementierung aus einer anderen Quelle: Private Function crc_ccitt_update_5(ByVal crc As UInt16, ByVal idata As Byte) As UInt16 Dim xdata As UInt16 xdata = idata ' x = ((crc>>8) ^ data) & 0xff; xdata = ((crc >> 8) Xor xdata) And &HFF ' x ^= x>>4; xdata = xdata Xor (xdata >> 4) ' crc = (crc << 8) ^ (x << 12) ^ (x <<5) ^ x; crc = (crc << 8) Xor (xdata << 12) Xor (xdata << 5) Xor xdata crc = crc And &HFFFF Return crc End Function hingegen ergab den "richtigen" Breitbandkatzewert 0xF8E5 Ist die libc bzw crc16.h falsch? Muß ich ggf. das Makefile anpassen? Meines ist "Standard" laut AVR Studio? Osder hat einer eine korrekte schnelle Implementierung in ASM? Danke für Eure Mühen :-) Yogy
_crc_xmodem_update mit Startwert 0xffff liefert dir dein gewünschtes 0xF8E5 (und mit Startwert 0 das auch in den Internetrechnern für crc_xmodem gezeigte 0xE5EA). Ob jetzt eher die Internet-Rechner oder die avrlibc richtig liegen, darfst du selber rausfinden. Dem folgenden Kommentar in der avrlib-Doku nach tippe ich allerdings auf die avrlibc:
1 | Note: |
2 | Although the CCITT polynomial is the same as that used by the Xmodem protocol, |
3 | they are quite different. |
4 | The difference is in how the bits are shifted through the alorgithm. |
5 | Xmodem shifts the MSB of the CRC and the input first, |
6 | while CCITT shifts the LSB of the CRC and the input first. |
Oliver
Nachtrag: Vielleicht hilft das hier zu weiteren Verwirrung ;) http://regregex.bbcmicro.net/crc-catalogue.htm#crc.cat.crc-16-ccitt-false Oliver
Oh, das ging aber fix. Danke. Oliver. Damit funzt es. Ich vermute nal, die libc ist da fehlerhaft. Denn die ASM-Routinen entsprechen auch nicht dem genannten C-Beispiel, bzw. in C ist ein ODER anstelle eines XOR (bei return). Auch scheint mir der ASM Teil ein wenig verquer. Aber Hauptsache, es geht jetzt und ich kann das in C oder VB auf dem PC und mittels crc26.h auf dem AVR in C nutzen. Mal sehen, vlt. setze ich mich nochmals dran und versuche eine ASM Implementierung (Kenne mich -noch- nicht mit dem Interface GNU-C und ASM für den AVR aus) der erwähnten C-Routine "crc_ccitt_update_5" (Bei mir als VB laufend) Danke nochmals und schönes WE. Ich habe ja was zu tun... Yogy
So, ich habe die o.a. VB-Routine nach AVR / GNU-C portiert und passend für das File crc16.h dargestellt:
1 | static __inline__ uint16_t |
2 | _crc_ccitt_update (uint16_t __crc, uint8_t __data) |
3 | { |
4 | uint16_t __ret; |
5 | |
6 | __asm__ __volatile__ ( |
7 | |
8 | "eor %B0,%1" "\n\t" |
9 | |
10 | "mov __tmp_reg__,%B0" "\n\t" |
11 | "swap %B0" "\n\t" |
12 | "andi %B0,0x0f" "\n\t" |
13 | "eor %B0,__tmp_reg__" "\n\t" |
14 | "mov %1,%B0" "\n\t" |
15 | |
16 | "mov %B0,%A0" "\n\t" |
17 | "mov %A0,%1" "\n\t" |
18 | "swap %A0" "\n\t" |
19 | "andi %A0,0xf0" "\n\t" |
20 | "eor %B0,%A0" "\n\t" |
21 | |
22 | |
23 | "mov %A0,%1" "\n\t" |
24 | "lsr %A0" "\n\t" |
25 | "lsr %A0" "\n\t" |
26 | "lsr %A0" "\n\t" |
27 | "eor %B0,%A0" "\n\t" |
28 | |
29 | |
30 | "mov %A0,%1" "\n\t" |
31 | "swap %A0" "\n\t" |
32 | "andi %A0,0xf0" "\n\t" |
33 | "lsl %A0" "\n\t" |
34 | |
35 | "eor %A0,%1" "\n\t" |
36 | |
37 | |
38 | |
39 | : "=d" (__ret) |
40 | : "r" (__data), "0" (__crc) |
41 | : "r0" |
42 | ); |
43 | return __ret; |
Diese Routine ist kürzer als die dort angegebenen XMODEM-Routine. Zur freien Verwendung natürlich.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.