mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik #define in C


Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
...
???

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Daniel aka Khani (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul (Gast)
Datum:

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

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: carbolo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

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


Gruß,

Dirk

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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. [...]

  [...]

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, da sind einige Ligaturen durch gerutscht.

Die Zeichenkette fi soll ein "fi" sein.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Unbekannter

Stimmt, bei Funktionsaufrufen geht das, aber leider nicht be defines:
#include <io.h>

#define LED1 PORTB,1

#define LED_AN(x,y)     x&=~(1<<y)

int main()
   {
     LED_AN(PORTB,1);   // geht

     LED_AN(LED1);      // geht nicht
     return 0;
   }


Peter

Autor: Wegstabenverbuchsler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe erstmal folgende Lösung gefunden:
#include <io.h>

#define LED1            1
#define LED1_PORT       PORTB

#define LED2            3
#define LED2_PORT       PORTC


#define LED_ON(x)       x##_PORT&=~(1<<x)
#define LED_OFF(x)      x##_PORT|=1<<x


int main()
{
  LED_ON( LED1 );

  LED_OFF( LED2 );

  for(;;);
}


Ist halt etwas mehr Schreibarbeit bei den Defines.


Peter

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Peter K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.