Forum: Mikrocontroller und Digitale Elektronik Hi-Tech C spezifisches union/struct


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hi,

ich habe folgendes defniert:
1
union{
2
    volatile struct{
3
   unsigned         :2;
4
   unsigned  white:1;
5
   unsigned  red:1;
6
   unsigned  blue:1;
7
   unsigned  green:1;
8
   unsigned  violett:1;//Magenta
9
   unsigned  yellow:1;
10
}bits;
11
unsigned int all;
12
}ColorPick;

und führe dann später folgendes aus:
1
//6 Farben
2
    for (; temp > 0; temp--)
3
    {
4
        ColorPick.all >> 1;
5
6
        if (ColorPick.all < 4)
7
            ColorPick.all = 0b10000000;
8
    }
9
    set_pwm((ColorPick.bits.white | ColorPick.bits.red | ColorPick.bits.violett) ? 255 : 0,
10
            (ColorPick.bits.white | ColorPick.bits.green) ? 255 : 0,
11
            (ColorPick.bits.white | ColorPick.bits.blue | ColorPick.bits.violett) ? 255 : 0, 255);


Kurze Erklärung dazu, was ich eingentlich bewecken möchte.
Ich benötige etwas ähnliches wie ein BOOL[6], bei dem immer nur EIN 
Eintrag TRUE ist und dieser mittels Schleife weitergeschoben wird. 
Möchte aber gerne die einzelnen Bits benennen können. Des Weiteren 
befinde ich mich auf einem PIc und möchte nicht 6x uint8_t verschwenden.

Laut Compilerhandbuch ist die erste variable im struct das LSB. Da ich 
nur 6 benötige lasse ich ab dem vorletztem LSB "resetten".

Um ein Shift ausfüren zu dürfen, musste ich noch das Union drumherum 
basteln.

Nun die Frage an euch: Geht es auch schöner und kompakter?

In jedem Fall möchte ich "red" etc. noch lesen können. ColorPick >> x 
wäre auch schön, aber ich sehe keinen Weg das Union zu umgehen und ein 
Shift direkt auf das struct machen zu dürfen.

Grüße Oekel

: Verschoben durch Moderator
von Steffen (Gast)


Lesenswert?

Hallo Oekel,

mal als Nachfrage: Du brauchst ein bool[6] bei dem immer nur ein Eintrag 
true ist?! Das heißt es gibt genau 6 Zustände? Habe ich sicherlich iwie 
falsch verstanden, denn das wäre einfach ein Zähler 0..5 (oder enum, 
wenn Du Namen haben möchtest) mit Inkrement und Wrap Around.

Grüße, Steffen

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Steffen schrieb:

> ...denn das wäre einfach ein Zähler 0..5 (oder enum,
> wenn Du Namen haben möchtest) mit Inkrement und Wrap Around.

Kannst du mir kurz ein Bsp. geben, wie du das Wrapping meinst?
Ansonsten hast du recht, habs wieder viel zu kompliziert angegangen.

Aber bekomme ich damit dann auch eine Bitmaske a la 001000, die ich dann 
über die Farben legen kann?

Grüße

von Steffen (Gast)


Lesenswert?

Hallo Oekel,

(1) Der Wraparound (also bspw. 5+1 auf 0) passiert einfach per Modulo.

i = (i+1) % 6 ;

(2) In Deinem Beispiel sehe ich den einzigen Funktionsaufruf in 
set_pwm() mit drei variablen Argumenten die entweder 255 oder 0 sind. 
Und einen Ausdruck wie

(ColorPick.bits.white | ColorPick.bits.green) ? 255 : 0

ersetzt Du durch

(i == white || i == green) ? 255 : 0

wobei die Farbnamen vorher per enum definiert werden.

Grüße, Steffen

von ... (Gast)


Lesenswert?

ColorPick.all >> 1;


cool. Aber nutzlos.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Beim säubern des Codes durch umdeklination diverser Namenskonstrukte, 
bin ich dann doch noch Mal zur Union zurück gekommen.

Liegt es schlichtweg an der 8Bit Architektur, dass ich folgendes nicht 
schreiben darf? Normal ist die Größe einer Union doch durch den Typen 
mit dem meisten Speicherplatzverbrauch vordefiniert. Daher sollte "tmp" 
überflüssig sein. Der Kompiler meckert jedoch in beiden Fällen, dass Bit 
9 und 10 nicht in das Bitfeld passen:
1
union DIPSwitches {
2
    uint16_t tmp;
3
    struct {
4
        unsigned DIP1 : 1;
5
        unsigned DIP2 : 1;
6
        unsigned DIP3 : 1;
7
        unsigned DIP4 : 1;
8
        unsigned DIP5 : 1;
9
        unsigned DIP6 : 1;
10
        unsigned DIP7 : 1;
11
        unsigned DIP8 : 1;
12
        unsigned DIP9 : 1;
13
        unsigned DIP10 : 1;
14
        unsigned : 6;
15
    };
16
    struct {
17
        unsigned all10 : 10;
18
        unsigned : 6;
19
    
20
    struct {
21
        unsigned all6 : 6;
22
        unsigned : 10;
23
    };
24
} DIPs;

Sicher kann ich im ganzen Code uint16_t DIPs = x; z= (DIP & 
0b0000001111111111) usw. schreiben doch fände ich obiges eleganter,
wenn es denn funktioniert ;)

Grüße Oekel

PS: 
http://openbook.galileocomputing.de/c_von_a_bis_z/015_c_strukturen_009.htm 
liegt hier vor, hat jedoch mit Hi-Tech C für PIC wenig gemein.

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.