Forum: Mikrocontroller und Digitale Elektronik #define in C


von Peter Pan IV (Gast)


Lesenswert?

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!

von johnny.m (Gast)


Lesenswert?

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
...
???

von Peter Pan IV (Gast)


Lesenswert?

Ich habe mir soetwas vorgestellt, z.B. in Arrayform:

#define position1 10,10,80,90


der Funktionsaufruf würde so aussehen:

rahmen_eck(position1);

von Daniel aka Khani (Gast)


Lesenswert?

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.

von johnny.m (Gast)


Lesenswert?

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

von Rahul (Gast)


Lesenswert?

Eben: Es ist ja eine Textersetzung, die der Preprozessor(?) macht...

von Peter Pan IV (Gast)


Lesenswert?

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!

von peter dannegger (Gast)


Lesenswert?

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

von carbolo (Gast)


Lesenswert?

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

von Unbekannter (Gast)


Lesenswert?

@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.

von Dirk (Gast)


Lesenswert?

Hi,

ich wuerde soetwas wie Rahmen zeichnen, vielleicht auch lieber ueber
ein Struct machen.


Gruß,

Dirk

von Unbekannter (Gast)


Lesenswert?

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. [...]

  [...]

von Unbekannter (Gast)


Lesenswert?

Oh, da sind einige Ligaturen durch gerutscht.

Die Zeichenkette fi soll ein "fi" sein.

von peter dannegger (Gast)


Lesenswert?

@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

von Wegstabenverbuchsler (Gast)


Lesenswert?

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....

von Karl H. (kbuchegg)


Lesenswert?

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.

von peter dannegger (Gast)


Lesenswert?

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

von Volker (Gast)


Lesenswert?

@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

von peter dannegger (Gast)


Lesenswert?

@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

von Volker (Gast)


Lesenswert?


von Peter K. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

:-)
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
Noch kein Account? Hier anmelden.