Forum: Mikrocontroller und Digitale Elektronik Port setzen in Binärschreibweise


von Johannes (menschenskind)


Lesenswert?

Hallo

Nutze die IAR Workbench und wollte soeben beim Setzen eines Ports 
anstatt
1
PORT = 0x0E
 einfach mal
1
PORT = 0b00001110

benutzen, aber da meckerte mir der Compiler rum.
Geht das einfach nur nicht, oder muss ich da bei der Syntax was 
Spezielles beachten?

Danke

von amateur (Gast)


Lesenswert?

Vielleicht kennt der 0b____ nicht, obwohl mittlerweile recht geläufig.

von Cyblord -. (cyblord)


Lesenswert?

Ich hätte da eine etwas unkonventionelle, ja gerade zu verrückte Idee: 
Sieh doch mal in der Doku zu deinem Compiler nach. Oder ist dir das zu 
crazy?

von amateur (Gast)


Lesenswert?

Ich sehe es erst jetzt:
Muss es nicht PORTA, PORTB oder so heißen?

von Cyblord -. (cyblord)


Lesenswert?

amateur schrieb:
> Ich sehe es erst jetzt:
> Muss es nicht PORTA, PORTB oder so heißen?

Du weißt doch nicht mal um welchen Controller es geht. Spielt für die 
Frage auch keine Rolle. Außerdem kann er seine Variablen und Makros 
nennen wie er will.

von Peter D. (peda)


Lesenswert?

Johannes Hofmann schrieb:
> aber da meckerte mir der Compiler rum.

Aha, die Fehlermeldung lautet also:
"main.c:19: error: Der Compiler meckert rum"

Noch nie was von Copy&Paste gehört?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Johannes Hofmann schrieb:
> PORT = 0b00001110

Abgesehen davon, daß Du vermutlich PORTF meinst, und das Semikolon am 
Zeilenende vergessen haben wirst:

In C gibt es keine "Binärschreibweise". Das "0b"-Präfix ist eine 
proprietäre Erweiterung mancher Compiler -- und sollte daher 
vermieden werden.

von Johannes (menschenskind)


Lesenswert?

Das PORT hatte ich mir vorher definiert und das Semikolon vergess ich 
gerne mal. :) Denn es ist halt nur semi-cool...

Danke für die Erleuchtung

von Dennis (Gast)


Lesenswert?

Die Binärschrbeiweise kennt IAR nicht. Aber du kannst dir auf der 
Homepgae Files runterladen, in denen die Makros für 8, 16 und 32 Bit 
definiert sind. Musste nur einbinden, dann geht es. Sparste dir das 
selber anlegen der 65536 Makros bei 16Bit... vielleicht war ja auch 
32Bit dabei :-) ?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dennis schrieb:
> Aber du kannst dir auf der Homepgae Files runterladen, in denen die
> Makros für 8, 16 und 32 Bit definiert sind.

Man könnte sich ja auch mal drei Tage nacheinander jeweils 10 Minuten 
lang hinsetzen und die 16 Bitwerte für ein Nibble lernen.

Dann kann man Hexzahlen lesen, und muss nicht auf fehlerträchtige 
Binärdarstellungen ausweichen.

Fehlerträchtig, ja:

0b000010000000001 ist halt nicht das gleiche wie 0b0000100000000001.

Da muss man schön viele Nullen zählen, um den Unterschied zu sehen.

0x0401 und 0x0801 sind irgendwie auffälliger unterschiedlich, nicht?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Such im Netz nach
1
c binary constants macro

Da findest du entsprechende Makros zur Umrechnung. Man braucht übrigens 
für 16-Bit-Konstanten keine 2**16 Makros, ein einziges genügt schon.

Aber wie schon geschrieben wurde: Binärkonstanten bringen mehr Nachteile 
als Vorteile, und kein halbwegs erfahrener Embedded-Programmierer will 
sie. Deswegen sind sie nicht einmal im allerneuesten C-Standard (C11) 
vorgesehen.

Hexadezimal- und (in selteneren Fällen) Oktaldarstellung sind vollkommen 
ausreichend.

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


Lesenswert?

Yalu X. schrieb:
> Aber wie schon geschrieben wurde: Binärkonstanten bringen mehr Nachteile
> als Vorteile, und kein halbwegs erfahrener Embedded-Programmierer will
> sie.

