mikrocontroller.net

Forum: Compiler & IDEs #defines in AVR-libc


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

warum sind eigentlich alle Ports, Pins und Register in der AVR-libc 
folgendermaßen definiert:
/* DDRC */
#define DDC7    7
#define DDC6    6
#define DDC5    5
#define DDC4    4
#define DDC3    3
#define DDC2    2
#define DDC1    1
#define DDC0    0

im Code soll man das dann z.B. so nutzen:
DDRC = (1 << DDC0) | (1 << DDC1) | (1 << DDC2) | (1 << DDC3) | (1 << DDC4);
Das soll dann laut AVR-GCC-Tutorial "übersichtlich und selbsterklärend" 
sein.
DDRC = 0x1F;
hingegen soll "unübersichtlich" sein.
DDRC = 0b00011111;
Das es auch so geht wird gar nicht erwähnt.

Würde man es in der AVR-libc direkt so definieren:
/* DDRC */
#define DDC7    128
#define DDC6    64
#define DDC5    32
#define DDC4    16
#define DDC3    8
#define DDC2    4
#define DDC1    2
#define DDC0    1
dann könnte man es noch viel übersichtlicher und mit relativ wenig 
Tipparbeit so schreiben:
DDRC = DDC0 | DDC1 | DDC2 | DDC3 | DDC4;

Ich frage mich, warum das trotzdem so umständlich gemacht wird. Ist es 
ohne die Shiftoperatoren nicht elitär genug, oder gibt es dafür einen 
richtigen Grund?

Gruß,
Thomas

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

Bewertung
0 lesenswert
nicht lesenswert
Thomas schrieb:

> Ist es
> ohne die Shiftoperatoren nicht elitär genug, oder gibt es dafür einen
> richtigen Grund?

Manchmal benötigt man tatsächlich die Pinnummer ( also 0, 1, 2, 3 ... 7 
) und nicht die Bit-Maske die daraus ensteht.

Hab ich die defines
#define DDC7    7
#define DDC6    6
#define DDC5    5
#define DDC4    4
#define DDC3    3
#define DDC2    2
#define DDC1    1
#define DDC0    0

dann hab ich automatisch die Pinnummern. Die zugehörigen Bit-Masken kann 
ich mir ohne grossen Aufwand selbst definieren
#define DDC7_MASK    ( 1 << DDC7 )
#define DDC6_MASK    ( 1 << DDC6 )
#define DDC5_MASK    ( 1 << DDC5 )
...

und kann die dann leicht benutzen
  DDRC = DDC0_MASK | DDC1_MASK | DDC2_MASK | DDC3_MASK | DDC4_MASK;


aber der umgekehrte Weg ist ungleich schwieriger.
Hab ich nur die Bit-Masken, dann gibt es keinen einfachen Weg um daraus 
die Pinnummern zu generieren.

Die eigentliche Frage lautet daher: Welches ist die sinnvoll einfachste 
Möglichkeit das gewünschte auszudrücken, so dass Alles weitergehende 
daraus auf simple Art und Weise erzeugt werden kann?
Und das sind nun mal die Pin-Nummern

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt auch Fälle, wo man die Bit-Nummer braucht, z.B. bei diversen 
Assemblerbefehlen.

Grundsätzlich ist die Bit-Nummer universeller, weil man sehr einfach von 
der Nummer zur Maske kommt (eben mit dem Shift). Bei der von dir 
vorgeschlagenen Bit-Maske kommt man aber nicht auf ebenso einfachem Weg 
an die Nummer, wenn man die mal braucht.

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich frage mich, warum das trotzdem so umständlich gemacht wird. Ist es
> ohne die Shiftoperatoren nicht elitär genug, oder gibt es dafür einen
> richtigen Grund?

Die Original-Dateien von Atmel haben nun mal die Register-Bits so 
definiert.

Und sind wir mal ehrlich, ein Programmierer der an eine 
Shift-Operationen scheitert sollte vielleicht ans Umsatteln auf BWL 
denken.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liegt am Instruktionssatz des AVR.
Folgende Instruktionen beispielsweise brauchen nicht eine Maske, sondern 
eine Bitnummer:
- sbis und sbic, sbrs und sbrc
- sbi und cbi
- bst und bld
- brbs und brbc
- bset und bclr

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl heinz & Stefan:
Danke für die Erläuterung.

@Norgan
Kein Grund arrogant zu werden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:
> Liegt am Instruktionssatz des AVR.

Naja.  Dafür, dass der AVR mit Zielrichtung C konzipiert worden ist,
hätte man auch wirklich die Bitmaske in die Headerdatei schreiben
können.  Ein Assembler sollte mühelos in der Lage sein, aus

SBI PORTA, 0x40

auszurechnen, welches Bit er nun setzen soll und ggf. einen Fehler
zu spucken, falls in der Zahl rechts nicht genau ein Bit gesetzt
sein sollte.

Dafür dürfen wir uns nun den Rest des AVR-Lebens in C mit all
diesen Schiebeoperatoren herumärgern.  Egal ob nun direkt hin
geschrieben oder hinter _BV() versteckt, sie machen den geschriebenen
C-Code reichlich unübersichtlich.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tjo, is wohl wahr.

Autor: hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit #define geht es auch noch anderst:
#define MASK(a)    ( 1 << a)

#define DDC2    2
#define DDC1    1
#define DDC0    0

df=MASK(DDC2)|MASK(DDC0);     // neue Schreibweise

df=(1<<DDC2)|(1<<DDC0);      // alte Schreibweise



Ob diese Ersetzung schöner ist muß man selber überlegen.

Man braucht es ja nicht MASK zu nennen.

gruß hans

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hans schrieb:

> Man braucht es ja nicht MASK zu nennen.

Man könnte es, ja, ähem, zum Bleistift _BV() nennen. :-)

Autor: hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich dachte eher an "setzen"

gruß hans

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde es einfach so nennen:
#define BIT7    128
#define BIT6    64
#define BIT5    32
#define BIT4    16
#define BIT3    8
#define BIT2    4
#define BIT1    2
#define BIT0    1

Bringt doch Null Mehrwert, wenn da auch noch der Name des Registers mit 
verwurschtelt ist. Der steht ja eh vor dem =.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas schrieb:

> Bringt doch Null Mehrwert, wenn da auch noch der Name des Registers mit
> verwurschtelt ist. Der steht ja eh vor dem =.

Nur bei PORTx/DDRx/PINx.  Dort benutze ich in aller Regel wirklich
nur die Zahlen.

Interessant wird das ja erst bei den diversen IO-Steuerregistern mit
ihren Bitnamen.

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.