Hallo! Stellt euch bitte folgende Situation vor: In einem IC gibt es ein 16-bit breites Konfigurationsregister, dass ich über SPI auslesen möchte. Ich definiere mir also eine Integer-Variable, in der ich diese Info abspeichern kann. Da ich über den SPI-Bus aber nur 8 bit auf einmal empfangen kann, muss ich das Auslesen dieses Registers auf 2 Anläufe staffeln. Im ersten Anlauf lese ich z.B. das High-Byte und im zweiten das Low-Byte. Die Frage lautet nun, wie ich die zwei gelesenen Bytes in meine ursprünglich dafür vorgesehene Variable bekomme. Ich habe vor kurzem ein Beispielprogramm gesehen, in dem folgendes Konstrukt dafür verwendet wurde (auszugsweise): int config_reg; // Aufruf der Funktion, um das Konfigurationsregister auszulesen: get_config_reg( (unsigned char*) &config_reg); // Inhalt der Funktion: void get_config_reg( (unsigned char*) &config_reg) { spi_byte_1 = read_spi(); // Lies erstes Byte vom SPI-Bus config_reg[1] = spi_byte_1; spi_byte_2 = read_spi(); // Lies zweites Byte vom SPI-Bus config_reg[0] = spi_byte_2; } Mich würde jetzt interessieren, ob sowas einer "sauberen" C-Programmierung entspricht? Mir ist schon klar, wie es funktioniert und das es korrekt ist; ich habe so etwas in der Art aber zum ersten Mal gesehen. Ich hätte es nämlich so gemacht: int config_reg; // Aufruf der Funktion, um das Konfigurationsregister auszulesen: config_reg = get_config_reg(); // Inhalt der Funktion: int get_config_reg() { int ergebnis; ergebnis = read_spi(); // Lies erstes Byte vom SPI-Bus ergebnis = ergebnis >> 8; ergebnis |= read_spi(); // Lies zweites Byte vom SPI-Bus return ergebnis; } Beide Konstrukte liefern ja dasselbe Ergebnis. Wie gesagt, würde mich aber interessieren, ob so etwas "sauber" und gebräuchlich ist. Vielen Dank schonmal für euere Beiträge! Gruß Thomas
Ich halte die erste Variante für besser, da hier der Zugriff direkt erfolgen kann, und keine Schiebe-Operationen erforderlich sind... Ralf
Die 1. Variante ist gefährlich, da sie einen Compiler bzw. Target mit einer bestimmten Byteorder voraussetzt. Die Schiebvariante ist sauber, da sie völlig unabhängig vom verwendeten Compiler und verwendeten Target immer funktioniert. Peter
Mir gefällt die zweite Variante ehrlich gesagt auch besser, auch wenn sie vielleicht nicht ganz so ellegant ist, wie Variante 1. @Peter: Was meinst du mit "einer bestimmten Byteorder" (little endian oder big endian)? Gruß Thomas
. Das hier geht in die Hose: // Inhalt der Funktion: int get_config_reg() { int ergebnis; ergebnis = read_spi(); // Lies erstes Byte vom SPI-Bus ergebnis = ergebnis >> 8; ergebnis |= read_spi(); // Lies zweites Byte vom SPI-Bus return ergebnis; } Man beachte die Richtung des Schiebeoperators! Obendrein ist die Funktion des Schiebeoperators bei vorzeichenbehafteten Werten ... seltsam. Mehr Funktionalität dürfte das hier bringen: unsigned int get_config_reg() { unsigned int ergebnis; ergebnis = read_spi(); // 1. Byte ist LSB ergebnis |= read_spi() << 8; // 2. Byte ist MSB return ergebnis; } oder, wenn die Bytes "andersrum" abgespeichert werden sollen: unsigned int get_config_reg() { unsigned int ergebnis; ergebnis = read_spi() << 8; // 1. Byte ist MSB ergebnis |= read_spi(); // 2. Byte ist LSB return ergebnis; }
Die erste Variante ist ganz pfui, zu der Byteorder kommt noch die Unsicherheit, ob der Compiler int mit 16 oder 32 Bit annimmt. Bei big-endian und 32Bit kommt da ziemlich überraschendes bei raus und du findest deine Konfigurationsbits niemals wieder... Bei der Schiebevariante kannst du immer sicher sagen, wo jedes Bit aus deinem Konfigurationsregister landet. Und von wegen Eleganz: int get_config_reg() { union { unsigned char b[ sizeof(int) ]; int i; } tmp; tmp.b[0] = read_spi(); // Lies erstes Byte vom SPI-Bus tmp.b[1] = read_spi(); // Lies zweites Byte vom SPI-Bus return tmp.i; } Kann man auch machen, kommt aber u.U. der gleiche Murx bei raus. Gruss, Baku
Hallo. Muss es nicht ergebnis = ergebnis << 8 heissen? Gruß Marco
Ja okay, die Schieberichtung war falsch herum und auch die Integer-Definition habe ich bei mir im konkreten Programm auf unsigned int. Auf jeden Fall lag ich mit meiner Meinung richtig, dass Variante 1 ziemlich unsicher ist und ich davon im Bereich Mikrocontrollerprogrammierung wohl besser die Finger lassen werde. Danke für eure Meinungen. Gruß Thomas
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.