Forum: Mikrocontroller und Digitale Elektronik Einsteigerfrage zu C #define _BV() und Bit setzen -AVR-


von Bob Beginner (Gast)


Lesenswert?

Hallo

wahrscheinlich Grundlagenwissen aber ich brauche trotzdem eine 
Bestätigung oder Berichtigung und Beantwortung bei zwei Detailfragen.

Hier ein Codeauschnitt eines C-Programmes (für einen 8 Bit AVR)

#define RC_NOK_OUT  PA0
#define BLINK0_OUT  PA1
#define BLINK1_OUT  PA2
#define BLINK2_OUT  PA3
#define BLINK3_OUT  PA4
#define BLINK4_OUT  PA5
#define BLINK5_OUT  PA6
#define BLINK6_OUT  PA7
#define BLINKX_OUT (_BV(BLINK0_OUT) | _BV(BLINK1_OUT) | \
              _BV(BLINK2_OUT) | _BV(BLINK3_OUT) | \
              _BV(BLINK4_OUT) | _BV(BLINK5_OUT) | \
              _BV(BLINK6_OUT))

Mein Verständniss hierzu:

Pin PA0 wird der Name RC_NOK zugewiesen
Pin PA1 wird der Name BLINK0_OUT zugewiesen
usw.

Wenn später der Name BLINKX_OUT genutzt wird werden Pin PA0 bis PA7 über 
deren zugewiesene Namen alle auf Ausgang gesetzt.

Ist das soweit richtig?

| =_BV(Bitnummer) setzt ein Bit
Aber weshalb steht vor den ersten _BV(BLINK0_OUT) kein | Zeichen?

Und ist \ einfach nur ein Zeichen das es in der folgenden Zeile weiter 
geht mit den Befehl, also könnte \ wegfallen wenn alles in einer Zeile 
geschrieben werden würde?
...(_BV(BLINK0_OUT) | _BV(BLINK1_OUT) | \
              _BV(BLINK2_OUT) | _BV(BLINK3_OUT) | \
              _BV(BLINK4_OUT) | _BV(BLINK5_OUT) | \
              _BV(BLINK6_OUT))

Wie gesagt ich bin Anfänger und kenne noch nicht alle Tricks und 
Feinheiten.

mfg

Bob Beginner

von Schaust Du Nur (Gast)


Lesenswert?

Bob Beginner schrieb:
> _BV(BLINK0_OUT)

Das ist ein Makro und ist irgendwo weiter oben definiert. z. Bsp. in 
einem Header.
#define ...    _BV(x)

Die Namen der Makros sind schlecht gewählt, da nicht selbsterklärend. 
Scheint also ein Anfänger zu sein. Vorsicht mit solchem Code.

von Mathias O. (m-obi)


Lesenswert?


von Mathias O. (m-obi)


Lesenswert?

Achja du musst später dann nur PORTA |= BLINKX_OUT; schreiben.

von Bernd K. (prof7bit)


Lesenswert?

Bob Beginner schrieb:
> #define RC_NOK_OUT  PA0
> #define BLINK0_OUT  PA1
> #define BLINK1_OUT  PA2
> #define BLINK2_OUT  PA3
> #define BLINK3_OUT  PA4
> #define BLINK4_OUT  PA5
> #define BLINK5_OUT  PA6
> #define BLINK6_OUT  PA7
> #define BLINKX_OUT (_BV(BLINK0_OUT) | _BV(BLINK1_OUT) | \
>               _BV(BLINK2_OUT) | _BV(BLINK3_OUT) | \
>               _BV(BLINK4_OUT) | _BV(BLINK5_OUT) | \
>               _BV(BLINK6_OUT))

Wenn schon dann mach das lieber gleich so:
1
#define RC_NOK_OUT  _BV(PA0)
2
#define BLINK0_OUT  _BV(PA1)
3
#define BLINK1_OUT  _BV(PA2)
4
#define BLINK2_OUT  _BV(PA3)
5
#define BLINK3_OUT  _BV(PA4)
6
#define BLINK4_OUT  _BV(PA5)
7
#define BLINK5_OUT  _BV(PA6)
8
#define BLINK6_OUT  _BV(PA7)
9
#define BLINKX_OUT (BLINK0_OUT | BLINK1_OUT | \
10
                    BLINK2_OUT | BLINK3_OUT | \
11
                    BLINK4_OUT | BLINK5_OUT | \
12
                    BLINK6_OUT)
Dann musst Du nicht jedesmal mit dem _BV herumhantieren wenn Du sie 
verwendest, das macht weniger Kopfschmerzen beim Lesen.

Und gib den Pins richtige Namen, nicht so nichtssagende Nummern. Etwa 
so:
1
#define HAUPTSTEUERKONTROLLE   PORTB
2
3
#define WARPANTRIEB            _BV(PB1)
4
#define IMPULSANTRIEB          _BV(PB2)
5
#define TRAEGHEITSDAEMPFER     _BV(PB3)

Und dann:
1
void machen_sies_so() {
2
    HAUPTSTEUERKONTROLLE |= IMPULSANTRIEB | TRAEGHEITSDAEMPFER;
3
}

von Bob Beginner (Gast)


Lesenswert?

Hallo

dank an die welche sinnvolle Hilfe geleistet haben -also an Mathias O. 
und Bernd K.

Die Frage bezüglich  des \ Zeichens konnte mittlerweile geklärt werden.

Der Code (das Komplette Programm) stammt nicht von mir.

Um den Autor nicht zu kurz kommen lassen hier der Link zum Programm
http://www.xyleroo.de/rctiny.html

Bob Beginner

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Schaust Du Nur schrieb:

> Die Namen der Makros sind schlecht gewählt, da nicht selbsterklärend.

Historischer Ballast.  Sollte wohl mal bit value heißen.

> Scheint also ein Anfänger zu sein.

Wenigstens nicht ein Mr. Nobody wie du.  Dürfte von Marek Michalkiewicz
gewesen sein.  Lässt sich vielleicht noch im SVN nachvollziehen.

> Vorsicht mit solchem Code.

Vorsicht mit solchen Ratschlägen.  Wenn du's nicht weißt, brauchst
du darüber auch keinen Kommentar ablassen.

@TE:

Der Grund für diese Konstrukte ist, dass Atmel seinerzeit leider
nicht C-freundliche Bitmasken für die einzelnen Bitwerte (bit value,
genau :) vergeben hat, sondern Bitnummern.  Das sollte wohl Befehle
wie CBI und SBI im Assembler einfacher machen, aber das hätte man
auch anders lösen können.  Aber aus genau diesem Grunde muss man als
C-Programmierer ganz häufig so eine Bitnummer in die zugehörige Maske
umwandeln, was in C durch den relativ umständlich anmutenden Ausdruck
1 << bitno erfolgt.  Da man das eben so häufig braucht, liefert die
avr-libc dafür einen Makro, der zumindest ein wenig kürzer ist.

von Schaust Du Nur (Gast)


Lesenswert?

Jörg W. schrieb:
>> Vorsicht mit solchem Code.
>
> Vorsicht mit solchen Ratschlägen.

???
Du schreibst selbst

Jörg W. schrieb:
> nicht C-freundliche Bitmasken

=> nicht C-freundlich == schlechtes C == macht man so nicht

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Schaust Du Nur schrieb:
>> nicht C-freundliche Bitmasken
>
> => nicht C-freundlich

Ja.  Von Atmel seinerzeit so vorgegeben, weil der Assembler eben
nicht

SBI PORTB, 0x80

sondern

SBI PORTB, 7

haben möchte.

> macht man so nicht

Ja, genau.

Sag das Atmel.

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.