Forum: Mikrocontroller und Digitale Elektronik Wie immer Low Byte und High Byte zusammensetzen


von Sebastian (Gast)


Lesenswert?

Hallo Leute,

ich empfange Daten über die RS232 Schnittstelle. An die Nutzdaten habe 
ich eine CRC16 Checksumme drangehängt (2Bytes).

Von der Checksumme wird zuerst das Low Byte und anschließend das High 
Byte übertragen.

Ich habe eine For-Schleife. Diese For-Schleife liest das 1.Byte aus dem 
RS232-Buffer aus und soll dieses Byte im unsigned short crc16_checksum 
speichern.

Die habe ich wie folgt gelöst:
1
received_checksum = ((unsigned short) rs232_data);

Jedoch beim 2. Schleifendurchlauf lese ich das High Byte aus dem RS232 
Buffer aus. Nun kann ich ja nicht die gleiche Anweisung wie oben nehmen.

Ich könnte in der For-Schleife eine Fallunterscheidung vornehmen dies 
benötigt aber wieder zusätzlich Laufzeit.

Gibt es denn auch eine elegenate Lösung um dann das High Byte in den 
Datentype short zu schreiben?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sebastian schrieb:
> Ich könnte in der For-Schleife eine Fallunterscheidung vornehmen dies
> benötigt aber wieder zusätzlich Laufzeit.

Und? Meinst Du, das Überprüfen des Schleifenindex auf das zweite Byte 
frisst so viel Rechenzeit, daß die serielle Übertragung dadurch Probleme 
bekommt?

von Volkmar D. (volkmar)


Lesenswert?

Sebastian schrieb:
> Ich könnte in der For-Schleife eine Fallunterscheidung vornehmen dies
> benötigt aber wieder zusätzlich Laufzeit.

Ich behaupte mal das diese zusätzliche Laufzeit (insbesondere im 
Vergleich zu der Zeit die die serielle Datenübertragung benötigt) 
vernachlässigbar ist.

Wenn Du aber die folgende Zeile nur dann aufrufst, wenn auch 
Checksummen-Bytes empfangen werden, dann ist keine weitere 
Unterscheidung nötig:
1
received_checksum = (received_checksum >> 8) | (((unsigned short) rs232_data)<<8);

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Volkmar Dierkes schrieb:
1
 received_checksum = (received_checksum >> 8) | (((unsigned short) rs232_data)<<8);

Die Zeile solltest Du Dir nochmal ansehen.

von Volkmar D. (volkmar)


Lesenswert?

Kannst Du mir auf die Sprünge helfen wo ich mich vertan habe?

Es sollte so funktionieren, daß beim ersten Aufruf das empfangene 
Low-Byte zunächst als High-Byte vermerkt wird. Beim zweiten Aufruf wird 
das vorher empfangene Byte an die richtige Stelle geschoben und das 
zusätzlich empfangene Byte als High-Byte gespeichert.

Damit braucht man nur die Fall-Unterscheidung machen, ob 
Checksummenbytes empfangen werden oder nicht, sie sortieren sich dann 
selber.

Aber wenn ich da einen Denk- oder Umsetzungsfehler gemacht habe, nur her 
damit.

von Frank K. (fchk)


Lesenswert?

Volkmar Dierkes schrieb:
> Kannst Du mir auf die Sprünge helfen wo ich mich vertan habe?

Das Low-Byte ist doch schon an der richtigen Stelle. Wenn Du das nochmal 
8 Bits nach rechts schiebst, ist es im Orkus.

Es gibt noch eine elegantere Lösung:
1
typedef union
2
{
3
  unsigned short s;
4
  struct
5
  {
6
    unsigned char lo;
7
    unsigned char hi;
8
  } b;
9
} hilo16_t;
10
11
hilo16_t received_checksum;
12
13
// erster Schleifendurchlauf
14
received_checksum.b.lo=rs232_data;
15
16
// zweiter Schleifendurchlauf
17
received_checksum.b.hi=rs232_data;
18
19
// 16 Bit-Wert benutzen
20
check_crc(received_checksum.s);

Damit gibts keine Bitschiebereien, sondern die Bytes landen gleich da, 
wo sie hinsollen.

fchk

von Volkmar D. (volkmar)


Lesenswert?

Frank K. schrieb:
> Das Low-Byte ist doch schon an der richtigen Stelle. Wenn Du das nochmal
> 8 Bits nach rechts schiebst, ist es im Orkus.

Deswegen schiebe ich es ja erstmal nach links. Aber egal, es gibt viele 
Möglichkeiten wie man die Daten zusammenbauen kann.

von Oliver J. (skriptkiddy)


Lesenswert?

Frank K. schrieb:
> Es gibt noch eine elegantere Lösung:
Ist dir bewusst, dass dein Code abhängig von Bytereihenfolge (Endianess) 
des verwendeten Prozessors ist?

Gruß Oliver

von Wutheini (Gast)


Lesenswert?

Frank K. schrieb:
> Es gibt noch eine elegantere Lösung:
Und du bist dir sicher dass das ohne "#pragma pack" oder ähnlichen Kram 
überall funktioniert?

von Sebastian (Gast)


Lesenswert?

Ich habe s jetzt so gemacht:
1
 if(i == 0)
2
 {
3
    // Das Low Byte der Checksummer
4
    received_checksum = (unsigned short) rs232_data;
5
 }
6
 else
7
 {
8
    // Das High Byte der Checksummer
9
    received_checksum |= ((unsigned short) rs232_data) << 8;    
10
 }

von Simon K. (simon) Benutzerseite


Lesenswert?

Frank K. schrieb:
> Es gibt noch eine elegantere Lösung:
> ...union...

Welche aber leider die Lösung mit den meisten Fallstricken ist, wie oben 
schon dargestellt wurde.

von Sebastian (Gast)


Lesenswert?

Beim Enum benötigt man auch eine Fallunterscheidung. Zudem mehr Speicher 
für die zusätzliche Variable

von Oliver J. (skriptkiddy)


Lesenswert?

Sebastian schrieb:
> Beim Enum benötigt man auch eine Fallunterscheidung. Zudem mehr Speicher
> für die zusätzliche Variable
Inwiefern kann man das mit einem enum lösen?

Gruß Oliver

von Sebastian (Gast)


Lesenswert?

Ich meinte eine Union :-)

von H.Joachim S. (crazyhorse)


Lesenswert?

Ich nehm trotzdem union für sowas :-), ist nun mal die schnellste, 
übersichtlichste und codesparendste Variante.
Und wenn ich sowas mal auf einen anderen Prozessor portieren 
wollte/müsste, ist es auch schnell angepasst.

von Frank K. (fchk)


Lesenswert?

Wutheini schrieb:
> Frank K. schrieb:
>> Es gibt noch eine elegantere Lösung:
> Und du bist dir sicher dass das ohne "#pragma pack" oder ähnlichen Kram
> überall funktioniert?

Nö. Und die Endianess ist auch wichtig. Weiß ich auch. Wenn aber der 
Rest der Applikation ohnehin sehr hardwarenah ist, spielt die 
Portabilität keine große Rolle mehr.

Man muss halt wissen, was man macht.

http://www-users.cs.york.ac.uk/susan/joke/foot.htm

fchk

von Oliver J. (skriptkiddy)


Lesenswert?

Frank K. schrieb:
> Wenn aber der Rest der Applikation ohnehin sehr hardwarenah ist,
> spielt die Portabilität keine große Rolle mehr.
Ich hab mir zum Prinzip gemacht, alles was über uart_putc und uart_getc 
liegt, hardwareunabhängig zu proggen. Wenn man tatsächlich mal ein 
Programm auf eine andere Zielarchitektur portieren muss, ist es durchaus 
von Vorteil eine klare Trennlinie zwischen hardwareabhängigem und 
hardwareunabhängigem Teil zu haben. Je weiter unten die Trennung 
erfolgt, desto schneller ist dann portiert.

Gruß Oliver

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.