Forum: Mikrocontroller und Digitale Elektronik 2 Bytes zusammenfügen


von Miki (Gast)


Angehängte Dateien:

Lesenswert?

hallo zusammen,

ich empfange per UART 2 Bytes und will die 12 Bit-Data in 16 Bit 
variable speichern.

z.B 3000=0xBB8.

uint8_t Data_Rx[2];
uint16_t Druck;

Druck= (((Data_Rx[0] & 0xFFF)<<4)&& (Data_Rx[1] & 0xFFF) ) ;


in der Variable kommt immer 1 raus statt 3000.

von Blub B. (googoo)


Lesenswert?

der Fehler ist das logische Und, &&
du brauchst das bitweise Und &

von BS (Gast)


Lesenswert?

1) ...& 0xFF, nur 8 Bit maskieren
2) << 8, um 8 Bits schieben
3) nicht && (das ist logisches Und), sondern entweder + oder auch | 
(Oder bitweise)
4) beide Teile noch auf 16 Bit casten

von BS (Gast)


Lesenswert?

Dennsi W. schrieb:
> der Fehler ist das logische Und, &&
> du brauchst das bitweise Und &

Nee, man braucht das bitweise Oder...

von C. U. (chriull)


Lesenswert?

Du solltest mit 0xFF verunden - du hast ja nur 8 Bit.
Data_rx[0] gehört um 8 bit nach links verschoben
Die beiden bytes gehören dann verodert und nicht verundet. Und wie 
vorher erwähnt mit dem bit wise operator und nicht mit dem logischen.

von BS (Gast)


Lesenswert?

...und dann noch checken, ob zuerst das Highbyte oder das Lowbyte 
übertragen wird.

von Joachim B. (jar)


Lesenswert?

Frage:
Warum setzt du "& 0xFFF"? -> Data_Rx[0] hat 8 Bit
Frage:
Warum setzt du "&&"? -> ein bool & kann nie >1 werden
Frage:
Wie heisst dein Lehrbuch?

von Miki (Gast)


Lesenswert?

Druck= (((Data_Rx[0] & 0xFF)<<8)+ (Data_Rx[1] & 0xFF) ) ;

kommt nun 47880 raus

von Blub B. (googoo)


Lesenswert?

BS schrieb:
> Nee, man braucht das bitweise Oder...

logisch ;)

von Miki (Gast)


Lesenswert?

Joachim B. schrieb:
> Warum setzt du "&&"? -> ein bool & kann nie >1 werden
> Frage: Mistake
> Wie heisst dein Lehrbuch?
Salami für Alle

von BS (Gast)


Lesenswert?

Wenn Data_Rx 8 Bit ist, kann das & 0xFF entfallen.

von BS (Gast)


Lesenswert?

Die empfangenen Daten sind aber entweder 0xBB08 oder 0x08BB.

von Dirk B. (dirkb2)


Lesenswert?

BS schrieb:
> Wenn Data_Rx 8 Bit ist, kann das & 0xFF entfallen.

Aber nur, wenn es unsigned ist.

Mit dem &0xff ist es besser.

von Stefan F. (Gast)


Lesenswert?

wert=256*highByte+lowByte;

von HildeK (Gast)


Lesenswert?

Wenn die Byteorder stimmt: union aus data[2] und wert.
Benefit: Belegt nur einmal den Speicher ...

von S. R. (svenska)


Lesenswert?

Miki schrieb:
> Druck= (((Data_Rx[0] & 0xFF)<<8)+ (Data_Rx[1] & 0xFF) ) ;
> kommt nun 47880 raus

Tausche 0 und 1.

von Rolf M. (rmagnus)


Lesenswert?

Dirk B. schrieb:
> BS schrieb:
>> Wenn Data_Rx 8 Bit ist, kann das & 0xFF entfallen.
>
> Aber nur, wenn es unsigned ist.

Ist es doch (beides):

Miki schrieb:
> uint8_t Data_Rx[2];

Für Bitgefummel sollte man übrigens sowieso immer unsigned-Typen 
verwenden.

von GEKU (Gast)


Lesenswert?

Miki schrieb:
> uint8_t Data_Rx[2];
> uint16_t Druck;
>
> Druck= (((Data_Rx[0] & 0xFFF)<<4)&& (Data_Rx[1] & 0xFFF) ) ;

