Hallo Gemeinde, ich schreibe in C ein Prog. für den mega128. Zur Ausgabe auf ein Grafikdisplay muss ich div. Parameter an eine Funktion übergeben. Es soll z.B. ein rechteckiger Rahmen gezeichnet werden. Meine Funktionsaufruf mit den Rahmendaten(x1,y1,x2,y2)lautet: rahmen_eck(10,10,80,90); Ich möchte die Rahmendaten aber in einer #define-Anweisung definieren. Wie sieht dann diese Anweisung aus? In meinen Lehr(Leer-)büchern finde ich dazu nichts. Könnt Ihr mir helfen? Vielen Dank!
Hallo Ich kann aus dem was Du geschrieben hast das Problem nicht ganz nachvollziehen. Was genau soll mit #define definiert werden? #define x1 10 #define x2 10 ... ???
Ich habe mir soetwas vorgestellt, z.B. in Arrayform: #define position1 10,10,80,90 der Funktionsaufruf würde so aussehen: rahmen_eck(position1);
Hallo Peter, wieso machst Du es dann nicht so und drückst auf den "Compile"- Button ? Wenn ich mir nicht sicher bin und ich wenig Lust zum nachdenken oder nachschauen habe, dann probiert ich's einfach aus. Wenn eine Fehlermeldung kommt, dann kann man immer noch reagieren. Ist ja nicht so, als würde compilieren 2 Stunden dauern ;-). MfG, Daniel.
Genau: Hast Du das mal ausprobiert? Ich wüsste jetzt keinen Grund, warum das so nicht funktionieren sollte. Aber probieren geht über studieren! Kaputt machen kannste damit wahrscheinlich nix. Gruß Johnny
Habt Dank! Jetzt funzt es. Bei #define position 10,10,80,90 brachte der Compiler immer die Fehlermeldung: L3402: too few parameter in function call diese hab ich falsch interpretiert. Schande über mich! Besten Dank für Eure Hilfe!
Leider kommt die Textersetztung zu spät. Erst wird geprüft, ob eine Funktion mit 4 Argumenten auch 4 Argumente kriegt und da krachts schon. Ich ärgere mich auch jedesmal darüber, daß ich einen Portpin nicht mit einem Define ersetzen kann, immer muß man das Portregister extra mitschleppen. Peter
Ich glaube dass das was du suchst nicht #define ist, sondern struct. Kann das sein? Der Funktionsaufruf würde dann etwa so aussehen: structname.x1 Dafür brauchst du noch nicht mal Klassen, das deht auch in C wunderbar. Schöne Grüße: Z
@peter dannegger: > Leider kommt die Textersetztung zu spät. > > Erst wird geprüft, ob eine Funktion mit 4 Argumenten auch > 4 Argumente kriegt und da krachts schon. Nö. Ein normgerechter C-Compiler muss folgenden Code astrein akzeptieren: void f(int a, int b, int c, int d) { // Mach was... } #define werte 1, 2, 3, 4 int main() { f(werte); return 0; } Akzeptiert das Dein Compiler nicht, ist er kaputt und Du solltest Dein Geld zurück verlangen.
Hi, ich wuerde soetwas wie Rahmen zeichnen, vielleicht auch lieber ueber ein Struct machen. Gruß, Dirk
Als besonderer Service eine Auszügen aus dem ISO-C99-Dokument: 5.1.1.2 Translation phases [...] 1. Physical source file multibyte characters are mapped [...] 2. Each instance of a backslash character (\) immediately followed by a new-line character is deleted, splicing physical source lines to form logical source lines. [...] 3. The source file is decomposed into preprocessing tokens and sequences of white-space characters [...] 4. Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. [...] 5. Each source character set member and escape sequence in character constants and string literals is converted to the corresponding member of the execution character set [...] 6. Adjacent string literal tokens are concatenated. 7. White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. [...] 8. All external object and function references are resolved. Library components are linked to satisfy external references to functions and objects not defined in the current translation. [...] [...]
Oh, da sind einige Ligaturen durch gerutscht. Die Zeichenkette fi soll ein "fi" sein.
@Unbekannter Stimmt, bei Funktionsaufrufen geht das, aber leider nicht be defines:
1 | #include <io.h> |
2 | |
3 | #define LED1 PORTB,1
|
4 | |
5 | #define LED_AN(x,y) x&=~(1<<y)
|
6 | |
7 | int main() |
8 | {
|
9 | LED_AN(PORTB,1); // geht |
10 | |
11 | LED_AN(LED1); // geht nicht |
12 | return 0; |
13 | }
|
Peter
Das von Peter Dannegger gesagte klingt doch aber logisch, wenn der Präprozessor nur 1 Durchlauf macht: In Zeile 9 wird der Platzhalter "LED_AN(PORTB,1)" nach Zwischenübersetzung von x=PORTB und y=1 gegen "gescheites" Assemblerzeugs PORTB&=~(1<<1) ersetzt. Der Parser/Compiler kann danach was damit anfangen. In Zeile 11 wird der Platzhalter "LED_AN(LED1)" nach Zwischenübersetzung von LED1= "PORTB,1" gegen einen anderen Platzhalter LED_AN(PORTB,1) ersetzt. Der Parser/Compiler kann mit nix anfangen. Würde der Präprozessor nun nochmal durchlaufen, dann könnte er ja, aber er weiß ja nicht daß er nochmal durchrennen soll....
Der Preprozessor läuft normalerweise in mehreren Durchläufen durch. Das Problem ist ein anderes: Wenn der PP auf LED_AN( LED1 ); stoesst, sucht er eine Ersetzung für LED_AN. Die findet er auch: #define LED_AN(x,y) x&=~(1<<y) aber jetzt geht das Dilemma los: Das LED_AN Makro will 2 Paramter, da steht aber nur eines, naemlich LED1 Daher beschwert sich der Preprozessor, dass die Anzahl der Makroargumente nicht mit der Anzahl der vom Makro verlangten Argument uebereinstimmt. Das LED1 seinerseits wieder ein Makro ist, wurde zu diesem Zeitpunkt noch überhaupt nicht ins Kalkül gezogen. Inwiefern sowas ISO-Konform ist, kann ich nicht sagen. Eigentlich wäre es logisch wenn der PP zunächst mal Makro-Argument seinerseits wieder auf Makros untersucht und ersetzt. Aber anscheinend passiert das nicht.
Ich habe erstmal folgende Lösung gefunden:
1 | #include <io.h> |
2 | |
3 | #define LED1 1
|
4 | #define LED1_PORT PORTB
|
5 | |
6 | #define LED2 3
|
7 | #define LED2_PORT PORTC
|
8 | |
9 | |
10 | #define LED_ON(x) x##_PORT&=~(1<<x)
|
11 | #define LED_OFF(x) x##_PORT|=1<<x
|
12 | |
13 | |
14 | int main() |
15 | {
|
16 | LED_ON( LED1 ); |
17 | |
18 | LED_OFF( LED2 ); |
19 | |
20 | for(;;); |
21 | }
|
Ist halt etwas mehr Schreibarbeit bei den Defines. Peter
@Peter Dannegger du kannst das aber auch folgendermaßen machen: typedef unsigned char byte; struct test { byte b0:1; byte b1:1; byte b2:1; byte b3:1; byte b4:1; byte b5:1; byte b6:1; byte b7:1; } __attribute__((_packed_)); #define LED1 ((volatile struct test*)&PORTD)->b0 #define LED2 ((volatile struct test*)&PORTD)->b1 #define LED3 ((volatile struct test*)&PORTD)->b2 ... Im Proramm kannst du dann schreiben LED1=1; LED2=0; usw. Gruß Volker
@Volker, ja so gehts auch, sieht dann auch gleich dem 8051 ähnlicher. Wozu ist denn das "__attribute__((_packed_))" gut, es scheint auch ohne das zu gehen. Peter
Kann mal jemand in Sätzen ausdrücken was #define LED1 ((volatile struct test*)&PORTD)->b0 macht, bzw. wie es der Präprozessor liest und verarbeitet? wäre sehr nett, desnn es würde mir verständlich machen, was ich da überhaupt verwende. Vielen Dank
:-) Der Präprozessor nimmt einfach nur zur Kentnis, das er überall dort, wo der Text "LED1" auftaucht, er diesen Text durch den Text "((volatile struct test*)&PORTD)->b0" ersetzen soll. Das ist sein Job und das macht er auch: Textersetzungen Was der Ursprungstext in seinem Zusammenhang bedeutete, bzw. welche Bedeutung der Ersatztext hat, interessiert den Präprozessor nicht. Nun ist mir schon klar, dass du das nicht wissen wolltest, auch wenn du danach gefragt hast :-) PORTD PORTD ist selber wieder ein Präprozessor Makro. Seinen Effekt könnte man so ausdrücken: Es handelt sich um die Werte, die an den Portpins vom PORTD anliegen. Also PORTD der Port D &PORTD nimm die Adresse vom PORTD ((volatile struct test*)&PORTD) und tu so, als ob diese Adresse ein Pointer auf etwas wäre, was sich ein struct test schimpft. Genau genommen sogar ein volatile struct test Pointer ein struct test ist das hier struct test { byte b0:1; byte b1:1; byte b2:1; byte b3:1; byte b4:1; byte b5:1; byte b6:1; byte b7:1; } __attribute__((packed)); also ein Byte, welches mittels einer struct in einzelne Bits aufgeteilt wird. ((volatile struct test*)&PORTD)-> und jetzt greif über diesen 'tu so als ob' Pointer auf ein Member dieser Struktur zu ((volatile struct test*)&PORTD)->b0 Nämlich auf das Member b0 Alles zusammengenommen: Über den Port D, der sich in C als ganzes Byte preäsentiert, wird eine Kappe in Form eines struct test gestülpt, so dass die einzelnen Bits direkt zugreifbar werden. Aus einiger Entfernung betrachtet: Du brauchst ein C-Buch
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.