AVR Register setzen

OP #3645890
Lesenswert?

Hallo,
ich verwende einen ATmega16U4 und möchte die ADC`s benutzen.
Nun ist es so das in dem Register ADMUX Bit 0 ... 4 geändert wird und
in dem Register ADCSRB NUR Bit 5. Die anderen Bit´s müssen unberührt 
bleiben.
Um das ganze zu vereinfachen wollte ich nun ein #define machen.
aber wie kann ich die beiden Register in einer zeile zusammenfassen??

#define ADMUX &= 0b00010000 | ADCSRB &= 0b00100000

Vielen Dank für alles hilfreiche
#3645906
Lesenswert?

@ Mathias Feld (savag)

>Nun ist es so das in dem Register ADMUX Bit 0 ... 4 geändert wird und
>in dem Register ADCSRB NUR Bit 5. Die anderen Bit´s müssen unberührt
>bleiben.

Wie dui schon richtg erkannt hast, braucht man dazu Bitmanipulation.

>Um das ganze zu vereinfachen wollte ich nun ein #define machen.
>aber wie kann ich die beiden Register in einer zeile zusammenfassen??

Wozu sollte das gut sein? Schreib lieber eine normale Funtkion.
#3645997
Lesenswert?

Eine Funktionjn zu schreiben ist sicherlich die bessere Wahl.

Allerdings muss man als C-Programmierer auch mit Makros umgehen können.
Dabei lässt man sich immer vom Gedanken leiten: Makros sind einfach nur 
eine Textersetzung. Makros sind einfach nur eine Textersetzung. Makros 
sind einfach nur eine Textersetzung.

Nicht mehr.

Das bedeutet bei der Entwicklung eines Makros:
Die erste Frage lautet nicht: wie muss ich das schreiben?
Sondern die erste Frage lautet: was muss eigentlich nach der 
Textersetzung rauskommen?

in deinem Fall.
Im Endeffekt muss nach der Textersetzung rauskommen
1
int main()
2
{
3
...
4
   ADMUX &= 0b00010000;
5
   ADCSRB &= 0b00100000;
6
...

soweit so gut. C erfodert von dir nicht, dass du jede Anweisung in eine 
neue Zeile schreibst. d.h. du darfst das auch so schreiben.
1
int main()
2
{
3
...
4
   ADMUX &= 0b00010000;  ADCSRB &= 0b00100000;
5
...

Nachdem jetzt klar ist, wie eigentlich das Ergebnis aussehen soll, 
überlegt man sich, weche Textersetzung man haben möchte, so dass der 
Zieltext sich einfacher präsentiert.
Anstatt dem ganzen Wust, möchtest du gerne schreiben
1
int main()
2
{
3
...
4
   SET_ADC;
5
...

jetzt ist es aber leicht zu sehen, welcher Text durch welchen anderen 
Text ersetzt werden soll. Wenn in der letzten Version der Text "SET_ADC" 
durch den Text "ADMUX &= 0b00010000;  ADCSRB &= 0b00100000" ersetzt 
wird, dann entsteht nach der Textersetzung genau das richtige.

Daher
1
#define SET_ADC  ADMUX &= 0b00010000;  ADCSRB &= 0b00100000
2

3
int main()
4
{
5
...
6
  SET_ADC;
7
...

erzeugt genau das, was du willst.

Laut den Regeln darf allerdings ein Makro auch über mehr als 1 Zeile 
gehen. Alles was dazu nötig ist, ist das man in die letzte Spalte einer 
Zeile einen '\' reinschreibt.
1
#define SET_ADC  ADMUX &= 0b00010000;   \
2
                 ADCSRB &= 0b00100000
3

4
int main()
5
{
6
...
7
  SET_ADC;
8
...

Am Prinzip der Textersetzung ändert sich dadurch nichts. Immer noch 
sorgt das Makro dafür, dass im eigentlichen Code der Text "SET_ADC" 
durch einen anderen Text ersetzt wird. Und nach wie vor ist das Ergebnis 
dieser Textersetzung genau das gewünschte.


PS: die Schreibweise 0b00010000 ist an dieser Stelle Müll. Anstatt sich 
da Gedanken darüber zu machen, wie man einen 2-Zeiler durch etwas 
kürzeres ersetzen kann, solltest du dir lieber Gedanken machen, wie du 
diese Binärkonstante besser schreiben kannst. Nicht umsonst hat dir 
Atmel in den Header Files die ganzen Bitnamen vordefiniert. Benutze sie!
OP #3646334
Lesenswert?

SUUUPER Antwort,
das war genau das was ich gesucht habe. Habe schon gesehen das Atmel das 
vordefiniert. Jedoch ist es im Datenblatt als Binär angegeben. Wollte es 
auch so gleich übernehmen das ich später auch auf einen Blick die 
Zuordnung im Datenblatt habe.

Habe mittlerweile eine Funktion gebaut, aber dies wird mir mit 
sicherheit nochmal über den Weg laufen und ich finde diese Methode auch 
nicht schlecht.

Nochmals vielen Dank für die tolle beschreibung.
#3646378
Lesenswert?

Mathias Feld schrieb:
> SUUUPER Antwort,
> das war genau das was ich gesucht habe. Habe schon gesehen das Atmel das
> vordefiniert. Jedoch ist es im Datenblatt als Binär angegeben.

Im Datenblatt hat jedes Bit einen Namen. Und genau dieselben Namen hast 
du durch die Header zur Verfügung.

Anstatt
1
  ADCSRB &= 0b00100000;
kannst du daher genausogut auch
1
  ADCSRB &= ( 1 << MUX5 );

(was zwar immer noch falsch ist, aber zumindest lesbar falsch. Richtig 
wäre
1
  ADCSRB &= ~( 1 << MUX5 );
um das Bit MUX5 im ADCSRB zu löschen.
)

Der UNterschied zwischen beiden Schreibweisen besteht darin, dass du in 
der zweiten Version direkt im Code stehen hast, dass du hier irgendwas 
mit dem MUX5 Bit anstellen willst, während du in der ersten Version erst 
mal das Datenblatt konsultieren musst um rauszufinden, dass dieses 
einsame 1 Bit an der Bitposition MUX5 steht.

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