Hallo Forenuser.
ich habe mir aus den Codebeispielen diese schönen Zeilen zum setzen und
löschen von Bits kopiert
#define setbit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
Nun möchte ich aber dieses weitertreiben, so dass ich Proceduren auch
auf anderen Ports oder anderen Prozessoren benutzen kann.
also z.B. einen gepulsten Port für IR-Kommunikation.
Wenn ich das in dieser Form mache
#define ir_transmit PORTA,PA6
gibts einen Fehler bei
setbit(ir_transmit);
mit der Begründung
macro "setbit" requires 2 arguments, but only 1 given
Die Fehlermeldung ist klar.
Versteht der Compiler nicht, dass es sich bei ir_transmit um 2
Argumente handelt?
Wie macht man es richtig?
> Versteht der Compiler nicht, dass es sich bei ir_transmit um 2> Argumente handelt?
Für den Präprozessor ist es nur 1 Argument.
> Wie macht man es richtig?
Das SETBIT ist selbst schon ein Makro. Der Präprozessor merkt sich eine
Liste von allen Defines zum späteren ersetzen. Wenn im Sourcecode die
vorgesehene Ersetzung von SETBIT vor der Ersetzung von IR_TRANSMIT
abgearbeitet wird, kommt die Fehlermeldung. Du müsstest zusehen, dass
das define von IR_TRANSMIT dem Präprozessor zuerst bekannt wird.
Tipp: Wenn man Makros grundsätzlich nur in Grossbuchstaben schreibt,
sieht man eher was im Sourcecode los ist.
"Schräg, ja, ich weiß. :-)"
Wow !
Die Typüberprüfung erfolgt also nur bei der ersten Macroexpansion und
läßt sich durch 3-fach Macros überlisten.
Ist das nun ein Bug oder ein Feature des AVR-GCC ?
Ist das auch bei anderen Compilern so ?
Peter
P.S.:
Muß ich gleich mal ausprobieren.
ich schließe mich dem wow an.
Wäre Stefans lösung auch ok? Dann bliebe nämlich die Funktion von
SETBIT für einzeln zu setzende Bits erhalten oder führt das ggf zu
anderen Problemen?
> Ist das nun ein Bug oder ein Feature des AVR-GCC ?
Kein Bug! Schau mal da:
http://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html#Macro-Arguments
Wichtig ist folgender Abschnitt:
All arguments to a macro are completely macro-expanded before they are
substituted into the macro body. After substitution, the complete text
is scanned again for macros to expand, including the arguments. This
rule may seem strange, but it is carefully designed so you need not
worry about whether any function call is actually a macro invocation.
You can run into trouble if you try to be too clever, though. See
Argument Prescan, for detailed discussion.
> Ist das auch bei anderen Compilern so ?
Das ist das im ISO-Standard so vorgesehen. Allerdings gab es in der
Vergangenheit etliche Compiler bzw. Präprozessoren (einschließlich
derjenigen von Microsoft), die diese Regel falsch umsetzten, so dass
das entweder beim Konstrukt von flyingwolf fälschlicherweise kein
Fehler oder bei dem von Jörg fälschlicherweise ein Fehler ausgegeben
wurde.
Die Variante von Jörg funktioniert auch bei Digital Mars, nicht jedoch
bei Microsoft (warning C4003: Nicht genügend übergebene Parameter für
das Makro 'setbit2').
Eine Variante, die aber bei allen korrekten Präprozessoren
funktionieren sollte, und die sich elegant auf Funktionen auf die
PINA/DDRA Register erweitert:
Bitfelder = struct?
Da habe ich letztens was interessantes gesehen. Alle Variablen waren in
einer Struktur definiert auch die 1-Bit-Vars und dann wurde die ganze
Structur ins EEProm geschrieben.
Hi,
>Also ich hab das mit den Bitfeldern ausprobiert.>Zumindest der AVR-GCC macht dann die SBI- und CBI-Befehle draus, ganz>so wie es sein soll.
@Peter
Weisst du wie es bei Keil und 8051er aussieht?
Gruß,
Dirk
Solange es um einzelne Bits geht, kann der Compiler was draus machen -
wenngleich ich auch schon abschreckende Beispiele gesehen habe (weiss
bloss nicht mehr wo).
Der Haken bei Bitfeldern liegt aber wesentlich auch darin, dass man
keine Chancen hat, es besser zu machen. Jedenfalls nicht solange man
bei den Bitfeldern bleibt und nicht nebenbei noch die klassischen
Register und Bits pflegt. Sowas wie
ControlRegister |= 1<<Enable | 1<<CrashAndBurn;
ist bei Bitfeldern nicht drin, und
ControlRegister.Enable = 1;
ControlRegister.CrashAndBurn = 1;
darf bei dem natürlich als "volatile" deklarierten ControlRegister
kein Compiler legal zusammenfassen (wenngleich SDCC sowas ähnliches
fertigbringt). Mit CBI/SBI ist das ok, u.U. sogar besser, bei nicht
bitweise adressierbaren Adressen zieht sich das jedoch arg in die
Länge.
"Weisst du wie es bei Keil und 8051er aussieht?"
Beim Keil kann man mit "sbit" einzelne Bits einer bitadressierbaren
Variable definieren. Näheres im Keil Handbuch oder auf deren Webseite
(Knowledegbase).
Peter