Naja.  Man soll nie „nie“ sagen … ich habe sie auch schon benutzt:
1
/*
2
 * Diagnostic patterns.
3
 */
4
static const segment_bits sbits[] PROGMEM =
5
{
6
  //         a    aaaaaaaa    aaaa        aaaaaaaa    aaaaa
7
  //    aaaaa1    11112222    2333   a    33322222    11111aaa
8
  //  xx135791    35791357    9135xxx2    42086420    86420864
9
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 }, /* all off */
10
  { 0b00111111, 0b11111111, 0b11110001, 0b11111111, 0b11111111 }, /* all on */
11
  { 0b00000000, 0b00000000, 0b00000001, 0b11111111, 0b11111111 }, /* checker */
12
  { 0b00111111, 0b11111111, 0b11110000, 0b00000000, 0b00000000 }, /* checker */
13
14
  { 0b00100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 }, /* 1 */
15
  { 0b00000000, 0b00000000, 0b00000001, 0b00000000, 0b00000000 },
16
  { 0b00010000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
17
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001 },
18
  { 0b00001000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
19
20
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000010 }, /* 6 */
21
  { 0b00000100, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
22
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000100 },
23
  { 0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
24
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001000 },
25
26
  { 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00000000 }, /* 11 */
27
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000 },
28
  { 0b00000000, 0b10000000, 0b00000000, 0b00000000, 0b00000000 },
29
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00100000 },
30
  { 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00000000 },
31
32
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000 }, /* 16 */
33
  { 0b00000000, 0b00100000, 0b00000000, 0b00000000, 0b00000000 },
34
  { 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b10000000 },
35
  { 0b00000000, 0b00010000, 0b00000000, 0b00000000, 0b00000000 },
36
  { 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0b00000000 },
37
38
  { 0b00000000, 0b00001000, 0b00000000, 0b00000000, 0b00000000 }, /* 21 */
39
  { 0b00000000, 0b00000000, 0b00000000, 0b00000010, 0b00000000 },
40
  { 0b00000000, 0b00000100, 0b00000000, 0b00000000, 0b00000000 },
41
  { 0b00000000, 0b00000000, 0b00000000, 0b00000100, 0b00000000 },
42
  { 0b00000000, 0b00000010, 0b00000000, 0b00000000, 0b00000000 },
43
44
  { 0b00000000, 0b00000000, 0b00000000, 0b00001000, 0b00000000 }, /* 26 */
45
  { 0b00000000, 0b00000001, 0b00000000, 0b00000000, 0b00000000 },
46
  { 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b00000000 },
47
  { 0b00000000, 0b00000000, 0b10000000, 0b00000000, 0b00000000 },
48
  { 0b00000000, 0b00000000, 0b00000000, 0b00100000, 0b00000000 },
49
50
  { 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000 }, /* 31 */
51
  { 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b00000000 },
52
  { 0b00000000, 0b00000000, 0b00100000, 0b00000000, 0b00000000 },
53
  { 0b00000000, 0b00000000, 0b00000000, 0b10000000, 0b00000000 },
54
  { 0b00000000, 0b00000000, 0b00010000, 0b00000000, 0b00000000 },
55
};

Wäre hexadezimal nicht so übersichtlich.

> Deswegen sind sie nicht einmal im allerneuesten C-Standard (C11)
> vorgesehen.

Das ist eher Ignoranz des C-Standard-Gremiums gegenüber popeligen
Embedded-Programmierern.  Im C99 Rationale steht dazu lapidar, dass
der entsprechende Vorschlag “due to lack of precedence and
application” nicht mit aufgenommen worden war.  Nun, da GCC das
offziell übernommen hat, können sie zumindest keinen “lack of
precedence” mehr konstatieren, wenn das mal wieder jemand aufs
Tablett legt.

von Reinhard Kern (Gast)


Lesenswert?

Yalu X. schrieb:
> Da findest du entsprechende Makros zur Umrechnung. Man braucht übrigens
> für 16-Bit-Konstanten keine 2**16 Makros, ein einziges genügt schon.

Das ist ok, es gibt aber auch Lösungen im Netz per h.file, da werden 256 
Konstanten definiert - aber dann muss man sich ganz genau an die 
Schreibweise halten, und 16 Bit gibts eh nicht.

Gruss Reinhard

von Yalu X. (yalu) (Moderator)


Lesenswert?

Jörg Wunsch schrieb:
> Wäre hexadezimal nicht so übersichtlich.

Mag sein. Allerdings (vielleicht liegt an meinen Augen) fällt es mir 
schwer, mit einem Blick zu erkennen, wo denn nun überall die 1-Bits 
sind. Insofern ist der Vorteil für mich persönlich eher gering, da ich, 
um diese Bitmuster zu verstehen, sowieso Zeile für Zeile abscannen 
müsste.

Man könnte das Ganze auch ohne Verwendung von Binär- und Hexzahlen so 
schreiben:
1
#define BITS(b) {       \
2
  (uint8_t)((b) >> 32), \
3
  (uint8_t)((b) >> 24), \
4
  (uint8_t)((b) >> 16), \
5
  (uint8_t)((b) >>  8), \
6
  (uint8_t)((b) >>  0) }
7
8
#define BIT(n)           BITS(1ULL << (n))
9
#define BIT_RANGE(b, n)  (((1ULL << n) - 1) << b)
10
11
#define BITS_NONE        BIT_RANGE( 0,  0)
12
#define BITS_ALL_EVEN    BIT_RANGE( 0, 17)
13
#define BITS_ALL_ODD     BIT_RANGE(20, 18)
14
#define BITS_ALL         (BITS_ALL_EVEN | BITS_ALL_ODD)
15
16
static const segment_bits sbits[] PROGMEM = {
17
  BITS(BITS_NONE),     BITS(BITS_ALL),
18
  BITS(BITS_ALL_EVEN), BITS(BITS_ALL_ODD),
19
  BIT(37), BIT(16),
20
  BIT(36), BIT( 0),
21
  BIT(35), BIT( 1),
22
  BIT(34), BIT( 2),
23
  BIT(33), BIT( 3),
24
  BIT(32), BIT( 4),
25
  BIT(31), BIT( 5),
26
  BIT(30), BIT( 6),
27
  BIT(29), BIT( 7),
28
  BIT(28), BIT( 8),
29
  BIT(27), BIT( 9),
30
  BIT(26), BIT(10),
31
  BIT(25), BIT(11),
32
  BIT(24), BIT(12),
33
  BIT(23), BIT(13),
34
  BIT(22), BIT(14),
35
  BIT(21), BIT(15),
36
  BIT(20) 
37
};

Für meine (schlechten) Augen wird dadurch auch die Systematik etwas auch 
deutlicher.

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


Lesenswert?

Yalu X. schrieb:
> Für meine (schlechten) Augen wird dadurch auch die Systematik etwas auch
> deutlicher.

Ja, das ist gut zu lesen.

Der wesentliche Punkt der Binärschreibweise war, dass ich von den
Kommentaren darüber ausgehend die Einsen gesetzt habe.  Also erstmal
im Editor ein Array angelegt, in dem alle Konstanten als 0b00000000
drin standen, und dann Zeile für Zeile die Einsen entsprechend der
Anodenreihenfolge (es geht um eine VFD-Ansteuerung) im Kommentar
gesetzt.

Es ging also eher um Schreibbarkeit denn Lesbarkeit. ;-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Jörg Wunsch schrieb:
> Es ging also eher um Schreibbarkeit denn Lesbarkeit. ;-)

Ok :)

Die Binärschreibweise ist aus dem gleichen Grund auch ganz praktisch zur 
Definition von Zeichensätzen für Matrix-Displays. Besser lesbar wäre das 
Ganze allerdings, wenn man statt 0b11001010 auch 0b11__1_1_ o.ä. 
schreiben könnte.

In C++ kann man auch ein Stringliteral (z.B. "##--#-#-") von einem Makro 
in eine Integerzahl umwandeln lassen. In C geht das leider (noch) nicht, 
weil dort "##--#-#-"[3] nicht als konstanter Ausdruck angesehen wird.

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


Lesenswert?

Yalu X. schrieb:
> Besser lesbar wäre das Ganze allerdings, wenn man statt 0b11001010 auch
> 0b11__1_1_ o.ä. schreiben könnte.

Ja, das würde auch bei langen Dezimalzahlen zuweilen helfen. Statt
14745600 also 14_745_600.

Wer formuliert den Vorschlag für die WG14? ;-)

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.