mikrocontroller.net

Forum: Compiler & IDEs boolsche Variable


Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute.
Es gab mal sowas schönes wie boolsche Variable.
Man hat eine Variable, nennen wir sie "test" vom typ boolean
deklariert.
Dann konnte man test := true oder test := false setzen oder
zurücksetzen und mit if(test)  zb für einen Vergleich heranziehen.
Die Frage: Wenn ich ein Bit z.B. PORTD,PD7 so z.B. durch eine define
"vorbereiten", dass es genau so funktioniert, wie "test", wenn wir
mal davon ausgehen das die Zuweisung über = erfolgt und der Vergleich
über ==

Autor: Christoph __ (chris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In C geht das (soweit ich weiß) mangels Operatorüberladung nicht. Du
müsstest also auf (mehrere) Makros ausweichen.

In C++ könnte man zum Beispiel eine Klasse schreiben, die die von dir
verlangten Operatoren überlädt.

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

Bewertung
0 lesenswert
nicht lesenswert
> Es gab mal sowas schönes wie boolsche Variable.

Gibt's in C99 übrigens auch.  Anders als in C++ (wo es ein
Standardtyp
ist) muss man in C #include <stdbool.h> machen, danach hat man den Typ
"bool" und die Werte "false" und "true" definiert.

> Die Frage: Wenn ich ein Bit z.B. PORTD,PD7 so z.B. durch eine define
> "vorbereiten", dass es genau so funktioniert, wie "test", wenn
wir
> mal davon ausgehen das die Zuweisung über = erfolgt und der
Vergleich
> über ==

Du meinst sowas?

#define PORTTEST (PIND & _BV(PD7))

...
  if (PORTTEST) {
    ...
  }

(Ich nehme mal an, du wolltest PIND testen und nicht PORTD. ;-)

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (Ich nehme mal an, du wolltest PIND testen und nicht PORTD. ;-)

Ach ja, da war ja noch was. Ich gebe zu das Beispiel ist schlecht
gewählt. Ich dachte mir es wäre allgemeinverständlicher als
GPIOR2,GPIOR04.

mir schwebte etwas in der Art
 #define?? transmitter_online ??? (GPIOR2,GPIOR04)

if ("ankommende Daten ok") transmitter_online = true; (1) else
transmitter_online = false;

if (transmitter_online) { "Mach was "}

geht sowas und wenn ja, wie?

Autor: Christoph __ (chris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> geht sowas und wenn ja, wie?

Wie oben geschrieben, mit C geht das nicht.
Der Zuweisungsoperator hat in C eine genau festgelegte Bedeutung. Da es
keine "1-Bit-Variable" gibt (zumindest keinen Zeiger darauf), kann man
nur mit dem Zuweisungsoperator allein kein einzelnes Bit verändern.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein kleines Beispiel, wie es doch funktionieren könnte!
In wie weit das aber Portabel ist, kann ich nicht sagen. Die Idee kam
mir ganz spontan, als ich mich an einen anderen Thread erinnerte.
#include <avr/io.h>
#include <stdbool.h>

typedef struct
IOPort8Bit_s {
        unsigned char pin0:1;
        unsigned char pin1:1;
        unsigned char pin2:1;
        unsigned char pin3:1;
        unsigned char pin4:1;
        unsigned char pin5:1;
        unsigned char pin6:1;
        unsigned char pin7:1;
} IOPort8Bit_t;

IOPort8Bit_t *porta_mirr = (IOPort8Bit_t *)(&PORTA);
IOPort8Bit_t *pina_mirr = (IOPort8Bit_t *)(&PINA);

int
main(void)
{
        DDRA = 0xff;

        porta_mirr->pin1 = true;
        porta_mirr->pin2 = false;
        
        for(;;)
        {
                /* if(pina_mirr->pin1) or: */
                if(pina_mirr->pin1 == true)
                {
                        porta_mirr->pin0 ^= 1;
                }
        }

        /* NEVEREACHED */
        return 1;
}

Autor: Andreas Fertl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest doch auch eine Variablen einen Typedef machen.
typedef unsigned char Bool;      /* Boolean */
#define TRUE 1
#define FALSE !TRUE

So kannst du dann mit
Bool test;
eine "Boolsche" Variable deklarieren, die sich auch so verhält, nur
nicht 1 Bit belegt.

if (test)

Falls dann test==TRUE geht er rein, sonnst nicht.

Grüße Andreas

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darum geht es ja nicht, er möchte definitiv nur ein Bit einer Variablen
manipulieren...

Autor: ---- __ (quaddash)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Detail am Rande. Ich glaube nicht, daß man so:
#define TRUE 1
#define FALSE !TRUE
True und False definieren sollte.

Besser ist:
#define TRUE (1==1)
#define FALSE (1==0)
somit wird TRUE und FALSE genauso definiert wie der Compiler selbst
intern auch die Werte darstellt.

Autor: Andreas Fertl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ok, falsch verstanden... :)

Wenn ich soetwas benötige verwende ich auch einen sturct, wie schon
oben beschrieben.

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

Bewertung
0 lesenswert
nicht lesenswert
Ist alles Quark. :-)

Unter C99 nimmt man eh' <stdbool.h> (und schreibt boot, true, und
false, also alles klein).

Ansonsten kannst du in de.comp.lang.c nachfragen, warum die
sinnvollsten Definitionen

#define TRUE 1
#define FALSE 0

heißen.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
< er möchte definitiv nur ein Bit einer Variablen
manipulieren...

Das ist nicht ganz richtig. Er möchte ein Bit eines Registers
abfragen oder manipulieren, aber nicht 3 Makros dafür benutzen
#define checktransmitter checkbit(
#define transmitter_online setbit(
#define transmitter_offline clearbit(

sondern nur transmitter dem Register ... zuweisen

und dann mit transmitter = true / transmitter = false oder
if(transmitter)

manipulieren

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, gut, dann kommt jetzt die Preisfrage an Dich:

  Was passiert in dem von mir eingefügten Code?

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@
Hab ich gesagt, dass Dein Code schlecht, oder falsch ist?
Sieht klassse aus und von dem was ich so davon verstehe, wird er
sicherlich auch funktionieren. Ist zwar viel zu kompliziert für mich
aber bestimmt ok.

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

Bewertung
0 lesenswert
nicht lesenswert
> Was passiert in dem von mir eingefügten Code?

Er wird nicht garantiert funktionieren, weil du das volatile
vergessen hast. ;-)  IO-Register (die ja intern erstmal wie
Speicheradressen behandelt werden) müssen volatile sein.

Ansonsten ist ein bit field durchaus eine Möglichkeit dafür, ja.
Allerdings verliert der Compiler durch die zusätzlich eingefügten
Pointervariablen den Überblick, dass es sich um IO-Register handelt,
sodass er keine IO-Befehle mehr optimieren kann (IN, OUT, SBI, ...).
Besser ist daher
#define porta_mirr  ((volatile IOPort8Bit_t *)(&PORTA))
#define pina_mirr   ((volatile IOPort8Bit_t *)(&PINA))

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hab ich gesagt, dass Dein Code schlecht, oder falsch ist?

Nein, hast Du nicht.
Bitte nicht gleich wieder unter die Decke gehen ;)

Ich passe den Code mal ein bißchen auf Deine spärlichen Angaben an,
damit Du das evtl. besser verstehst:
#include <avr/io.h>
#include <stdbool.h>

typedef struct
Register8Bit_s {
        unsigned char flag1:1;       /* irgendein flag      */
        unsigned char flag2:1;       /* irgendein flag      */
        unsigned char transmitter:1; /* transmitter ein/aus */
        unsigned char receiver:1;    /* receiver ein/aus    */
} Register8Bit_t;

Register8Bit_t reg;                  /* 'Register' anlegen  */

int
main(void)
{
        reg.transmitter = true;
        reg.receiver = false;
        
        for(;;)
        {       /* Endlosschleife */
                if(reg.flag1 == true)
                {       /* wenn flag1 gesetzt dann */
                        reg.flag2 ^= 1; /* toggle das andere */
                }
        }

        /* NEVEREACHED */
        return 1;
}

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oha, wie peinlich!

Jörg hat natürlich völlig Recht. Ich habe das 'volatile' auch im
zweiten Code vergessen. Vermutlich würde im 2. Code einfach so ziemlich
alles wegoptimiert...

So wäre besser:
volatile Register8Bit_t reg;         /* 'Register' anlegen  */

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@OldBug
Das Beispiel ist mir schon in gewisser Weise klar.
Ich muss halt etwas mit dem Speicher geizen, darum möchte ich keine 8
Bit für einen boolschen Operanden verschwenden.
Natürlich kann ich das ganze Register so bitweise belegen, aber ich
komme mit den Structs nicht so gut klar und dann auch noch ein volatile
...
Das durchschaue ich nicht mehr und da inzwischen einfache if-Abfragen
den größten Wahnsinn anzetteln und mich in stundenlange Fehlersuche
verwickeln, will ich es nicht mit Dingen schmücken, die ich
anschließend nicht mehr kurz auflösen kann um Fehler einzugrenzen.
Ich werd es mir auf jeden Fall ausdrucken und für die nächste Version
vormerken, weil es zimlich gut aussieht,

nur...
wo ist der Punkt an dem ich "reg" dem GPIOR2 (das Register) zuweise?

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, ok, ich wusste, daß ich was vergessen/übersehen hatte :-)

In Zeile 12:
Ersetze diese Zeile durch
#define reg ((volatile Register8Bit_t *)(&GPIOR2))

Das kostet Dich kein einziges Bit mehr Speicher.
'reg' kannst Du natürlich nach Lust und Laune umbenennen, so lange Du
 keinen bereits vergebenen 'Namen' auswählst.

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Code von OldBug; ich kann mich noch daran erinnern, daß die
Reihenfolge der Bits abhängig vom Compiler ist. Die Reihenfolge ist im
C-Standard leider nicht festgelegt.

ciao, Stefan.

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.