Hallo.
Stehe gerade auf dem Schlauch;
Beim Kompilieren wird folgender Fehler angezeigt
'port' und 'mask' undeclared
in der Zeile
#define SET_BIT (port,mask) ((port) |= (1<<mask))
Daher habe ich verschiedene Präproz.-Aufrufe ausprobiert - ohne Erfolg.
Hatte schon ein paar mal den Präprozessor Makro genau so geschrieben -
Funktionierte immer.
#define SET_BIT(port,mask) ((port) |= (1<<mask))
> Hatte schon ein paar mal den Präprozessor Makro genau so geschrieben
Sicher nicht mit Leerzeichen zwischen Name und Klammer. Beim
Präprozessor ist das nicht zulässig.
A. K. schrieb:> #define SET_BIT(port,mask) ((port) |= (1<<mask))
Hier ist ein Leerzeichen nach "SET_BIT" falsch, da es sich um ein Makro
mit "port" und "mask" als Parameter handelt.
__Son´s B. schrieb:> #define OBER_BEREICH (1023/15*11.5)
Hier muss ein Leerzeichen nach "OBER_BEREICH" eingefügt werden, da es
sich nicht um ein Makro sondern um eine Wertdefinition handelt.
Speckbert schrieb:> __Son´s B. schrieb:>> #define OBER_BEREICH (1023/15*11.5)>> Hier muss ein Leerzeichen nach "OBER_BEREICH" eingefügt werden, da es> sich nicht um ein Makro sondern um eine Wertdefinition handelt.
Natürlich handelt es sich um ein Makro, allerdings um eines ohne
Parameter.
__Son´s B. schrieb:> ???> Wie unterscheiden sich die Präproz.?> Geht es darum, ob Werte zurück gegeben werden oder irgend etwas> ausgelöst wird?
Nein, es geht darum, ob du an dein Makro Parameter übergeben willst. In
dem Fall muss die Parameterliste mit ihren Klammern ohne Leerzeichen
nach dem Namen stehen. Wenn dagegen die Klammer Teil des Inhalts des
Makros ist, muss sie durch das Leerzeichen abgegrenzt werden. Irgendwie
muss der Präprozessor das ja unterscheiden können.
Deshalb die Fehlermeldung bei:
__Son´s B. schrieb:> #define OBER_BEREICH(1023/15*11.5)
Der Präprozessor erwartet in den Klammern eine Parameterliste und stellt
dann fest, dass 1023 kein gültiger Parametername ist.
OK!
Noch zwei Grundlagen, die ich nicht ganz zuordnen kann;
--1--
#define SET_BIT(port,mask) ((port) |= (1<<mask))
#define CLR_BIT(port,mask) ((port) &= ~(1<<mask))
#define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))
(SET_BIT(PORTB,PB2))
Fehlermeldung für Zeile LED_LOW.
Darf ein Macro ein anderes Macro nicht direkt aufrufen?
--2--
In ADC_Init() warnt der Komp., dass "messwert" deklariert, aber nicht
benutzt wird.
uint16_t messwert;
Hier wird diese Var. in der letzten Zeile zugwiesen;
messwert = ADCW;
Wie begründet sich die Warnmeldung?
__Son´s B. schrieb:> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))
Einfach so:
#define LED_LOW() (CLR_BIT(PORTB,PB1))
zu 2
nicht verwendet oder nicht gelesen?
__Son´s B. schrieb:> OK!>> Noch zwei Grundlagen, die ich nicht ganz zuordnen kann;> --1--> #define SET_BIT(port,mask) ((port) |= (1<<mask))> #define CLR_BIT(port,mask) ((port) &= ~(1<<mask))> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))> (SET_BIT(PORTB,PB2))>> Fehlermeldung für Zeile LED_LOW.
Gleicher Fehler wie vorher. Du gibst "CLR_BIT(PORTB,PB0)" als
Parameterliste für dein Makro LED_LOW an. Das ergibt aber nicht viel
Sinn.
> Darf ein Macro ein anderes Macro nicht direkt aufrufen?
Doch, darf es.
> --2--> In ADC_Init() warnt der Komp., dass "messwert" deklariert, aber nicht> benutzt wird.> uint16_t messwert;> Hier wird diese Var. in der letzten Zeile zugwiesen;> messwert = ADCW;> Wie begründet sich die Warnmeldung?
Wird der Inhalt denn irgendwann auch mal wieder gelesen? Eine Variable,
in den ich einen Wert nur reinschreibe, ohne ihn nachher je wieder
anzufassen, ist sinnlos.
__Son´s B. schrieb:> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))> (SET_BIT(PORTB,PB2))
Was soll das darstellen?
> Darf ein Macro ein anderes Macro nicht direkt aufrufen?
Doch.
> Wie begründet sich die Warnmeldung?
Möglicherweise weil du zwar einen Wert reinschreibst, aber sonst mit
"messwert" nichts passiert?
Kirsch schrieb:> Einfach so:> #define LED_LOW() (CLR_BIT(PORTB,PB1))
Funktioniert leider auch nicht!
A. K. schrieb:> Was soll das darstellen?
Vereinfachung der Abfolge LED/high aus, LED/mid aus, LED/low ein
Alternative wäre aufwendiger;
main()...
SET_BIT(PORTB,PB0);
CLR_BIT(PORTB,PB1);
CLR_BIT(PORTB,PB2);
und das immer wieder, je nach Schaltungszustand.
Kirsch schrieb:> zu 2> nicht verwendet oder nicht gelesen?
In der Tat, ein Wert wird ausgelesen und in diese Var geschrieben, aber
nicht weiter verwendet.
__Son´s B. schrieb:> Kirsch schrieb:>> Einfach so:>> #define LED_LOW() (CLR_BIT(PORTB,PB1))> Funktioniert leider auch nicht!
"Funktioniert nicht" ist keine adäquate Fehlerbeschreibung.
Das sieht für mich so korrekt aus.
__Son´s B. schrieb:> #define LED_LOW(CLR_BIT(PORTB,PB0)) (CLR_BIT(PORTB,PB1))> (SET_BIT(PORTB,PB2))>> Fehlermeldung für Zeile LED_LOW.
Das ist ja auch totaler Mist.
1.:
A. K. schrieb im Beitrag #4421150:
> Da fehlt mal wieder das Lerrzeichen.
2.:
Der Aufruf ist
1
LEDLOW;
Daraus wird:
1
PORTB&=~(1<<PB0)PORTB&=~(1<<PB1)PORTB|=(1<<PB2);
Fällt dir auf, was da fehlt?
Rictig! Hinter den ersten beiden Anweisungen fehlt das Semikolon.
Generell ist es sinnvoll, sich mal zu überlegen, was nach einer
Makro-Ersetzung rauskommt und zu scahuen, ob das einen Sinn ergibt.
Damit kommt man zumindest schneller zum Ziel als durch hin- und
herschieben von Leerzeichen und mal probieren, ob's der Compiler
schluckt.
__Son´s B. schrieb:> Ok, so passt´s
Nein, das ist auch Mist.
Überleg dir mal, was passiert, wenn du schreibst:
1
if(blabla)LEDLOW;
Setz das in eine do{}while(0) Schleife. Alles andere macht nur Probleme.
Die Schleife wird vom Compiler komplett wegoptimiert. Die ist also gar
nicht da.
Mein grosses V. schrieb:> Überleg dir mal, was passiert, wenn du schreibst:
while(1)
{
mit_wert = ADC_Read_Avg(3,64);
if (mit_wert > OBER_BEREICH) { LED_HIGH; }
if (mit_wert < UNTER_BEREICH) { LED_LOW; }
else { LED_MID; }
}
Nach meinm Verständnis, wird "mit_wert" in einer Dauerschleife
ausgewertet und danach den 3 Bedingungen zu geordnet. Was soll daran
"Mist" sein?
__Son´s B. schrieb:> if (mit_wert > OBER_BEREICH) { LED_HIGH; }
Das habe ich auch nicht geschrieben, sondern das:
1
if(blabla)LEDHIGH;
Und daraus wird:
1
if(blabla)Anweisung1;
2
Anweisung2;
3
Anweisung3;
D.h., daß Anweisung1 in Abhängigkeit von blabla ausgeführt wird,
Anweisung2 und 3 dagegen immer. Das ist aber nicht Sinn der Sache.
Du zwingst dich damit, immer hinter der if-Abfrage Klammern zu setzen.
Das ist bei nur einer folgenden Anweisung aber gar nicht notwendig. Das
funktioniert jetzt, da du es weisst. Damit schiesst du dir aber
langfristig ins Knie.
Mach es vernünftig!
__Son´s B. schrieb:> Was soll daran "Mist" sein?
Die Erklärung von "Mein grosses Vorbild" hat da noch etwas
Optimierungspotenzial.
Es ging ihm darum, dass du das Makro nicht genau wie eine Funktion
behandeln kannst, da es mehrere statements beinhaltet. Dadurch können
unerwartete Effekte auftreten wie z.B. in:
1
#define X() a(); b()
2
3
if(z==3)X();
Man erwartet, dass a() und b() nur aufgerufen werden, wenn z den Wert 3
hat. Tatsächlich wird b() aber immer aufgerufen. Denn durch die
Makro-Ersetzung entsteht:
1
if(z==3)a();b();
oder etwas klarer eingerückt:
1
if(z==3)
2
a();
3
b();
Aus dem Grund wird in Makros, die mehrere statements zusammenfassen,
gerne ein do {} while(0) darum herum geschrieben. Das tut letztendlich
nichts anderes, als den Code zwischen den Klammern genau einmal
auszuführen, aber es ist insgesamt wieder ein einzelnes Statement. Damit
funktioniert die obige Abfrage auch wie erwartet:
1
#define X() do { a(); b(); } while (0)
2
3
if(z==3)X();
wird ersetzt durch:
1
if(z==3)
2
do
3
{
4
a();
5
b();
6
}while(0);
Durch den Trick mit dem do/while wird b genau wie a in der Bedingung
ausgeführt.
A. K. schrieb:> wenn du eines Tages mal die {} Klammern weglässt
ahhh! Es ging also nur um meinen Minimal-Auszug;
LED_LOW;
ohne Vor- und Nachstehendes!?
Klar kann das in c nicht einfach nur "dumm" rum stehen...
__Son´s B. schrieb:> ahhh! Es ging also nur um meinen Minimal-Auszug;
Nein. Es geht darum, dir zu zeigen, wie man vernünftige Makros mit
mehreren enthaltenen Anweisungen schreibt.
__Son´s B. schrieb:> Klar kann das in c nicht einfach nur "dumm" rum stehen...
Natürlich kann man das. Aber willst du dir jeden Spezialfall deiner
Makros merken?
Sinn der Übung ist, daß du gar nicht unbedingt wissen musst, daß das ein
Makro ist, sondern du dieses genauso wie eine Funktion benutzen kannst
und benutzen musst. Mit allen Spezialitäten bei der Abfrage von
Bedingungen oder der Benutzung in Schleifen.
Konsequenterweise kann man das auch so schreiben:
1
#define Makro() do{...}while(0)
2
3
Makro();
4
5
while(1)Makro();
6
7
while(1)
8
{
9
Makro();
10
}
11
12
if(Bla)Makro();else{...}
13
14
if(Bla)
15
{
16
Makro();
17
}else{...}
Kriegst du die Aufrufe mit deiner Version auch hin? Nein. Bei zwei
Aufrufen fliegst du auf die Schnauze. Und vor allen Dingen: Weißt du das
in einem Jahr noch?