Forum: Mikrocontroller und Digitale Elektronik ATmega128 - CRC16 nach CCITT mit vielen Bytes


von Björn Niethammer (Gast)


Angehängte Dateien:

Lesenswert?

Moin Moin!

Ich sitze hier an einem kleinen Problem. Vielleicht könnt ihr mir ja 
helfen.

Für ein serielles proprietäres Protokoll muss ich eine CRC16 Checksumme 
berechnen. Dazu werden alle ASCII Zeichen zwischen dem Start und Ende 
Zeichen in die Berechnung mit einbezogen. Wenn ich nun eine kurze 
Meldung schicken will klappt die Berechnung auch wunderbar. Kurz 
bedeutet zwei Zeichen für Ziel, zwei Zeichen für Quelle und ein Zeichen 
als positive Quitierung. Wenn ich nun aber eine längere Meldung schicken 
will (z.B. beim Hochfahren zum Statusabgleich anfordern) dann bleibt die 
Checksumme Null. Es werden also 4 Bytes mit je 0x00 gesendet. Dies ist 
natürlich nicht richtig. Nach der klasse Webseite 
http://www.zorc.breitbandkatze.de/crc.html müsste die Checksumme "61CB" 
sein wenn ich das Datum "b2400000000000001" senden will.

Nun meine Frage - habt ihr eine Idee wieso bei diesem Datum bei mir als 
Checksumme "0" rauskommt?


Eingesetzt wird der ATmega128 von ATMEL mit dem CodeVisonAVR Compiler in 
der Version 1.25.7a. Das Board ist ein Entwicklungsboard der FTZ 
Leipzig. Zu finden unter http://www.easytoweb.net.

Ich habe mal eine gekürzte Version meines Sourcecodes angehängt. In der 
Funktion minimax_quitierung() wird eine Checksumme berechnet die auch 
richtig ist. In der Funktion minimax_statusabgleich() wird auch eine CRC 
berechnet die aber den oben beschriebenen Fehler aufweist.

Vielen Dank schonmal für eure Mühe.

Gruß
Björn Niethammer

von Yagan Ζ. D. (yagan)


Lesenswert?

Björn,

in minimax_statusabgleich() hast du
unsigned char crc_wert = 0x0000; geschrieben, was mir nicht richtig 
erscheint.
Es müsste unsigned int sein.
Ausserdem sehe ich nirgends eine Zuweisung der Art
crc_word = (unsigned char *)(&crc_wert);
damit auch der CRC-Wert gesendet wird.

Ciao, Yagan

von Björn Niethammer (Gast)


Lesenswert?

Hallo Yagan!

Die Deklarierung der Variable hab ich testweise mal auf unsigned char 
gesetzt. Das war vorher immer unsigned int. Auch hab ich unsigned long 
getestet um einen Overflow auszuschließen. In allen Fällen kommt aber 0 
als Ergebnis zurück.

Die Zuweisung

crc_word = (unsigned char *)(&crc_wert);

erledige ich mit der Anweisung

sprintf(crc_word,"%04X",crc_wert);

Damit wird die Variable crc_wert auf crc_word gecastet, auf 4 Stellen 
begrenzt und in dem Fall, dass es weniger als 4 Zeichen sind führende 
Nullen eingefügt. In all meinen anderen Funktionen klappt das auch 
einwandfrei. Nur in der minimax_statusabgleich() nicht.

Ich werde trotzdem mal deine cast Anweisung testen. Um Auszuschließen 
das es an der sprintf() Funktion liegt. Mal sehen was da rauskommt. 
Melde mich mit dem Ergebnis dann wieder zurück.

Gruß
Björn Niethammer

von Björn Niethammer (Gast)


Lesenswert?

So ich habe mal die cast Anweisung

crc_word = (unsigned char *)(&crc_wert);

getestet. Leider kommt da zwar was raus aber nicht das was ich brauche. 
Das Protokoll sieht eine ASCII->HEX Darstellung. Also der HEX Wert des 
CRC wird in ACSII Zeichen gewandelt und übertragen. Wenn ich obige cast 
Anweisung nutze dann werden aber die HEX Werte übertragen. Somit bin ich 
auf die sprintf() Funktion angewiesen.

Ich hab jetzt auch mal testweise den Wert von crc_wert manuell 
festgelegt. Auch dann gibt sprintf() Null als Wert für crc_word zurück. 
Gibt es bei sprintf() irgendwelche Einschränkungen oder Probleme 
weswegen es so ein Verhalten gibt?

von Yagan Ζ. D. (yagan)


Lesenswert?

Hallo Björn

> Die Zuweisung
>
> crc_word = (unsigned char *)(&crc_wert);
>
> erledige ich mit der Anweisung
>
> sprintf(crc_word,"%04X",crc_wert);

ok, das habe ich nicht beachtet.

Dann liegt das Problem darin, dass crc_word nur als pointer deklariert 
ist, aber kein Speicher dahinter steht.
Schreibe
         unsigned char crc_word[5]; // string für 4 chars CRC 
hexadezimal.
dann müsste es allein mit
         sprintf(crc_word,"%04X",crc_wert); und
         uart_write_block(UART_DEV1,crc_word,4);
funktionieren.

Ciao, Yagan

von Björn Niethammer (Gast)


Lesenswert?

Ohh super! Vielen vielen Dank Yagan. Das war tatsächlich das Problem. 
Mich wundert nur das es in all den anderen Funktionen wo ich auch die 
CRC Berechnung drinn habe es nicht zu diesem Fehler gekommen ist(siehe 
z.B. die minimax_quitierung() in dem Anhang). Na vielleicht war das auch 
nur Zufall das es klappte. Ich werde vorsichtshalber in allem Funktionen 
diese Zuweisung von Speicher mit reinnehmen.

Erinnert mich auch irgendwie an meinen meistgemachten Fehler bei der 
Programmierung unter Linux. Wenn da was nicht ging war es meist ein 
vergessenes malloc(). ;-)

Nochmal vielen Dank für deinen schnelle Hilfe. Weiter so!

Gruß
Björn Niethammer

von Yagan Ζ. D. (yagan)


Lesenswert?

Björn,

dass es manchmal funktioniert, kann daran liegen, dass der pointer auf 
irgendeinen vorhandenen oder unbenutzten Speicherbereich zeigt. Dadurch 
können aber seltsame Nebeneffekte auftreten.

Eigentlich müsste der Compiler eine Warnung absetzen, dass eine benutze 
Variable nicht initialisiert ist.

Ciao, Yagan

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.