Natürlich kannst Du einen Macro machen. Ich würde es mir aber nochmal
überlegen. Für Dich, der jetzt im Programm „drin” ist, ist ein Macro
keine Hürde und macht das Programm lesbarer. Für Dich in zwei Jahren
oder einen anderen Leser ist das eine Indirektion mehr, die zunächst
gelernt sein will, um sie als menschlicher Macro-Expander bereit zu
halten. Man muss erst mal nachsehen, was der Macro bedeutet, um das
Programm zu verstehen.
Und schließlich halte ich
1
PORTC|=(1<<0);
für eine sehr klare Formulierung, die ohne Überlegung jedem, der bloß ab
und zu mit solchen Programmen zu tun hat, sofort und ohne weitere Umwege
verständlich ist. Es ist etwa so, wie wenn ein Englischanfänger in
englischen Text die Übersetzungen reinschreibt: für den, der nur ein
wenig damit vertraut ist, stört es später höchstens den Lesefluss.
Und natürlich wäre
Hc Zimmerer schrieb:
> Und schließlich halte ichPORTC |= (1 << 0);> für eine sehr klare Formulierung, die ohne Überlegung jedem, der bloß ab> und zu mit solchen Programmen zu tun hat, sofort und ohne weitere Umwege> verständlich ist.
Naja, klar sit damit nur, dass man den Pin anschaltet, mehr nicht.
Normalerweise schaltet man den ja aber nicht um seiner selbst willen,
sondern um irgend was zu bewirken.
Es ist somit viel besser, das Resultat zu benennen, als den Weg.
also, statt PinC0_ein, lieber Power_LED_ein(), oder latchData()
Das macht es zum einen einfacher, wenn man die Anschlüsse tauscht, oder
gar das modul, was an dem Ausgangsport höngt.
>Und schließlich halte ich>PORTC |= (1 << 0);>für eine sehr klare Formulierung,
Wenn man den Pin dann später mal wechseln möchte
und das da oben an mehreren Stellen im Code steht,
wird es aber ne Menge Arbeit alle Codezeilen zu
ändern. Wenn ein #define in einer Headerdatei
verwendet wird muss man nur ein Zeile ändern.
Hc Zimmerer schrieb:
> Und schließlich halte ichPORTC |= (1 << 0);> für eine sehr klare Formulierung,
Für mich ist sowas total unleserlich.
Mich interessiert nicht, welchen Pin ich schubse, sondern wozu das nütze
ist.
Also schreibe ich lieber:
1
LED1=LED_ON;
2
MOTOR1_LEFT=MOTOR_STOP;
3
// usw.
Und das geht eben sehr einfach mit dem SBIT Macro.
Außerdem muß man dann für jeden Pin auch nur einen Namen definieren.
Beim OR/AND muß man immer 2 Namen definieren, die Portadresse und die
Pinnummer.
Leider habe ich noch keinen Weg gefunden, wie man automatisch den DDR-
und PIN-Pin mit definieren kann. Ein #define innerhalb des #define geht
nicht.
Peter
> für eine sehr klare Formulierung
Dazu kann ich als PIC-User sagen, dass mir diese schreibweise zunächst
mal alles andere als "klar vormuliert" vorkam. Da muss man erstmal
überlegen, welches Bit da jetzt wie wohin geschoben, invertiert und
ge-AND-et wird...
Da finde ich die PIC-C-18 Schreibweise deutlich schöner:
PORTBbits.RB1 = 1;
z.B.
>> Für was brauch ich denn da die do-while schleife drumrum? Das will mir> nicht so ganz einleuchten.>> Macht nicht>
1
>#definepinc0_an(PORTC|=(1<<0))
2
>
> genau das gleiche?>> Gruss,> Gast
Hallo,
stimmt. Hatte ganz am Anfang schon jemand geschrieben. Als ich es
ausprobiert hatte, habe ich allerdings eine Fehlermeldung bekommen. Muss
allerdings ein Tippfehler gewesen sein. Habs jetzt nochmals ausprobiert
und es funktioniert.
Peter Dannegger schrieb:
> Leider habe ich noch keinen Weg gefunden, wie man automatisch den DDR-> und PIN-Pin mit definieren kann. Ein #define innerhalb des #define geht> nicht.
#define DDR(x) (*(&x - 1)) /* address of data direction register of
port x */
#define PIN(x) (*(&x - 2)) /* address of input register of port x
*/
und dann z.B. DDR(PORTB) oder PIN(PORTA)
Das beruht darauf, dass die Register an fortlaufenden Adressen liegen.
Das habe ich in Peter Fleurys LCD-Lib gefunden. Ist aber nicht gerade
eine saubere Methode. Denn diese Anordnung der Register ist ja nirgendwo
garantiert. Beim Mega128/Mega64 ist das PINF-Register etwa getrennt von
PORTF und DDRF abgelegt. Das fängt er an dieser Stelle dann mit
#if defined(_AVR_ATmega64_) || defined(_AVR_ATmega128_)
/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
#define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )
#else
#define PIN(x) (*(&x - 2)) /* address of input register of port x
*/
#endif
ab. Das ist also extrem kritisch, wenn neue AVRs herauskommen, die
ebenfalls so eine abweichende Anordnung haben.
Gast0 schrieb:
> Macht nicht#define pinc0_an (PORTC |= (1<<0))> genau das gleiche?
in dem Fall ist es egal.
Spätestens, wenn es mehrere Anweisungen werden, ist essenziell.
#define SR_latch() {PORTC |= (1<<0); PORTC &= ~(1<<0);}
sieht auf den ersten Blick richtig aus.
Baut man das dann aber in ein if-else-konstrukt ein:
if(x>y)
SR_latch();
else
++x;
geht es nicht:
da dann steht:
if(x>y)
{PORTC |= (1<<0); PORTC &= ~(1<<0);};
else
++x;
das semikolon schließt die if-Anweisung unwiederuflich.
Daraus lernt man 2 sachen:
1. Macros, die Anweisungen kapseln immer in do{}while(0)
2. Macros, die Anweisungen kapseln nicht benutzen, dafür gibt es
inline-Funktionen.