#defines in AVR-libc

Gast #1249784
Lesenswert?

Moin,

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

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

Würde man es in der AVR-libc direkt so definieren:
1
/* DDRC */
2
#define DDC7    128
3
#define DDC6    64
4
#define DDC5    32
5
#define DDC4    16
6
#define DDC3    8
7
#define DDC2    4
8
#define DDC1    2
9
#define DDC0    1
dann könnte man es noch viel übersichtlicher und mit relativ wenig 
Tipparbeit so schreiben:
1
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
#1249796
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
1
#define DDC7    7
2
#define DDC6    6
3
#define DDC5    5
4
#define DDC4    4
5
#define DDC3    3
6
#define DDC2    2
7
#define DDC1    1
8
#define DDC0    0

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

und kann die dann leicht benutzen
1
  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
#1249798
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.
Gast #1249799
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.
Gast #1249810
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
Moderator Persönliche Seite #1249828
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.
Gast #1250134
Lesenswert?

Mit #define geht es auch noch anderst:
1
#define MASK(a)    ( 1 << a)
2

3
#define DDC2    2
4
#define DDC1    1
5
#define DDC0    0
6

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

9
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
Gast #1250190
Lesenswert?

Ich würde es einfach so nennen:
1
#define BIT7    128
2
#define BIT6    64
3
#define BIT5    32
4
#define BIT4    16
5
#define BIT3    8
6
#define BIT2    4
7
#define BIT1    2
8
#define BIT0    1

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren