Es gibt verschiedene Möglichkeiten, die auch ein Stück weit davon abhängen, wie komplex das Protokoll werden soll. Ich will dir Mal zwei Möglichkeiten aufzeigen:
Option 1: Zustandsautomat
Auf Empfängerseite definierst du für jedes Byte einen Zustand, zum Beispiel B1_Lesen, B2_Lesen, B3_Lesen. Wenn du ein Byte empfängst, wechselst du über eine Fallunterscheidung (switch/case) in den aktuellen Zustand und verarbeitest dort das Empfange Byte. Danach wechselst du in den nächsten Zustand (Zustandsvariable inkrementieren) und wenn die Routine dann das nächste Mal aufgerufen wird, wechselt die Fallunterscheidung so in den nächsten Zustand. B3_Lesen muss nach Abschluss der Auswertung dann aber nicht in B3_Lesen+1 sondern in Zustand B1_Lesen überleiten.
Option 2: Puffer/struct/union
Wenn du ein ausreichend strukturiertes Protokoll hast (wovon ich fast ausgehe), kannst du die Daten auch erst einmal in einen Puffer (Byte-Array) einlesen und solange den Inhaltszähler inkrementieren bis du drei Bytes empfangen hast. Für deinen Frame hast du dir ein passendes struct definiert, mit dem du bequem auf die Inhalte zugreifen kannst. Jetzt kannst du den Puffer entweder über einen cast in einen Zeiger auf den struct-Datentyp verwandeln, oder du hast dir einen union-Datentyp definiert in dem sowohl ein Byte-Array als auch der struct liegen, und kommst so komplett ohne casts aus.
Dazu ein Codebeispiel:
Code:
typedef struct {
uint8_t a;
int8_t b;
uint16_t c;
} frame_t;
typedef union {
frame_t frame;
uint8_t buffer[sizeof(frame_t)];
} frame_union_t;
void someFunction() {
frame_union_t buf;
// irgendwie mit Daten befüllen, hier nicht sehr sinnvoll ...
buf.buffer[0] = 0xaa;
buf.buffer[1] = 0xbb;
buf.buffer[2] = 0xcc;
buf.buffer[3] = 0xdd;
foo = buf.frame.c; // was das wohl gibt?!
}
mfG,
Markus
Lesezeichen