AVR Register Beschreiben

Gast #4285126
Lesenswert?

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!
#4285131
Lesenswert?

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.
#4285161
Lesenswert?

@ 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?
#4285175
Lesenswert?

PHY_CC_CCA  ->        xxxx xxxx binär
&         0xE0  ->   UND  1110 0000 binär
    ----------            ---------------
=    xxx0 0000         =  xxx0 0000 binär


11 == 0000 1011 binär:

     xxx0 0000 binär
|    0000 1011 binär
     ---------------
=    xxx0 1011 binär


Die oberen 3 Bits des Registers PHY_CC_CCA werden also unverändert 
gelassen, die unteren 5 Bits erhlaten den (Binär-)Wert von 11.

Gruß, Stefan
#4285236
Lesenswert?

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.
Gast #4285256
Lesenswert?

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?
#4285264
Lesenswert?

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
1
00000000000000000000000000000000000000000000000000001011
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)
Gast #4285291
Lesenswert?

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?
#4285296
Lesenswert?

@ 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.
#4285314
Lesenswert?

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.
Gast #4285316
Lesenswert?

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.
#4285325
Lesenswert?

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_t tmp = 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.
Gast #4285351
Lesenswert?

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=?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren