Hallo,
ich bin im Moment dabei einen ATMEGA2564RFR2 zu programmieren. Dabei
stellt sich mir eine Frage zum Beschreiben der Register.
Es gibt z.B. Register in denen der Übertragungskanal festgelegt wird. In
der Tabelle im Datenblatt vom Controller steht dazu Kanal 11 - 26. Wie
kann ich aber nun diesen Kanal in das Register schreiben wenn das
Register aus 8 Bits besteht und Bit 4 - 0 für den Kanal belegt sind?
Im Beispiel Programm sieht das ganze so aus:
// Channel should be between 11 and 26 (2405 MHz to 2480 MHz)
if ((channel < 11) || (channel > 26)) channel = 11;
PHY_CC_CCA = (PHY_CC_CCA & 0xE0) | 11; // Set the channel to 11
Aber wie kommt man darauf?
Danke für Eure Hilfe!
PHY_CC_CCA nimmt den alten Wert des Registers.
PHY_CC_CCA & 0xE0 ergibt: alle Bits aus dem alten Register, die auch in
0xE0 enthalten sind, wobei hex 0xE0 in Binärschreibweise 1110 0000 ist.
Also ist PHY_CC_CCA & 0xE0 "alles in PHY_CC_CCA, außer den untersten 5
Bits".
Durch das ...|11 wird wiederum alles gesetzt, was im linken Operanden
enthalten ist, sowie alles, was in der 11 enthalten ist.
Damit wird also im gesamten Ausdruck (PHY_CC_CCA & 0xE0) | 11 aus dem
Register der untere Teil (5 Bit) gelöscht und durch 11 ersetzt.
Falk B. schrieb:> Siehe BitmanipulationFalk B. schrieb:> Siehe Bitmanipulation
Hast Du Dir in Deinem Browser einen Button installiert, der automatisch
obenstehenden Text posted? :)
(Da gäbe im Forum es so einige Themen, für die man Textbausteine
verwenden könnte...)
@ mse2 (Gast)
>Hast Du Dir in Deinem Browser einen Button installiert, der automatisch>obenstehenden Text posted? :)
Noch nicht, klingt aber nach einer guten Idee.
>(Da gäbe im Forum es so einige Themen, für die man Textbausteine>verwenden könnte...)
Sicher, die meisten Elementarfragen können so beantwortet werden. Warum
soll ich das kleine 1x1 immer wieder haarklein erklären, wenn es der
passende Artikel auch kann?
mse2 schrieb:> Falk B. schrieb:>> Siehe Bitmanipulation> Hast Du Dir in Deinem Browser einen Button installiert, der automatisch> obenstehenden Text posted? :)
Brauchst du gar nicht. Von einigen wichtigen Wiki Artikeln kennt man mit
der Zeit den Titel auswendig. Den schreibst du so
1
[[Bitmanipulation]]
in deine Antwort und das Forum baut den Link entsprechend ein.
Danke für eure Hilfe. Das macht Sinn :) Gibt es denn eine andere
Schreibweise wenn man nun z.b. Nur die unteren 5 Bits des Registers
Beschreiben wöllte?
@ Peter (Gast)
>Danke für eure Hilfe. Das macht Sinn :) Gibt es denn eine andere>Schreibweise wenn man nun z.b. Nur die unteren 5 Bits des Registers>Beschreiben wöllte?
Das ist eine Aufgabe fööör den Schööööler!
Peter schrieb:> Danke für eure Hilfe. Das macht Sinn :) Gibt es denn eine andere> Schreibweise wenn man nun z.b. Nur die unteren 5 Bits des Registers> Beschreiben wöllte?
Du kannst nicht nur die unteren 5 Bits beschreiben. In C kannst du nur
ein Register als ganzes beschreiben oder du lässt es. (*)
Aber es steht dir natürlich frei, das ganze so hinzudrehen, dass einige
Bits wieder genau die Werte kriegen, die sie vorher auch schon hatten,
wodurch sich effektiv an ihnen nichts geändert hat.
Mach dir keinen Kopf. Heutige Compiler sind gut. Die suchen sich den
besten Weg raus um zb ein einzelnes Bit auf 0 oder 1 zu setzen, wenn es
dafür auf einem Prozessor spezielle Instruktionen dafür gibt (wie zb
beim AVR).
(*) d.h. stimmt nicht ganz. Mit Bitfeldern kann man da was hindrehen.
Was allerdings nicht heissen soll, dass du nicht mit den Bitoperationen
in C umgehen können musst. Die sind in der µC Programmierung das, was
das kleine 1 mal 1 in der Mathematik ist.
Ok verstanden. Habe mich etwas täuschen lassen von der Umrechnung von
Hexadezimal auf Binär. Da ergab 11 - 1011. Daher dachte ich, dass ich
mit dem Befehl
PHY_CC_CCA |= 11 nur die unteren 4 Bits beschreibe aber 11 ist ja binär
00001011 und somit immer 8 Bit groß.
Richtig?
@ Peter (Gast)
>mit dem Befehl>PHY_CC_CCA |= 11 nur die unteren 4 Bits beschreibe
Effektiv schon, denn einen ODER-Verknüfung mit 0 bewirkt nichts
X oder 0 = x
> aber 11 ist ja binär 00001011 und somit immer 8 Bit groß.
Ja.
Peter schrieb:> PHY_CC_CCA |= 11 nur die unteren 4 Bits beschreibe aber 11 ist ja binär> 00001011 und somit immer 8 Bit groß.>> Richtig?
dezimal 11 kann binär auch
sein.
Führende 0-en kannst du links anhängen soviele du willst. Deswegen
ändern sich Werte nicht.
Aber die kleinste Einheit in C ist nun mal 1 Byte. Kleiner gehts in C
nicht. (bis auf den Sonderfall eines Bitfeldes, mit dem man Bytes auch
eine feinere Struktur verpassen kann, die allerdings nicht in allen
Details von der Sprache festgenagelt sind)
Also wäre die kurze Schreibweise für das Problem hier wirklich
PHY_CC_CCA |= 11,
da ich die unteren 4 Bit beschreiben muss.
Sollten die oberen beschrieben werden müsste man das ganze so schreiben
PHY_CC_CCA |= (11<<4).
Richtig verstanden?
Die Schreibweise
PHY_CC_CCA = (PHY_CC_CCA & 0xE0) | 11;
würde jetzt nur die oberen 3 Bit sichern?
@ Peter (Gast)
>PHY_CC_CCA |= 11,>da ich die unteren 4 Bit beschreiben muss.
Ja.
>Sollten die oberen beschrieben werden müsste man das ganze so schreiben>PHY_CC_CCA |= (11<<4).
Ja.
Allerdings muss man vorher sie entsprechenden Bits sicher löschen, denn
man kenn den Inhalt ja nicht genau!
>PHY_CC_CCA = (PHY_CC_CCA & 0xE0) | 11;>würde jetzt nur die oberen 3 Bit sichern?
Schau mal GENAU hin. 0xE0 = 0b0111000, d.g. die unter 4 Bit 0-3 und das
oberste Bit 7 werden gelöscht. Nur die Bits 4-6 werden nicht verändert.
Nein, denn wenn eines der unteren 5 Bits in PHY_CC_CCA gesetzt ist, dann
verfälscht dieses das Ergebnis.
Wenn PHY_CC_CCA vorher 4 ist, dann ist nach
PHY_CC_CCA |= 11,
das Ergebnis 4 | 11 == 0000 0100b | 0000 1011 = 0000 1111 = 16.
Gruß, Stefan
Peter schrieb:> Also wäre die kurze Schreibweise für das Problem hier wirklich>> PHY_CC_CCA |= 11,>> da ich die unteren 4 Bit beschreiben muss.
Nein.
Mit einer Oder-Operation kann man Bits nur von 0 auf 1 zwingen.
Aber ein einmal auf 1 gesetztes Bit kriegst du so nicht mehr auf 0.
Was ist wenn in PHY_CC_CCA in den unteren 4 Bits zum Beispiel schon ein
Wert von 15 steht? Dann sind alle 4 Bits auf 1. Die kriehst du so nicht
mehr auf 0. D.h. nach der Veroderung steht da immer noch 15 drinnen und
nicht 11.
Wenn du allerdings davon ausgehen kannst, dass die relevanten Bits
vorher schon alle 0 waren, dann kannst du das so machen.
Falk, nicht ganz E0 ist binär 11100000 oder etwa nicht?
Stefan, also müsste ich bei meinem Versuch zunächst die unteren vier Bit
löschen und dann mit meinem einfachen Befehl setzen oder ich verwende
doch die Schreibweise mit & und | und umgehe somit das löschen via
Extrabefehl.
Peter schrieb:> Falk, nicht ganz E0 ist binär 11100000 oder etwa nicht?>> Stefan, also müsste ich bei meinem Versuch zunächst die unteren vier Bit> löschen und dann mit meinem einfachen Befehl setzen oder ich verwende> doch die Schreibweise mit & und | und umgehe somit das löschen via> Extrabefehl.
Das & ist das löschen dieser Bits (d.h. das gezielte auf 0 setzen).
Ob du das in einer einzigen Anweisung schreibst
1
PHY_CC_CCA=(PHY_CC_CCA&0xE0)|11;
oder ob du das auf meherer aufteilst
1
uint8_ttmp=PHY_CC_CCA;
2
tmp&=0xE0;
3
tmp|=11;
4
PHY_CC_CCA=tmp;
schenkt sich nichts. Der Compiler wird deine 1-Anweisung sowieso in die
2.te Form auflösen.
Allerdings ist
1
PHY_CC_CCA&=0xE0;
2
PHY_CC_CCA|=11;
normalerweise nicht ganz gleichwertig. Denn PHY_CC_CCA wird
wahrscheinlich als µC-Register volatile definiert sein. D.h. der
Compiler muss beide zuweisungen machen. Im Endeffekt entsteht zwar das
richtige, aber für einen ganz kurzen Moment sind die bewussten Bits im
Register tatsächlich alle auf 0. Und in diesem 'Detail' unterscheidet es
sich dann vom Original.
Warum muss man den ziemlich guten Artikel Bitmanipulation jedem
"Depp" immer wieder vorkauen? Wie haben wir das damals (tm) nur gemacht,
als es keine Foren gab? (Also in der IT-Jungsteinzeit)
Jetzt hab ich es glaub ich
man nimmt E0 bzw. binär 11100000 und manipuliert mit einer UND Operation
weil dann die unteren 5 Bit definitiv 0 sind da eine UND Verknüpfung mit
0 immer 0 ergibt, die oberen 3 behalten aber ihren Zustand wenn sie
bereits null sind bleibt es dabei und wenn sie 1 sind auch. Dann kann
ich meinen 1011 binär einfach dazu schreiben als ODER. Somit wird aus
Nullen einen Eins und Nullen bleiben auf Null. Korrekt=?