Checksumme bestimmen (wahrscheinlich CRC8)

OP #4262561
Lesenswert?

Hallo,
ich habe eine Übertragung zwischen zwei Controllern, die nicht in meiner 
Hand liegt. Nun würde ich gerne selber Telegramme einschleusen. Das 
Problem ist, dass ich hierfür die Checksumme berechnen muss.

Das Telegram besteht aus STX Nutzdaten Checksumme ETX.

Hier sind mal 3 Beispiele:
1
02 02 01 01 D5 03
2
02 02 01 00 8B 03 
3

4
02 12 01 00 C1 03 
5

6
02 18 03 00 00 00 CA 03

Kann man anhand dieser Beispiele bereits das Polynom oder das Verfahren 
bestimmen? Gibt es evtl. ein Tool, welches ich mit dem Beispiel füttere 
und welches dann alle Polynome o.ä. per Brute-Force durchgeht?

Vielen Dank!
Gast #4263367
Lesenswert?

Fabian H. (hdr)schrieb:
>Hier sind mal 3 Beispiele:

Vier ;-)

Sind die Daten wirklich richtig erhoben?

>
>02 02 01 01 D5 03

Woher soll das "Protokoll" erkenen, welcher der 02er
der Start ist.

>02 02 01 00 8B 03
>
>02 12 01 00 C1 03
>
>02 18 03 00 00 00 CA 03

Hm, welcher 03er zeigt denn nun das Ende an?

Das Uebertragungsprotokoll waere ziemlich vermurkst,
wenn die bisherigen Hypothesen so stimmen.
#4263427
Lesenswert?

Zuumindest bei den Seriellen Protokollen mit denen
ich üblicherweise zu tun habe kommt die Checksumme nach ETX.
Dort wird das Paket ohne STX, aber mit ETX über simples XOR
der Bytes mit einer "Checksumme" (BCC) am Ende versehen.
Also:
1
STX XX XX XX XX ETX BCC

> Woher soll das "Protokoll" erkenen, welcher der 02er der Start ist.

Start kann ja nur das erste STX sein. Danach sucht man ja
üblicherweise nach dem ETX. Hat sein Paket zusammen, zieht
die Checksumme, und vergleicht sie mit der Checksumme
des Paketes.

Wenn die Checksumme wirklich Teil des Paketes ist, dann muss
verhindert werden, dass diese den Wert ETX annimmt.
Entweder über spezielles Escaping oder indem man die Checksumme
hinter das ETX schiebt.
OP #4263428
Lesenswert?

Tiramisu schrieb:
> Das Uebertragungsprotokoll waere ziemlich vermurkst,
> wenn die bisherigen Hypothesen so stimmen.

Warum vorhandene 02 / 03 des Frames nicht Escaped werden ist mir auch 
ein Rätsel, aber ist halt so...

Eine komplette Nachricht sieht so aus:

<STX> <Kommando> <Payload-Länge> <Payload> <CRC> <ETX>

Wobei das niederwertigste Bit des Kommandos immer die Datenrichtung 
angibt.

Durch das zeitliche Verhalten (immer ca. 1 Sekunde Pause zwischen den 
Telegrammen) sollten die oben gezeigten Telegramme schon richtig 
dargestellt sein. Durch STX, Länge, CRC und ETX ist die Syncronisation 
wohl relativ sicher. (auch ohne Escape).

Im Anhang ist mal ein längerer Trace. Die beiden Kommunikationspartner 
scheinen im Request / Respone Verfahren zu kommunizieren.
Angehängte Dateien:
Gast #4263644
Lesenswert?

Fabian H. schrieb:
> Warum vorhandene 02 / 03 des Frames nicht Escaped werden ist mir auch
> ein Rätsel, aber ist halt so...

Naja, wenn ich die Länge kenne kann ruhig ETX uns STX im Body 
vorkommen...
Ist doch logisch. Das letzte ETX kann man dann noch zur Sicherheit 
abfragen, um evtl. Bitfehler in der Länge zu erkennen.

Gruß,
Flo
Gast #4263658
Lesenswert?

Fabian H. schrieb:
> denn ich
> habe inzwischen alle Permutationen von Polynomen und Initialwerten
> durchprobiert...

Prüfe auch mal die Zwischenwerte in deinem Programm ab, ich habe schon 
einige Übertragungen gesehen, bei denen der CRC nicht über das gesamte 
Datenpaket gerechnet wurde sondern nur über einen Teilbereich.

Fabian H. schrieb:
> STM32F103

Dann hat es ja einen eingebauten CRC in HW, siehe Anhang.

Quote:"In the scope of the EN/IEC 60335-1 standard..."
Angehängte Dateien:
OP #4263735
Lesenswert?

Vielen Dank, Flo!
Irgendwo hatte sich wohl in meine CRC-Berechnung ein Fehler 
eingeschlichen. (ich denke mal, falsche Bit-Order), aber es lässt sich 
jetzt nicht mehr genau sagen... Egal.

Um diesen Thread ordentlich abzuschließen, hier die Zusammenfassung:

- Die CRC wird über den kompletten Frame ohne STX und ETX berechnet.
- Es wird das Dallas/Maxim Polynom (DOW) verwendet.
- Der folgende Code berechnet die richtige CRC:
1
    public class Crc
2
    {
3
        public static byte Calc(byte[] data)
4
        {
5
            byte crc = 0;
6
            byte inbyte;
7
            byte mix;
8

9
            for (byte i = 0; i < data.Length; i++)
10
            {
11
                inbyte = data[i];
12
                for (byte j = 0; j < 8; j++)
13
                {
14
                    mix = (byte)((crc ^ inbyte) & 0x01);
15
                    crc >>= 1;
16
                    if (mix != 0)
17
                        crc ^= 0x8C;
18
                    inbyte >>= 1;
19
                }
20
            }
21
            return crc;
22
        }
23
    }

Vielen Dank auch an alle anderen, die sich ebenfalls beteiligt haben!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren