Mikrocontroller und Digitale Elektronik
›
Thread
Unterstützung C Code + union
ZR
Zo R.
(hsch1978)
OP
15.05.2023 10:53
#7413842
Hallo und guten Morgen,
für meine Mikrocontroller Anwendung habe ich folgendes Problem vorliegen:
Ich habe als Eingangsparameter ein union. Dieses union besteht aus 8 Bit (uint8_t). Jedes Bit steht für ein bestimmtest Symbol.
Nun soll dieser union Wert verwendet werden, um die entsprechenden Symbole auf dem Display darzustellen.
1
typedef union
2
{
3
uint8_t rawByte ;
4
struct
5
{
6
uint8_t date : 1 ;
7
uint8_t warning : 1 ;
8
uint8_t lowBattery : 1 ;
9
uint8_t temp : 1 ;
10
uint8_t pressure : 1 ;
11
} st_displaySymbols ;
12
} un_displaySymbols ;
Für die Darstellung eines Symbols wird eine Funktion verwendet:
1
typedef enum
2
{
3
DISPLAY_SYMBOL_DATE ,
4
DISPLAY_SYMBOL_WARNING ,
5
DISPLAY_SYMBOL_LOW_BATTERY ,
6
DISPLAY_SYMBOL_TEMP ,
7
DISPLAY_SYMBOL_PRESSURE ,
8
} en_displaySymbols ;
1
void Display_SetSymbol ( en_displaySymbols symbol , bool on )
Und was ist jetzt deine Frage?
Ein Switch-Case über alle Elemente:
1
switch ( symbol )
2
{
3
case DISPLAY_SYMBOL_DATE : if ( symbol . date ) {...} else {...} break ;
4
case DIS ...
5
}
symbol.date --> union_symbol.st_displaySymbols.date
ZR
Zo R.
(hsch1978)
OP
15.05.2023 11:04
#7413856
Ist schwer das zu formulieren. Ich versuche es mal.
Ich erhalte einen 8 Bit Wert. In diesen 8 Bits entspricht dann jedem Bit ein bestimmtes Symbol. Nun soll in der Weiterverarbeitung die Symbole auf das Display angezeigt werden. Ein einzelnes Symbol zu aktivieren auf dem Display ist kein Problem. Wenn ich aber einen 8 Bit Wert habe, wo jedes Bit einem Symbol entspricht, das bereitet mir Probleme wie ich das in Software umsetzen könnte.
Beispiel:
uin8_t = 0xA0 ==> bit: 1010 0000
Hier soll das entsprechende Symbol von der Bitstelle 7 und auch von der Bitstelle 5 auf dem Display dargestellt werden. Alle anderen Symbol sollen nicht angezeigt werden.
PD
Peter D.
(peda)
15.05.2023 11:05
#7413858
Das Problem bei Bit-structs ist, die Order ist nicht eindeutig definiert.
Daher bevorzugt man oft Bitmasken (0x01, 0x02, .. 0x80).
Und wenn man nicht wirklich mit RAM knausern muß, nimmt man für jedes Bit einfach ein Byte.
1
uint8_t batt_status [ 5 ];
He S. schrieb:
Wenn ich aber einen 8 Bit Wert habe, wo
jedes Bit einem Symbol entspricht, das bereitet mir Probleme wie ich das
in Software umsetzen könnte.
https://www.mikrocontroller.net/articles/Bitmanipulation#Standard-C_4
Oliver
ZR
Zo R.
(hsch1978)
OP
15.05.2023 11:14
#7413865
Danke.
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
He S. schrieb:
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
Dann such dir halt eine passende Programmiersprache, in der du das kannst.
Oliver
He S. schrieb:
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
Wird so nicht möglich sein.
Ausser du machst eine switch case mit 256 cases. Aber das macht man so nicht und auf die Idee würde auch keiner kommen.
Prüfe das jeweilige Bit und gut ist.
PD
Peter D.
(peda)
15.05.2023 11:32
#7413882
He S. schrieb:
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
Das geht nicht.
Switch/Case kann immer nur eine Auswahl treffen, d.h. es darf immer nur ein Bit gleichzeitig gesetzt sein.
He S. schrieb:
Hallo und guten Morgen,
für meine Mikrocontroller Anwendung habe ich folgendes Problem
vorliegen:
Ich habe als Eingangsparameter ein union. Dieses union besteht aus 8 Bit
(uint8_t). Jedes Bit steht für ein bestimmtest Symbol.
Nun soll dieser union Wert verwendet werden, um die entsprechenden
Symbole auf dem Display darzustellen.
Evtl. so:
1
un_displaySymbols v = ...;
2
Display_SetSymbol ( DISPLAY_SYMBOL_DATE , v . st_displaySymbols . date == 1 );
3
Display_SetSymbol ( DISPLAY_SYMBOL_WARNING , v . st_displaySymbols . warning );
4
// ...
Ich nehme an, dass Du immer einen vollständige Zustandsupdate benötigst.
Ich hoffe, dir ist bewusst, dass das Dekodieren einer Leitungscodierung mit Hilfe einer union ein wenig gute Idee ist.
Du kannst den Namen der struct in der union auch weglassen, dann geht es eleganter:
1
un_displaySymbols v = ...;
2
Display_SetSymbol ( DISPLAY_SYMBOL_DATE , v . date == 1 );
3
Display_SetSymbol ( DISPLAY_SYMBOL_WARNING , v . warning );
4
// ...
ZR
Zo R.
(hsch1978)
OP
15.05.2023 13:02
#7413938
Hallo Wilhelm was meinsrt du mit ohne struct?
He S. schrieb:
Hallo Wilhelm was meinsrt du mit ohne struct?
Den Namen(!) des struct weglassen, wie geschrieben. Also so:
1
typedef union
2
{
3
uint8_t rawByte ;
4
struct
5
{
6
uint8_t date : 1 ;
7
uint8_t warning : 1 ;
8
uint8_t lowBattery : 1 ;
9
uint8_t temp : 1 ;
10
uint8_t pressure : 1 ;
11
};
12
} un_displaySymbols ;
P.S.: Der Präfix "un_" ist unnötig im Typ-Namen.
He S. schrieb:
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
Kein Problem. Prüfe immer das letzte gesetzte Bit ( (n&~(n-1)) , "position of rightmost bit"), mache eine Schleife über die Switch-Case und lösch am Ende des Schleifendurchlaufs die schon behandelten Bits.
PD
Peter D.
(peda)
15.05.2023 13:59
#7413983
Walter T. schrieb:
mache eine Schleife über die Switch-Case
Quasi nen Knopf an die Backe nähen.
Peter D. schrieb:
Walter T. schrieb:
mache eine Schleife über die Switch-Case
Quasi nen Knopf an die Backe nähen.
.. und sich dabei dann von hinten durch die Brust ins Auge und dann ins Knie schießen.
Oliver
Peter D. schrieb:
Quasi nen Knopf an die Backe nähen.
Jupp. Wobei ich das weniger sinnlos auch schon für einen primitiven priorisierten Scheduler genau so gemacht habe.
Aber der TO wollte doch unbedingt Switch/Case!
Es würde mich noch nicht einmal wundern, wenn der Optimizer daraus durch loop unrollig wieder eine Reihe von if( byte & (1<<bit) ){} machen würde.
M
Monk
Gast
15.05.2023 15:22
#7414027
He S. schrieb:
Ich würde es trotzdem gerne irgendwie mit switch case lösen.
Switch/case benutzt man für entweder/oder Szenarien. Bei dir können aber mehrere Flags gleichzeitig an sein.
ZR
Zo R.
(hsch1978)
OP
15.05.2023 15:23
#7414030
Ich habe es ohne switch/case realisiert. Ich übergebe der Funktion den Wert von der union.
1
typedef union
2
{
3
uint8_t rawByte ;
4
struct
5
{
6
uint8_t date : 1 ;
7
uint8_t warning : 1 ;
8
uint8_t lowBattery : 1 ;
9
uint8_t temp : 1 ;
10
uint8_t pressure : 1 ;
11
};
12
} un_displaySymbols ;
13
14
un_displaySymbols displaySymbols ;
15
16
displaySymbols = incomming_data ;
17
18
Display_SetSymbol ( DISPLAY_SYMBOL_DATE , displaySymbols . date );
19
Display_SetSymbol ( DISPLAY_SYMBOL_WARNING , displaySymbols . warning );
20
...
21
...
He S. schrieb:
Ich habe es ohne switch/case realisiert.
Das ist die Lösung, die ich oben beschrieben habe.
Ich übergebe der Funktion den
Wert von der union.
Nicht ganz: Du benutzt eine impl. Typkonversion.
Es ist besser, wenn die Elemente des struct, die ja eigentlich Bool'sch sind, auch als solche deklariert werden.
Und wie gesagt: die Namen Deine DT sind Mist.
He S. schrieb:
un_displaySymbols displaySymbols;
displaySymbols = incomming_data;
Das schreibt man so:
1
const un_displaySymbols displaySymbols = incomming_data ;
Ich denke, Dir ist dann auch klar, warum.
Ich würde das so machen:
1
#define USED_BITS 5
2
3
// Bit 0
4
void date ( uint8_t val )
5
{
6
7
}
8
9
// Bit 1
10
void warning ( uint8_t val )
11
{
12
13
}
14
15
// Bit 2
16
void lowBattery ( uint8_t val )
17
{
18
19
}
20
21
// Bit 3
22
void temp ( uint8_t val )
23
{
24
25
}
26
27
// Bit 4
28
void pressure ( uint8_t val )
29
{
30
31
}
32
33
const void ( * func [ USED_BITS ])( uint8_t val ) =
34
{
35
date ,
36
warning ,
37
lowBattery ,
38
temp ,
39
pressure
40
};
41
42
process_RawByte ( uint8_t byte )
43
{
44
for ( int i = 0 ; i < USED_BITS ; i ++ )
45
{
46
func [ i ]( byte & 1 );
47
byte = byte >> 1 ;
48
}
49
}
ZR
Zo R.
(hsch1978)
OP
16.05.2023 09:59
#7414608
Hallo Wilhelm M.,
wie kann ich die union mit boolsche Werte verändern?
He S. schrieb:
Hallo Wilhelm M.,
wie kann ich die union mit boolsche Werte verändern?
Du änderst den DT der Elemente von uint8_t zu bool.
ZR
Zo R.
(hsch1978)
OP
16.05.2023 10:29
#7414634
1
typedef union
2
{
3
uint8_t rawByte ;
4
struct
5
{
6
bool date ;
7
bool warning ;
8
bool lowBattery ;
9
bool temp ;
10
bool pressure ;
11
};
12
} un_displaySymbols ;
Das mit bool lässt der Compiler zu. Nur das mit der uint8_t Variable funktioniert nicht mehr. Diese ist aber schon für mich notwendig.
IW
Irgend W.
(irgendwer)
(Firma: egal)
16.05.2023 10:40
#7414651
He S. schrieb:
Nur das mit der uint8_t Variable
funktioniert nicht mehr.
Achtung, C kennt keine echten Bit-Typen. Ein "bool" wird intern als "int" verarbeitet. Je nach System hast du jetzt also "5 x 16Bit" oder "5 x 32Bit".
He S. schrieb:
Das mit bool lässt der Compiler zu. Nur das mit der uint8_t Variable
funktioniert nicht mehr. Diese ist aber schon für mich notwendig.
Geht mit >= C11. Du solltest ggf. den C-Standard angeben mit -std=c11 oder c17 oder c23.
Nennt sich unnamed Union member.
ZR
Zo R.
(hsch1978)
OP
16.05.2023 10:53
#7414661
Ok diesen Standard nutzen wir nicht.
Wir nutzen ISO C99.
PD
Peter D.
(peda)
16.05.2023 10:55
#7414664
Der AVR-GCC reserviert für bool Variablen 1 Byte.
Irgend W. schrieb:
Achtung, C kennt keine echten Bit-Typen.
Eben. Das noch kombiniert mit Bitfeldern, welche in C weder plattformkapatibel noch sonstwas sind, setzt dem Ganzen noch die Krone auf. Man handelt sich ein Problem nach dem nächsten ein.
Meines Erachtens sind Bitfelder in C überflüssig. Man kann das auch klassisch aufziehen:
1
uint8_t symbol_mask ;
2
3
#define DISPLAY_SYMBOL_DATE_MASK 0x01
4
#define DISPLAY_SYMBOL_WARNING_MASK 0x02
5
#define DISPLAY_SYMBOL_LOW_BATTERY_MASK 0x04
6
#define DISPLAY_SYMBOL_TEMP_MASK 0x08
7
#define DISPLAY_SYMBOL_PRESSURE_MASK 0x10
Rest siehe auch Artikel Bitmanipulation .
He S. schrieb:
Ok diesen Standard nutzen wir nicht.
Wir nutzen ISO C99.
Wir???? Das alles hört sich sehr nach Hobbygekruschtel an...
Na dann, Gib dem struct wieder einen Namen...
Frank M. schrieb:
Das noch kombiniert mit Bitfeldern, welche in C weder plattformkapatibel
noch sonstwas sind, setzt dem Ganzen noch die Krone auf. Man handelt
sich ein Problem nach dem nächsten ein.
Das habe ich ihm schon gaaaanz oben gesagt. Er hat es ignoriert.
He S. schrieb:
Nur das mit der uint8_t Variable
funktioniert nicht mehr. Diese ist aber schon für mich notwendig.
Dann mach es doch so, wie ich das gestern bereits vorgeschlagen hab:
Beitrag "Re: Unterstützung C Code + union"
Viel eleganter wirst du das in klassischem C kaum hinbekommen.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren