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
@ 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.
Hi, das mit der Funktion wäre meine nächste wahl gewesen. Dachte, vielleicht gibt es da eine möglichkeit die ich nicht kenne. Werde aber die variante mit der Funktion aufgreifen.
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!
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.
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.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.