& 0xFFF macht keinen Sinn,  da Data_Rx vom Typ unsigned char ist und 
nicht größer als 0xFF sein kann.

bleibt
1
        Druck= ((Data_Rx[0] <<4)&& Data_Rx[1] ) ;
Ich nehme an, dass Data_Rx [0] die HIGH Wert und Data_Rx [1] den LOW 
Wert.

Warum wird der HIGH Wert nur um 4 Stellen nach links verschoben?
Druck ist vom Typ unsigned short und besteht daher aus zwei unsigned 
char
Ein unsigned char besteht aus 8 Bit, daher muss um 8 Stellen nach links 
verschoben werden

besser
^
1
       Druck = ((Data_Rx [0]<<8) && Data_Rx [1]); // <<8 entspricht *256

Beispiel:

       Data_Rx[0] = 0x47 und Data_Rx[1] = 0x10
1
       0x47 << 8 =  0x4700  HIGH Wert  16 Bit
2
       0x11 << 0 =  0x0001  LOW Wert   16 Bit 
3
                              ======
4
                              0x4711

Das heißt der HIGH Wert  16 Bit  muss zum LOW Wert 16 Bit  addiert (+) 
und nicht logisch verundet (&&) werden.

daher  richtig
1
     Druck = (Data_Rx [0] << 8) + Data_Rx [1];

von GEKU (Gast)


Lesenswert?

GEKU schrieb:
> 0x47 << 8 =  0x4700  HIGH Wert  16 Bit
>        0x11 << 0 =  0x0001  LOW Wert   16 Bit
>                               ======
>                               0x4711

Anmerkung:

Die beiden Nullen hinter 0x47 kommen durch das Verschieben um 8 Stellen 
nach links bzw. durch die Multiplikation mit 256 zustande. Sie sind 
immer  Null.

Daher passiert beim Addieren kein Übertrag vom LOW Byte auf das HIGH 
Byte.
Das gilt auch umgekehrt für die vorderen zwei Nullen im LOW Wert.
Es könnte daher statt dem + Operator auch der | Oder Operator verwendet 
werden.

von GEKU (Gast)


Lesenswert?

GEKU schrieb:
> Es könnte daher statt dem + Operator auch der | Oder Operator verwendet
> werden.

genauer

 Es könnte daher statt dem | Oder Operator auch der +  Operator für die 
Addition verwendet werden.

von Jim M. (turboj)


Lesenswert?

Bei solchen Anfängerübungen ist es hilfreich sich einen C Compiler für 
den PC zu besorgen und das mit bekannten Daten am PC stat im μC 
auszuprobieren.

Da hat man dann auch einen Debugger...

von Stefan F. (Gast)


Lesenswert?

Jim M. schrieb:
> sich einen C Compiler fürden PC zu besorgen
> Da hat man dann auch einen Debugger...

Als kostenloses Gesamtpaket zum Beispiel https://www.qt.io/

Die IDE taugt auch für viele Mikrocontroller.

von Günter N. (turtle64)


Lesenswert?

HildeK schrieb:
> Wenn die Byteorder stimmt: union aus data[2] und wert.
> Benefit: Belegt nur einmal den Speicher ...

union ist eine sehr elegante Methode zur Typumwandlung, gerade
bei solchen Aufgaben, wo Daten byteweise übertragen werden.

Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.

Man muss natürlich schon recht genau wissen, was man da tut.
Ich habe da mal eine Überraschung erlebt, als ich 32-Bit-Integer 
byteweise von einem PSoC5LP zu einem PSoC3 übertragen habe. Einer davon 
ist Big Endian, der andere Little Endian.

Miki: Der Screenshot stammt aus PSoC Creator, oder?
Ich kenne nicht viele, die Cypress-Controller nutzen. Wenn Du Lust hast, 
schreib mir mal eine PM.

von Dirk B. (dirkb2)


Lesenswert?

Günter N. schrieb:
> union ist eine sehr elegante Methode zur Typumwandlung, gerade
> bei solchen Aufgaben, wo Daten byteweise übertragen werden.
>
> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.


Deswegen:
> Man muss natürlich schon recht genau wissen, was man da tut.
> Ich habe da mal eine Überraschung erlebt, als ich 32-Bit-Integer
> byteweise von einem PSoC5LP zu einem PSoC3 übertragen habe. Einer davon
> ist Big Endian, der andere Little Endian.

Der Compiler kann (wenn er darf) das Geschiebe und maskieren erkennen 
und optimieren.
Das ist portabel.

von HildeK (Gast)


Lesenswert?

Günter N. schrieb:
> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.
Nicht schlimm :-). Ich verstehe es auch nicht, eine negative Aussage kam 
von niemandem.
Ich hab so mal vor langer Zeit (DOS, 386er) Daten und Infos aus 
Meßgeräten ausgelesen und weiterverarbeitet.

> Man muss natürlich schon recht genau wissen, was man da tut.
Ja, deshalb mein Nebensatz: wenn die Byteorder stimmt ...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Günter N. schrieb:
> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.

Vielleicht weil Type-Punning kein robuster Code ist?  Jedenfalls ist man 
mit GCC auf der sicheren Seite:
1
To fix the code above, you can use a union instead of a cast
2
(note that this is a GCC extension which might not work with other
3
compilers)

http://gcc.gnu.org/bugs/#casting_and_optimization

von Wolfgang (Gast)


Lesenswert?

Günter N. schrieb:
> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.

Nimm's nicht so ernst. Melde dich einfach nicht an, dann hast du keine 
Probleme mit dem Bewertungssystem.

Das ist wie mit einem schwerhörigen Hund. Der lässt sich auch nicht so 
einfach durch Bellen einschüchtern.

von Rolf M. (rmagnus)


Lesenswert?

Günter N. schrieb:
> union ist eine sehr elegante Methode zur Typumwandlung, gerade
> bei solchen Aufgaben, wo Daten byteweise übertragen werden.
> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.

union ist weder besonders elegant, noch ist es dafür gedacht oder 
geeignet. Das wird vermutlich der Grund für die Bewertung sein.

Wolfgang schrieb:
> Günter N. schrieb:
>> Schade, dass der Beitrag negativ bewertet wurde. Verstehe ich nicht.
>
> Nimm's nicht so ernst. Melde dich einfach nicht an, dann hast du keine
> Probleme mit dem Bewertungssystem.

Bewertet wirst du trotzdem. Du siehst es nur nicht, und du kannst selbst 
nicht bewerten.

> Das ist wie mit einem schwerhörigen Hund. Der lässt sich auch nicht so
> einfach durch Bellen einschüchtern.

Es ist eher wie mit dem Kind, das beim Versteckspiel seine Augen zuhält, 
weil es glaubt, dass andere es dann auch nicht mehr sehen können.

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Johann L. schrieb:
> Jedenfalls ist man
> mit GCC auf der sicheren Seite:
> To fix the code above, you can use a union instead of a cast
> (note that this is a GCC extension which might not work with other
> compilers)

Offenbar war ich es auch damals mit dem MS C6.x (1990+). Also nicht nur 
GCC extension.

Wolfgang schrieb:
> Nimm's nicht so ernst.

Die Bewertung war ja bei meinem Beitrag. Es macht mir nichts aus, außer 
dass ich mir Gedanken mache, was falsches behauptet zu haben. Dann wäre 
eine entsprechende Erklärung hilfreicher.

Rolf M. schrieb:
> union ist weder besonders elegant, noch ist es dafür gedacht oder
> geeignet. Das wird vermutlich der Grund für die Bewertung sein.

Warum nicht elegant bzw. nicht geeignet? Weil ggf. nicht portabel?
Wofür dann gedacht? Nur um Speicherplatz zu sparen?
Hast du da ein paar Schlagworte dazu (auswendig; ich will dich nicht zum 
Durchsuchen von Papieren animieren :-) ...)?

von Rolf M. (rmagnus)


Lesenswert?

HildeK schrieb:
> Rolf M. schrieb:
>> union ist weder besonders elegant, noch ist es dafür gedacht oder
>> geeignet. Das wird vermutlich der Grund für die Bewertung sein.
>
> Warum nicht elegant bzw. nicht geeignet?

Ich finde es umständlich, dafür extra erst einen neuen Typ zu definieren 
und die Daten da rein und wieder rauszukopieren.

> Weil ggf. nicht portabel?

Das auch. ISO C sagt auch explizit, dass man nur das Element der union 
lesen darf, das als letztes geschrieben wurde. Es ist immer nur ein 
Element "aktiv".

> Wofür dann gedacht? Nur um Speicherplatz zu sparen?

Wenn man als Alternative eine struct sieht, von der man immer nur ein 
Element benutzt, könnte man das so sehen.
Ein beispielhafter Anwendungsfall wäre ein Event-Handling, wo den 
verschiedenen Events unterschiedliche Daten mitgegeben werden. Dann 
gibt's für jeden Eventtyp ein union-Element, wo die zu diesem Event 
gehörenden Daten drin sind. Anhand des Event-Typs weiß man dann, welches 
union-Element das aktive ist, und man kann darauf entsprechend 
zugreifen.

von Jemand (Gast)


Lesenswert?

Rolf M. schrieb:
> Das auch. ISO C sagt auch explizit, dass man nur das Element der union
> lesen darf, das als letztes geschrieben wurde. Es ist immer nur ein
> Element "aktiv".

Humbug!
1
If the member used to read the contents of a union object is not the same as the member last used to
2
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
3
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
4
punning’’). This might be a trap representation.

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> ISO C sagt auch explizit, dass man nur das Element der union
> lesen darf, das als letztes geschrieben wurde. Es ist immer nur ein
> Element "aktiv".

ISO C sagt aber auch explizit daß Type-Punning mit unions erlaubt ist.

von Rolf M. (rmagnus)


Lesenswert?

Ja, stimmt, in aktuelleren Versionen wurde das wohl geändert. Unelegant 
finde ich es trotzdem.

von HildeK (Gast)


Lesenswert?

Rolf M. schrieb:
> Ich finde es umständlich, dafür extra erst einen neuen Typ zu definieren
> und die Daten da rein und wieder rauszukopieren.

Danke für deine Erklärungen, auch für die der anderen Poster.
An rein- und rauskopieren hätte ich jetzt nicht als Erstes gedacht, ich 
würde die Elemente direkt als Variablen verwenden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

HildeK schrieb:
> Johann L. schrieb:
>> Jedenfalls ist man
>> mit GCC auf der sicheren Seite:
>> To fix the code above, you can use a union instead of a cast
>> (note that this is a GCC extension which might not work with other
>> compilers)
>
> Offenbar war ich es auch damals mit dem MS C6.x (1990+). Also nicht nur
> GCC extension.

Wenn's ein dokumentiertes Feature ist, kein Problem.  Wenn's auf dem 
Niveau von "was rauskommt, ist, was ich erwarte" ...

Bernd K. schrieb:
> Rolf M. schrieb:
>> ISO C sagt auch explizit, dass man nur das Element der union
>> lesen darf, das als letztes geschrieben wurde. Es ist immer nur ein
>> Element "aktiv".
>
> ISO C sagt aber auch explizit daß Type-Punning mit unions erlaubt ist.

Ab C99.

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Johann L. schrieb:
> Wenn's auf dem
> Niveau von "was rauskommt, ist, was ich erwarte" ...

:-)
Kann ich leider heute nicht mehr sagen ...

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
>> ISO C sagt aber auch explizit daß Type-Punning mit unions erlaubt ist.
>
> Ab C99.

Nein, da war das noch nicht so. In C99 heißt es noch:
"When a value is stored in a member of an object of union type, the 
bytes of the object representation that do not correspond to that member 
but do correspond to other members take unspecified values, but the 
value of the union object shall not thereby become a trap 
representation."

Der oben von "Jemand" zitierte Satz taucht dort nicht auf.

: Bearbeitet durch User
von HolgerT (Gast)


Lesenswert?

Miki schrieb:
> Druck= (((Data_Rx[0] & 0xFF)<<8)+ (Data_Rx[1] & 0xFF) ) ;
>
> kommt nun 47880 raus

<<4 war richtig, denn Du schreibst, Du hast nur 12-bit Daten.
1
MSB               LSB
2
DATA[0]       DATA[1]
3
1011 1011   0000 1000   
4
            ^^^^-wird verworfen

Deswegen DATA[1] nur mit 0xF ver-AND-en.

Dies:
1
Druck = (((Data_Rx[0] & 0xFF)<<4) + (Data_Rx[1] & 0xF));
sollte richtig sein.

Gruß
HolgerT

von Rolf M. (rmagnus)


Lesenswert?

HolgerT schrieb:
> <<4 war richtig, denn Du schreibst, Du hast nur 12-bit Daten.

Wenn denn in dem einen Data_RX[0] die unteren 4 Bit liegen und in [1] 
die oberen 8. Wenn wie oben angegeben 3000 rauskommen sollen, dann ist 
das wohl tatsächlich so, auch wenn das eher ungewöhnlich ist.

von Bernd K. (prof7bit)


Lesenswert?

Johann L. schrieb:
>> ISO C sagt aber auch explizit daß Type-Punning mit unions erlaubt ist.
>
> Ab C99.

Weil man feststellte daß sowieso schon alle (zurecht?) die ganze Zeit 
über so taten als sei es erlaubt. Die Fußnote wurde wohl auch nur 
nachträglich in einem späteren Korrigendum als Klarstellung eingefügt, 
als Interpretationshilfe der betreffenden Paragraphen, zur 
Verdeutlichung der eigentlichen Intention hinter den grottenhäßlich 
verklausulierten Formulierungen im Text.

Man kann die Erlaubnis oder den Ausgang der vermeintlich fragwürdigen 
Tat auch indirekt aus dem jeweiligen ABI schließen denn dort ist das 
exakte Speicherlayout von Unions festgeschrieben. Man muss sein Programm 
in dem Fall ja sowieso unweigerlich auf dieses eine ABI oder kompatible 
ABIs festnageln.

Eleganterweise (und auch um unmißverständlich zu dokumentieren daß man 
sich sehr wohl ganz genau bewußt war was man tat) sichert man solche 
endgültigen Festlegungen auf bestimmte ABI Eigenschaften (Endianness, 
Alignment, Wortgrößen, etc.) mit statischen Asserts ab, so daß kein 
Zweifel daran bestehen kann wofür der Code mal gedacht war und wofür er 
definitiv nicht gedacht war.

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Der oben von "Jemand" zitierte Satz taucht dort nicht auf.

Es gibt ein Korrigendum. Dort wurde die betreffende Fußnote nachträglich 
eingefügt die die eigentliche Intention des verklausulieren Textes 
noch mal explizit klarstellt. Denn es war auch ohne die Fußnote schon so 
gemeint, nur leider nicht menschenlesbar hingeschrieben.

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_283.htm

Und da sieht man auch daß das selbe bereits für C89 galt.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

HildeK schrieb:
> Die Bewertung war ja bei meinem Beitrag.

Wolfgangs Beitrag wurde auch abgewertet


> Es macht mir nichts aus, außer
> dass ich mir Gedanken mache, was falsches behauptet zu haben. Dann wäre
> eine entsprechende Erklärung hilfreicher.

Den Grund hast du doch gleich selber mitgeliefert.

: Bearbeitet durch User
von GEKU (Gast)


Lesenswert?

Rolf M. schrieb:
> HolgerT schrieb:
>> <<4 war richtig, denn Du schreibst, Du hast nur 12-bit Daten.
>
> Wenn denn in dem einen Data_RX[0] die unteren 4 Bit liegen und in [1]
> die oberen 8. Wenn wie oben angegeben 3000 rauskommen sollen, dann ist
> das wohl tatsächlich so, auch wenn das eher ungewöhnlich ist.

Nach links verschoben muss das höherwertige Byte.
Das niederwertige Byte nutzt alle 8 Bits.
Wenn das höherwertige Byte nur um 4 Bit nach links verschoben wird, dann 
gibt es einen Konflikt mit den 4 höherwertigen Bits des niederwertigen 
Bytes.

Beispiel:  0x47 0x11

falsch :

        0x0011 niederwertige Byte
        0x0470 höherwertige Byte    0x47<<4
        =======
        0x0481

richtig :

        0x0011 niederwertige Byte
        0x4700 höherwertige Byte    0x47<<8
        =======
        0x4711

von GEKU (Gast)


Lesenswert?

GEKU schrieb:
> Du hast nur 12-bit Daten

12 Bit Daten bedeuten normalerweise die Nichtverwendung der obersten 4 
Bits

siehe 12 Bit ADC Konverter

von GEKU (Gast)


Lesenswert?

GEKU schrieb:
> ADC Konverter

Eigentlich heißt es AD Konverter.

von Holger T. (holgert)


Lesenswert?

GEKU schrieb:
> Das niederwertige Byte nutzt alle 8 Bits.

Woher weißt Du das? Das geht aus Mikis Daten nicht hervor! Bei Ihm ist 
zu lesen:
Data[0] = 187 = 0xBB
Data[1] = 8 = 0x08

Er möchte, daß 0xBB8 als 3000 dargestellt wird. Also wird das 
High-Nibble von Data[1] verworfen. Punkt.

GEKU schrieb:
> GEKU schrieb:
>> Du hast nur 12-bit Daten
>
> 12 Bit Daten bedeuten normalerweise die Nichtverwendung der obersten 4
> Bits
>
> siehe 12 Bit ADC Konverter

Hier interessiert nicht, wie die NORMALERWEISE Bedeutung ist. Miki hat 
in seinem Eingangspost seine Daten in einem Screenshot mitgeliefert. Und 
da sind die so dargestellt, dass meine Berechnung passt.


Ich verstehe die ganze Diskussion der "Experten" um C-Standards, Unions 
und den anderen Kram nicht. Dieser Faden ist voll gekapert. Und die nur 
12-bit Breite wurde völlig ignoriert. Hoffentlich liest Miki überhaupt 
noch mit.

Gruß
Holger

von Menüsucher (Gast)


Lesenswert?

Normalerweise macht man das so:
1
uint8_t Data_Rx[2U];
2
uint16_t Druck;
3
4
Druck = ((uint16_t)Data_Rx[0U] + ((uint16_t)Data_Rx[1U] << 8U));

bzw. in C++:
1
uint8_t Data_Rx[2U];
2
uint16_t Druck;
3
4
Druck = (static_cast<uint16_t>(Data_Rx[0U]) + (static_cast<uint16_t>(Data_Rx[1U]) << 8U));


Das funktioniert garantiert immer und auf allen Architekturen mit allen 
Compilern und allen C/C++ Versionen.
Falls die Bytes vertausch sind, entsprechend 0U und 1U tauschen.

von Arduino Fan (Gast)


Lesenswert?

Miki schrieb:
> hallo zusammen,
>
> ich empfange per UART 2 Bytes und will die 12 Bit-Data in 16 Bit
> variable speichern.
>
> z.B 3000=0xBB8.
>
> uint8_t Data_Rx[2];
> uint16_t Druck;
>
> Druck= (((Data_Rx[0] & 0xFFF)<<4)&& (Data_Rx[1] & 0xFFF) ) ;
>
> in der Variable kommt immer 1 raus statt 3000.

Das müßte auch funktionieren:
1
Data_Rx[0] = 0xbb;
2
Data_Rx[1] = 8;
3
Druck = 0;
4
5
Druck = ( (uint16_t) (Data_Rx[0] << 4U) | ( (uint16_t) (Data_Rx[1]) );
6
7
Das ergibt:
8
9
Druck = 0x0bb8; oder 3000 in Dec.
Beim GCC sind die Casts notwendig.

von GEKU (Gast)


Lesenswert?

Holger T. schrieb:
> GEKU schrieb:
>> Das niederwertige Byte nutzt alle 8 Bits.
>
> Woher weißt Du das? Das geht aus Mikis Daten nicht hervor! Bei Ihm ist
> zu lesen:
> Data[0] = 187 = 0xBB
> Data[1] = 8 = 0x08

GEKU schrieb:
> Nach links verschoben muss das höherwertige Byte.
> Das niederwertige Byte nutzt alle 8 Bits.
> Wenn das höherwertige Byte nur um 4 Bit nach links verschoben wird, dann
> gibt es einen Konflikt mit den 4 höherwertigen Bits des niederwertigen
> Bytes.

Mein Post beschreibt nicht welches Byte das höherwertige ist.
Es beschreibt welche Konsequenzen ein Verschieben um nur 4 Bits hat.

von GEKU (Gast)


Lesenswert?

Arduino Fan schrieb:
> Das müßte auch funktionieren:

Ausprobiert?

von GEKU (Gast)


Lesenswert?

Arduino Fan schrieb:
> Data_Rx[0] = 0xbb;
> Data_Rx[1] = 8;
> Druck = 0;
>
> Druck = ( (uint16_t) (Data_Rx[0] << 4U) | ( (uint16_t) (Data_Rx[1]) );

Einmal kurz laut nachgedacht:

0x8 =>         0x0008    bleibt unverändert,  ist ok
0xbb =>       0x0bb0    Verschiebung um 4 Bit, man beachte ein Hexdigit 
ist 4bit groß!
ergibt =>      ======   Veroderung mit |
                     0x0bb8    und nicht 0xbb08


Warum sollt das niederwertige Byte nur 4 Bit groß sein?
Wenn das der Fall ist, dann mag die Berechnung von Arduino Fan richtig 
sein,
aber so eine Realisierung eines 12 Bit Wertes ist mir in meiner langen 
Beruflaufbahn noch nicht vorgekommen. War endlich ein mal Zeit ;)

von Bernd K. (prof7bit)


Lesenswert?

Das Rätsel um die höchst eigenwillige Kodierung könnte gelüftet werden 
wenn OP mal sagen würde woher er die Daten eigentlich bekommt 
(Typenbezeichnung oder Handbuch des sendenden Geräts oder 
Quelltextauszug desselben falls Eigenbau).

Vielleicht hat er auch nur nen Zahlendreher in seinen hingeschriebenen 
Beispieldaten fabriziert (wahrscheinlich) und die ganze 4-Bit-Aufregung 
ist somit hinfällig.

von A. S. (Gast)


Lesenswert?

GEKU schrieb:
> Warum sollt das niederwertige Byte nur 4 Bit groß sein?

Damit man um Zweifel mit einem Lesebefehl die obersten 8 signifikanten 
Bits bekommt.

Nur hätte ich dann fürs liebste 0x80 und nicht 0x08 erwartet.


PS.: Ich nutze statt Unions dann lieber pointercasts, z.b

#define BACC(v,o) ((unsigned char*)&(v))[o]

Natürlich abgesichert mit static-asserts etc. Entweder ich mach solche 
Speicherspielchen, dann direkt, oder eben nicht.

von GEKU (Gast)


Lesenswert?

Miki schrieb:
> ich empfange per UART 2 Bytes und will die 12 Bit-Data in 16 Bit
> variable speichern.

Wäre interessant welche Bytes in welcher Reihenfolge aus dem UART 
ausgelesen werden und welche Bedeutung die Information hat.

Miki schrieb:
> ich empfange per UART 2 Bytes und will die 12 Bit-Data in 16 Bit
> variable speichern.
>
> z.B 3000=0xBB8.

sagt nicht viel aus.

von GEKU (Gast)


Angehängte Dateien:

Lesenswert?

1
#include <stdio.h>
2
3
int main()
4
{
5
    // Beispiel mit UNION
6
    {
7
        union UINT_UNION // gross geschrieben der TYP von union
8
        {
9
            int a; // integer
10
            char b[sizeof(short int)]; // Array mit zwei Bytes
11
        }
12
        c; // klein geschrieben die Variable
13
14
        c.a = 0x4711;
15
16
        printf("a=%x  b0=%x b1=%x\r\n",c.a,c.b[0],c.b[1]);
17
18
        // liefert a=4711  b0=11  b1=47
19
    }
20
21
22
23
    // Beispiel Methode von A.S. :
24
25
    {
26
        unsigned int a;
27
28
        a=0x4711;
29
30
        printf("a=%x  b0=%x b1=%x\r\n",*(unsigned int*)&a, *(unsigned char*)&a, *((unsigned char*)&a+1));
31
32
        // liefert a=4711  b0=11  b1=47
33
    }
34
}

von Menüsucher (Gast)


Lesenswert?

GEKU schrieb:
> #include <stdio.h>
>
> int main()
> {
> ...
> }

Beide Methoden sind weder portabel noch besonders elegant 
(Ansichtssache)! Daher lieber so wie weiter oben von mir beschrieben. 
Die Variante fehlt übrigens in deinem Codebeispiel.

von GEKU (Gast)


Angehängte Dateien:

Lesenswert?

Menüsucher schrieb:
> Die Variante fehlt übrigens in deinem Codebeispiel.

Das ist natürlich die sauberste Methode (siehe Anhang)
Ich würde sie auch bevorzugen.

von Rolf M. (rmagnus)


Lesenswert?

GEKU schrieb:
> Menüsucher schrieb:
>> Die Variante fehlt übrigens in deinem Codebeispiel.
>
> Das ist natürlich die sauberste Methode (siehe Anhang)
> Ich würde sie auch bevorzugen.

Da stimme ich zu. Sie hat nebenbei auch noch den Vorteil, von der 
Endianness des Zielsystems unabhängig zu sein.

PS: Warum eigentlich überall dieses U?

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.