www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik #define aber wie?


Autor: Dominik Boine (dominik123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

habe mal eine frage zu dem "#define" Befehl.
Die Idee ist jedem PIN am Mikrokontroller einen Namen zuzuweisen.
bsp:
#include <avr/io.h>
#define LED PC0    //PortC Pin0
int main (void)
{
   LED=1;           // <= die Wertezuweisung mag der Compiler nicht
}
Wie kann ich dieses realisieren???



Gruß
Dominik

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie kann ich dieses realisieren???

So? Gar nicht!

Autor: Dieter Stotz (bulova)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik,

im Define fand bereits eine Zuweisung statt (sie bedeutet, dass "LED" 
eine bestimmte Pin-Adresse verwendet), die kann man nicht einfach 
überschreiben. Willst Du diese LED einschalten bzw. den Port High legen, 
geht das z. B. über die Zeile

output_bit(LED,1)

oder

output_high(LED)


Dieter

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define ist eine Präprozessor-Anweisung und kein Befehl. #define sagt 
dem Präprozessor, dass er eine Textersetzung vornehmen soll. In diesem 
Fall wird er an jeder Stelle, an der im Quellcode "LED" auftaucht, 
stattdessen "PC0" einsetzen. "PC0" ist aber an anderer Stelle (im 
Device-spezifischen Header-File) ebenfalls per #define definiert, und 
zwar steht da
#define PC0 0
0 ist aber schlicht und ergreifend eine Zahl, und der kannst Du mit "=" 
keinen anderen Wert zuweisen! Nach der Bearbeitung durch den 
Präprozessor steht in main nämlich
0 = 1;
Und dass das nicht sein kann, sollte klar sein...

Die von Dir beabsichtigte Schreibweise funktioniert ohne weiteres gar 
nicht. Dazu müsstest Du dem Compiler Bitzugriffe beibringen (manche 
kommerziellen Compiler machen das auch als nicht standardkonforme 
Erweiterung, aber AVR-GCC ist ein ANSI-C-Compiler und tut selbiges 
nicht).

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik Boine wrote:
> #include <avr/io.h>
> #define LED PC0    //PortC Pin0
> int main (void)
> {
>    LED=1;           // <= die Wertezuweisung mag der Compiler nicht
> }

"PC0" ist auch nur mit #define vereinbart worden, und zwar i.d.R. so:
#define PC0   0

Jetzt steht da also "0 = 1" in der Main-Routine...!
Deine Idee ist mit #define nicht direkt zu lösen; alles was du  mit 
#define festlegst, wird einfach nur ersetzt, bevor der Compiler deinen 
Quelltext zu sehen bekommt.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Machs so:

#include <avr/io.h>
struct bits {
  char b0:1;
  char b1:1;
  char b2:1;
  char b3:1;
  char b4:1;
  char b5:1;
  char b6:1;
  char b7:1;
} __attribute__((_packed_));

#define LED ((*(volatile struct bits*)&PORTC).b0)

Dann kannst du schreiben:

int main (void)
{
   LED=1;
}

Autor: mandrake (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

@Benedikt:
Ist __attribute__((packed)) ein von dir erfundener Name oder gibt es 
da noch eine Besonderheit?

Dann zu der define-Zeile:
Habe ich das so richtig verstanden?

(volatile struct bits*)&PORTC --> Cast der Adresse von PORTC in einen 
Pointer vom Typ [volatile struct bits].

((*(volatile struct bits*)&PORTC).b0)
  ^
  |
Dieser Stern ist dann der Inhaltsoperator -Richtig?


Bitte um Korrektur wenn ich was falsch verstanden habe.
Ansonsten wieder was gelernt - Danke!

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Etwas flexibler: Struktur wie bei Benedikt K., Makro wie hier:

Beitrag "Re: sbit macro für avr-gcc"

(Ersetze "test" durch "bits")

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mandrake wrote:
> Hallo zusammen!
>
> @Benedikt:
> Ist __attribute__((packed)) ein von dir erfundener Name oder gibt es
> da noch eine Besonderheit?

Das sagt dem Compiler, dass er die Bits so eng wie möglich packen soll, 
und das ganze nicht z.B. aus Geschwindigkeitsgründen optimieren soll.

> Dann zu der define-Zeile:
> Habe ich das so richtig verstanden?
>
> (volatile struct bits*)&PORTC --> Cast der Adresse von PORTC in einen
> Pointer vom Typ [volatile struct bits].

So in etwa. volatile verbietet dem Compiler hier wieder einige 
Optimierungsmöglichkeiten, so dass er diesen Befehl nicht wegoptimiert. 
Wenn man z.B. schreibt
LED=1;
LED=0;
denkt der Compiler: Am Ende kommt 0 raus, also ist die Zeile LED=1 
überflüssig und lässt diese weg. Mit dem volatile verbietet man dies dem 
Compiler.

> ((*(volatile struct bits*)&PORTC).b0)
>   ^
>   |
> Dieser Stern ist dann der Inhaltsoperator -Richtig?

Ja.

> Ansonsten wieder was gelernt - Danke!

Das ganze stammt übrigends nicht von mir, sondern taucht immer wieder 
hier im Forum auf. Keine Ahnung von wem das Orginal stammt.
Das ganze ist nicht unbedingt eine Vorbildliche Lösung, da der Code 
schwerer portierbar wird, es macht den Code meiner Meinung nach aber 
besser lesbar.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das packed-Attribute braucht man (zumindest bei neueren GCCs) nicht.
GCC 4.2.3 und 4.3.0 geben sogar eine Warnung aus:

  '_packed_' attribute directive ignored

Bei einem Bitfeld sind die einzelnen Elemente sowieso immer gepackt
solange sie alle in einem einzelnen char/int-Wert Platz haben.

Zu beachten wäre noch, dass beim Zugriff auf I/O-Bits mit der obigen
Methode für
  LED = 0;            // Output
  LED = 1;

  if(BUTTON) { ... }  // Input
  if(!BUTTON) { ... }

bestmöglicher Code erzeugt wird, nicht jedoch für
  LED = value;  // value in {0, 1}

  value = BUTTON;

was teilweise zu aufwendigen Schiebeoperationen führt. Hier ist es
meist besser,
  if(value)
    LED = 1;
  else
    LED = 0;

  if(BUTTON)
    value = 1;
  else
    value = 0;

zu schreiben. Auch wenn es in C komplizierter aussieht, wird es im
kompilierten Code kürzer und schneller.

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.