Hallo,
habe da ein Schiebeoperator Problem und komme nicht auf die Lösung.
Ich möchte das in der uiTemp00 Variable Bufferstelle [3] u. [4] und
[high nibble von 5] und in der
uiTemp11 [lo nibble von 5] und [6] u. [7] steht.
Also zusammengefasst so: uiTemp00 = 0x01117
uiTemp11 = 0x186A0
>Komme mit den Schiebeoperatoren nicht klar bitte um hilfe.
Nicht nur damit nicht.
uiTemp11 |= (uint32_t) ((RxBuffer[4] << 8) & 0x00FF);
Um 8Bit nach links schieben und dann schön mit dem UND 0x00FF
gleich plattmachen auf 0.
holger schrieb:>>Komme mit den Schiebeoperatoren nicht klar bitte um hilfe.>> Nicht nur damit nicht.>> uiTemp11 |= (uint32_t) ((RxBuffer[4] << 8) & 0x00FF);>> Um 8Bit nach links schieben und dann schön mit dem UND 0x00FF> gleich plattmachen auf 0.
habe es jetzt so abgeändert.
aber passt immer noch nicht die nibbles sind nicht an der richtigen
stelle bzw. nicht da.
Was mache ich noch falsch?
uiTemp00 = 0x086A0
uiTemp11 = 0x01107
Rechne doch einfach mal per Hand nach!
Uwe schrieb:> uiTemp00 |= (uint64_t) ((RxBuffer[5] << 10) & 0x0000F);
RxBuffer[5] ist 0x71
Das ganze dann um 10 Bit nach links, was kommt raus?
Und dann das Ergebnis mit 0x0000F verundet, was kommt dann raus?
Und mit dem Rest kanns Du das dann auch allein.
Btw. das 'uint64_t' da oben ist Schwachfug, 32 Bit sind völlig
ausreichend.
Uwe schrieb:> uiTemp00 = (uint32_t)(RxBuffer[7] & 0xFF);> uiTemp00 |= (uint32_t) ((RxBuffer[6] << 8) & 0xFF00);> uiTemp00 |= (uint64_t) ((RxBuffer[5] << 10) & 0x0000F);
wieso << 10?? Hast Du nicht von Nibbles gesprochen?
und wieso dann &0xf? fehlen da nicht 4 Nullen hinter
>> uiTemp11 = (uint32_t) ((RxBuffer[5] >> 4) & 0x000F);> uiTemp11 |= (uint32_t) ((RxBuffer[4] << 8) & 0xFFFF);> uiTemp11 |= (uint32_t) ((RxBuffer[3] << 8) & 0x00FF)
Auch hier scheinen mir die Anzahl an Schiebungen und die zugehörige
Maske gewürfelt. ICh würde erwarten, dass nur maximal 2 Fs auftauchen
und dass sie irgendwie dem geschobenen Wert entsprechen.
Tatsächlich sind die Maskierungen völlig unnötig. Denn mit den
Schiebeoperationen fügst Du lediglich Nullen (links oder rechts) hinzu.
Lies das am besten nochmal in einem C-Buch nach (oder im Standard).
Wichtig ist hier das Kapitel "Integral-promotion" oder
"Integer-Erweiterung". Es hängt auch von Deiner Maschine ab, was genau
Du machen musst. Aber grundsätzlich wird der linke Operand ein (unsigned
int) werden, was nicht grundsätzlich die selbe Länge wie ein uint32_t
hat.
Auch das solltest Du nochmal nachlesen.
Hi
Wieso eigentlich überall das &0xF ??
Wir brauchen doch nur die Bytes verschieben und mit der Ziel-Variabel
ver-ODER-n.
uint8 wird wohl nur 8 bit breit sein, oder?
Wenn ich da was schiebe, bleiben es doch nur 8 bit - also ruck zuck Null
In Assembler würde ich die Bytes nacheinander bitweise in die
Ziel-Variabel reinschieben.
uiTemp00 <-- 8xBuffer[3], 8xBuffer[4], 4xBuffer[5]
uitemp11 <-- 4xBuffer[5], 8xBuffer[6], 8xBuffer[7]
Und fertig.
Buffer[x] muß nur 8 bit breit sein, uitempxx sollte je 20 bit aufweisen.
(LSL und ROL wären meine Befehle)
MfG
hab es jetzt so aber eine Stelle passt immer noch nicht.. hilfe.hilfe
Sollte ich es noch dazu besser casten ??
das steht jetzt drinne
uiTemp00 = 0x1117
uiTemp11 = 0x186A (soll aber 0x186A0)
Uwe schrieb:> hab es jetzt so aber eine Stelle passt immer noch nicht.. hilfe.hilfe
Es scheint mir, dass Du sehr verwirrt und vor allem sehr aufgeregt bist.
Das wichtigste ist, dass Du ruhig wirst. Damit ist das Hauptproblem
schon mal gelöst. Wenn nötig, lege das Problem beiseite und gehe
schlafen. Es ist ohnehin schon spät.
Dann, im zweiten Schritt, liest Du die Stellen im C-Buch, die ich Dir
genannt habe, gründlich durch und denkst darüber nach.
> Sollte ich es noch dazu besser casten ??
Das ist soweit richtig. Aber wichtig ist auch, dass Du verstehst, warum
Du das tun sollst. Das lernst Du durch die Lektüre. Und dann verstehst
Du auch, in welchen Typ Du casten must.
Nur Mut. Das schaffst Du schon. Nur vor allem: Ruhe bewahren.
Systematisch vorgehen.
habe es jetzt so gemacht. Aber scheinbar sind die verundungen doch
notwenig weil sonst noch müll drinne steht das die Variable uint32_t
breit ist ...
Hat jemand noch eine Idee?
Uwe schrieb:> habe es jetzt so gemacht. Aber scheinbar sind die verundungen doch> notwenig weil sonst noch müll drinne steht das die Variable uint32_t> breit ist ...>> Hat jemand noch eine Idee?
Schon. Aber ich bin jemand der in gewissen Fällen nicht einfach die
Antwort gibt. In der Regel wollen wir hier helfen, Dir selbst zu helfen
und das bedeutet, dass Du selbst etwas leisten musst.
An sich hast Du die Grundidee schon erfasst, aber Du wendest sie noch
falsch an.
Es ist vor allem nötig, dass Du Dir einmal klarmachst, was genau
geschieht. Wie die Ausdrücke, die Du verwendest, vom Compiler
interpretiert werden.
Schaue Dir einmal folgendes an:
1
ulTemp0=(uint16_t)(ucRxBuffer[5]>>4);
Zerlege das mal in die einzelnen Schritte:
Zunächst hast Du den Ausdruck:
1
ucRxBuffer[5]
Was ist das?
Nun, Du hast ucRxBuffer als Vektor von uint8_t deklariert. D.h. jedes
Element besteht aus einem uint8_t. Einer vorzeichenlosen Zahl aus 8 Bit,
die daher Werte von 0 bis 255 (dezimal) bzw. 0 bis 0xFF (hexadezimal)
annehmen kann.
An der Position, dem Index 5 steht, wegen Deiner Intialisierung
der Wert 0x71 (hexadezimal).
Nun steht da, wenn man die Datentypen in der Form eines Casts
ausdrücklich hinschreibt im ersten Schritt:
1
((uint8_t)0x71)
Gut. Weiter. Betrachten wir den Ausdruck, in dem dieser Inhalt des
Buffers Verwendung findet und setzen den Inhalt gleich ein:
1
(((uint8_t)0x71)>>4)
Da schau ich gleich mal nach, weil ich das eben schon geübt habe. Was
hat denn die "4" für einen Datentyp? Dafür gibt es ja keine Deklaration
aus der ich das ablesen kann.
Das ergibt sich aus der Sprachbeschreibung von C. Das steht im
C99-Standard, den Du hier:
www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf nachlesen kannst, im
Abschnitt 6.4.4.1 im Paragraph "Semantics". Alternativ kannst Du Dir
auch mal den Kernighan/Ritchie, 2. Auflage, Abschnitt A.2.5.1
durchlesen. Das gibt es auf Deutsch. Allerdings ist es veraltet und es
gibt Abweichungen zu C99 (die bei dem Thema aber, soweit ich weiß, nicht
wesentlich sind).
Danach hat eine aus dezimalen Ziffern zusammengesetzte den Typ der in
der Reihenfolge int, long int und unsigned long int noch hineinpasst. In
unserem Fall wäre das int, da die 4 gerade dort hineinpasst.
OK. Nochmal das selbe Spiel. Schreiben wir die Typen ausdrücklich als
Cast hin:
1
(((uint8_t)0x71)>>(int)4)
Nun kommt endlich das eigentliche Problem, dass Dir Schwierigkeiten
bereitet.
Für jeden Operator in C ist festgelegt ob er einen bestimmten Typ als
Operanden erwartet und falls ja, welcher das ist.
Für die Schiebeoperationen ist das der Typ int. Das steht im Standard
unter Abschnitt 6.5.7. Im K&R unter A.7.8
Nun ist aber nur einer der Typen in dem Ausdruck int. Der andere ist
uint8_t! Was nun?
Auch dazu steht im Standard und im Buch etwas: Nämlich, dass die
Operanden der in einem anderen Beitrag von mir in diesem Thread schon
erwähnten Integer-Erweiterung unterzogen werden. Das steht im Standard
unter 6.3 Conversions, im K&R unter A.6.1 bzw. online in
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/007_c_typumwandlung_001.htm#mj5c5e497ac2ab4367fe9df0ffd218cfca
unter Abschnit 7.1.
Kurz gesagt, wird die 0x71, die verschoben werden soll in ein int
umgewandelt.
Nun ist aber int nicht gleich int. Das hängt von der Maschine und dem
Compiler ab. Im allgemeinen gilt zwar, dass häufig ein int 16 Bit breit
ist, aber das sollte man nicht voraussetzen. Wie das konkret ist, steht
in der Dokumentation Deines Compilers. Aber Achtung. Wenn der Compiler,
wie der GCC für mehrere Prozessoren existiert, musst Du zunächst den
Abschnitt suchen, der für Deine CPU zutrifft.
So. Ich denke das sollte genug Anleitung sein, wie Du Dir das Thema
selbst näherbringen kannst.
Die nächste Frage ist dann: Falls die 0x71 in ein 16 Bit int umgewandelt
wird, wie sieht diese Zahl dann aus, wenn sie etwa um 12 Bit nach links
verschoben wird?
Viel Erfolg.
Hallo,
danke für die Anleitung. Habe soweit alles gelesen und es entsprechend
abgeändert, aber die letzte Operation will einfach nicht funktionieren
und ich weiß nicht weiter....
Könnte bitte Jemand mal drüber schauen?
ulTemp0 = 0x186A0
ulTemp1 = 0x0C350 hier müsste aber 0x0C35F stehen
Uwe schrieb:> Ralf G. schrieb:>> Wenn du eine 8Bit breite Zahl um 8Bit nach rechts schiebst...>> Danke! So geht es jetzt:
Prima! Gut gemacht.
Vielleicht versuchst Du aber doch noch, die Maskierung einmal
wegzulassen. Das wäre eine Gelegenheit etwas interessantes
festzustellen.
Nimm den Ausdruck:
[c]
( (uint32_t) cRxBuffer[3] << 12) & 0xFF000;
[c]
An der Stelle 3 steht die Zahl 0x0C. Eingesetzt in den Ausdruck ergibt
das:
[c]
( (uint32_t) 0x0C << 12) & 0xFF000;
[c]
Während das Programm ausgeführt wird, wird zunächst das Cast wirksam:
Aus 0x0C wird 0x0000000C. Das ist die 32 Bit-Zahl 0xC, nur mit vielen
Nullen um die Anzahl der Bits deutlich zu machen.
Nun wird diese Zahl um 12 Bit nach links verschoben. Das ergibt
0x0000C000.
Also wird der Ausdruck:
[c]
( 0x000C000 & 0xFF000;
[c]
Um deutlich zu machen, was bei dem nun abschliessenden maskieren
geschieht, schreibe ich die beiden Wert untereinander.
0x0000C000
0x000FF000
Die Bitweise Und-Verknüpfung ergibt:
0x0000C000
Diese Und-Verknüpfung ändert also nichts an dem ursprünglichen Wert.
Der Punkt ist, dass die Schiebeoperation definitiv keine zusätzlichen
Bits setzt; die Anzahl der gesetzten Bits bleibt gleich. Deswegen wird
keine zusätzliche Maskierung benötigt.