Arduino sendet und empfängt 12 bit / 16 bit werte

Hallo habe eine Frage bzgl. das empfangen von Werten die Grösser sind als 8-Bit mit dem Arduino mega2560.

So möchte über den Serialport anahnd einer GUI werte zum Arduino senden können die grösser sind als 8-bit. Da der Arduino Meha2560 mit 8-Bit arbeitet und die Serialfunktion immer nur 8bit sendet, wüsste ich jetzt nicht, wie man das machen kann. Vllt mit shiften oder maskieren?

Wäre das möglich? bzw. wäre es möglich, eine Beispiele zu bekommen, wie man das realisieren könnte?

Freue mich über jede Hilfestellung

Einen 16(12) Bit Wert in zwei 8Bit zu wandeln:
a)
WertH8 = wert16/8;
WertL8 = Wert16%8;
WertH8 = wert16/256;
WertL8 = Wert16%256;
b)
mit lowByte() bzw highByte()
siehe http://arduino.cc/en/Reference/LowByte; http://arduino.cc/en/Reference/HighByte

Zwei 8-Bit Werte zu einem 16Bit wandeln:
a)
Wert16=WertH8*256+WertL8;
b)
mit word() siehe word() - Arduino Reference
Grüße Uwe

[EDIT] Fehler ausgebessert Uwe [/EDIT]

Hallo,

Du könntest auch eine Union benutzen, im Beispiel mal mit einem 32-Bit-Wert und zwei 16-Bit-Werten:

    union speicherTeiler {
        // lang enthält den Wert als 32-Bit-Zahl
        unsigned long lang;
        struct {
            // kurz1 enthält die niederwertigen 16 Bits
            unsigned short kurz1;
            // und kurz2 enthält die höherwertigen 16 Bits
            unsigned short kurz2;
        } geteilt;
        // Die Struktur geteilt teilt sich den Speicherplatz
        // mit der unsigned long Variablen lang
    };

Das kannst Du durch die Typen der Variablen in der Union an Deine gewünschten Bit-Größen anpassen. Damit sparst Du Dir zumindest Fleißkommaoperationen - falls es schnell gehen muss.

Gruß,
Ralf

ok ich dachte, das wäre nicht möglich, da ich mit einem 8-Bit controller(Atmega2560) arbeite und dieser nicht damit umgehen könnte. Habe ich da ein verständnisproblem?

Und wenn ich einen Wert grösser 8 bit erhalte wie mache ich das?
Bzw. wenn mein eeprom eine 16 bit adresse braucht, wie sende ich die 16 bit vom arduino zum eeprom?

uwefed:
Einen 16(12) Bit Wert in zwei 8Bit zu wandeln:
a)
WertH8 = wert16/8;
WertL8 = Wert16%8;
b)
mit lowByte() bzw highByte()
siehe http://arduino.cc/en/Reference/LowByte; http://arduino.cc/en/Reference/HighByte

Zwei 8-Bit Werte zu einem 16Bit wandeln:
a)
Wert16=WertH8*256+WertL8;
b)
mit word() siehe word() - Arduino Reference
Grüße Uwe

zu a) verstehe das nicht sorry, was das mit dem % und / auf soch hat. könntest du es mi bitte erklären?

Natürlich geht das. Viele 8 Bit Prozessoren haben mehrere 16 Bit Register (bzw. zwei 8 Bit Register die zusammen angesprochen werden können) für native 16 Bit Arithmetik. Die Limitation liegt hier in der externen Datenübertragung. Seriell ist halt nur bis maximal 9 Datenbits standardisiert und 8 sind heute normal.

Du hast mit int einen 16 Bit Datentyp und mit long einen 32 Bit Datentyp. Daher kannst daher einfach aus einzelnen 8 Bit Werten größere Zahlen basteln.

milito:

uwefed:
Einen 16(12) Bit Wert in zwei 8Bit zu wandeln:
a)
WertH8 = wert16/8;
WertL8 = Wert16%8;

zu a) verstehe das nicht sorry, was das mit dem % und / auf soch hat. könntest du es mi bitte erklären?

Du hast recht es müßte /256 heißen.
Wenn man einen 16 Bit integer Wert durch 256 teilt verliert man die Nachkommastellen und es bleibt nur das höherwertige Byte.
Mittels %256 (modulo) bleibt der Rest der Division /256 also das niederwertigst Byte.
Grüße Uwe

Hi, ok :D. danke
EIn Frage, könnte ich es auch mit dem Shiften realisieren, sodass ich zb wenn ich 12 bit haben möchte, dass ich das highbyte um 8 nach rechts shifte diesen uerst sende und dann das lowbyte und somit die beiden in ener integer variable speichere somit hätte ich den 16bit wert?

Bzw so: Serial sendet -> Highbyte(8bit) + LowByte(8bit) ----> dieser wird vom arduino alles in einer invariable gespeichert(High+Low) und danach sende die intvariable zum meinem SPI-Device?

wäre dies auch möglich?

Ja, allerdings macht SPI eigentlich auch nur byte-Transfer.

Ja. Eine Division durch 256 ist ein Rechts-Shift um 8, da 2^8 = 256. Das ist vielleicht besser verständlich.

So:

int value = (highByte << 8) | lowByte;

byte lowByte = value & 0x00FF;
byte highByte = value >> 8;

Wobei Compiler so intelligent sind, dass sie Divisionen und Multiplikationen von selbst durch Shift + Addition/Substraktion ersetzen.

Danke für die wertvollen Tipps und euer mühe.

Werde es ausprobieren :smiley:

Ich finde die Lösung von Schachmann mit den unions besser.

Spart das Bitschubsen, ist wohl für Anfänger schwerer zu verstehen als mod,div oder schieben.
Wobei ich auch fast noch ein C/C++ Anfänger bin, aber durch dieses Beispiel von Schachmann sehe ich auch den Sinn der C unions. :astonished: