Hallo Ihr,
ich hab da mal wider ein kleines Problem. Ich hab ein 16 bit großes
struct:
struct {
unsigned char AB : 1 ; // Kanal selektion
unsigned char DC : 1 ; // don't care
unsigned char GA : 1 ; // Gain
unsigned char SHDN : 1 ; // shutdown
unsigned int dac_val : 10 ; // dac value
unsigned char empty : 2 ; // don't care
} mcp4812;
Die ersten 4 bit sind fest:
mcp4812.AB = 0;
mcp4812.DC = 0;
mcp4812.GA = 1;
mcp4812.SHDN = 1;
"dac_val" steht der 10 bit Wert den der ADC ausgeben soll.
Diese 16 bit möchte ich so zerlegen das ich sie über die SPI
Schnittstelle
ausgeben kann. Beim MEGA 328 sind die Register bekanntlich 8 bit breit.
Von daher meine Frage wie zerlege ich den 16 bit "struct" in 2 8 bit
Häpchen die ich augeben kann.
Gruß
Andy
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
je nach dem welchen C dialekt du verwendest musst du dem union ggf. nen namen verpassen. lg
Andreas Geissler schrieb: > Von daher meine Frage wie zerlege ich den 16 bit "struct" in 2 8 bit > Häpchen die ich augeben kann. Die Frage taucht alle 2 Wochen erneut im Forum auf. Kleines Vorgepänkel. So etwas:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
ist meistens EXTREM unklug. Man macht keine anonyme struct! Denn dann kannst du diesen Datentyp zu nichts anderem mehr verwenden und sich im restlichen Code nicht mehr darauf beziehen. Es gibt zwar Ausnahmen, aber die sind rar. Also gib deiner struct einen Namen, und alles ist gut.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Zb kannst du mit einer union das Gewünschte erreichen
1 | |
2 | |
3 | |
4 | |
5 | |
In einer union liegen die Member quasi üereinander, belegen also denselben Speicherbereich. D.h. du kannst über Data den Speicher beschreiben und dir über Bytes denselben Speicher in Byte-Form auslesen.
1 | |
2 | |
3 | |
4 | |
5 | |
Eine andere Möglichkeit wäre es, einen entsprechenden Pointer zurecht zu casten.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
kleine korrektur zu meinem posting oben... dort musst du noch die empty bits aus dem struct streichen, sonst ist der struct 18bit gross lg
Hallo Ihr, danke für die schnelle Antwort. Gruß Andy
Karl Heinz schrieb: > Eine andere Möglichkeit wäre es, einen entsprechenden Pointer zurecht zu > casten. Ich würde genau diese Pointer-Cast-Variante immer dem union-Trick vorziehen. Das mit der union ist ausdrücklich lt. C-Standard nicht garantiert. Mein Rat: Den Tipp mit der union hier im Forum nicht mehr zu geben, sondern stattdessen ausschließlich die Pointer-Variante zu propagieren. Da kommt der Compiler nicht dran vorbei ;-)
Frank M. schrieb: > Karl Heinz schrieb: >> Eine andere Möglichkeit wäre es, einen entsprechenden Pointer zurecht zu >> casten. > > Ich würde genau diese Pointer-Cast-Variante immer dem union-Trick > vorziehen. Das mit der union ist ausdrücklich lt. C-Standard nicht > garantiert. Ich denke es war der C99 Standard (weiss nicht mehr genau), welcher diesen union Trick für chars (und damit auch unsigned chars) legitimiert hat. Zuvor war die Situation so, dass es keinen gerantierten Weg gab, weder durch union, noch durch umcasten von Zeiger-Typen. Denn auch in dem Moment, in dem du einen Pointer Typ umcastest, landest du automatisch in 'undefined behaviour' land. Und wieder (konsequenterweise): einzige Ausnahme: umcasten zu einem char-Pointer. > Mein Rat: Den Tipp mit der union hier im Forum nicht mehr zu geben, Mein Tipp: die neueren C-Standards beherzigen. Musste ich auch.
Gast
#3868592
Karl Heinz schrieb: > Frank M. schrieb: >> Karl Heinz schrieb: >>> Eine andere Möglichkeit wäre es, einen entsprechenden Pointer zurecht zu >>> casten. >> >> Ich würde genau diese Pointer-Cast-Variante immer dem union-Trick >> vorziehen. Das mit der union ist ausdrücklich lt. C-Standard nicht >> garantiert. > > Ich denke es war der C99 Standard (weiss nicht mehr genau), welcher > diesen union Trick für chars (und damit auch unsigned chars) legitimiert > hat. Meinst du N1256 (C99) 6.2.6.1(5)?
1 | |
Den Abschnitt gibt es auch in N1570 (C11). > Zuvor war die Situation so, dass es keinen gerantierten Weg gab, weder > durch union, noch durch umcasten von Zeiger-Typen. Doch. 6.2.6.1(4):
1 | |
Also:
1 | |
2 | |
3 | |
Und ja, das ist effizient. Sowohl Clang und gcc machen (zumindest auf x86_64) daraus entsprechende mov-Instruktionen da memcpy ein Builtin ist. avr-gcc, msp430-gcc & Co sollten das auch können, hängt ja der gleiche Optimizer dahinter. > Denn auch in dem Moment, in dem du einen Pointer Typ umcastest, landest > du automatisch in 'undefined behaviour' land. Und wieder > (konsequenterweise): einzige Ausnahme: umcasten zu einem char-Pointer. Fast richtig. char und void + cv-qualifiers. (memcpy nimmt void)
Danke für das Raussuchen, ghl. So hatte ich das auch in Erinnerung. Johann hatte das bzgl. union schon mehrfach hier im Forum angemerkt. Also halten wir fest: union ist bäh, Pointer ist gut. :-)
Frank M. schrieb: > Danke für das Raussuchen, ghl. So hatte ich das auch in Erinnerung. > Johann hatte das bzgl. union schon mehrfach hier im Forum angemerkt. Ist aber trotzdem Quatsch. Ich schätze Johann sehr. Aber in Sachen Standard Auslegung ist er für mich keine Autorität. Welcher Teil der ständig vprkommenden Phrase "except character type" ist unklar?
Karl Heinz schrieb: > Welcher Teil der ständig vprkommenden Phrase "except character type" ist > unklar? Du meinst offenbar dies in der Formulierung: "... is read by an lvalue expression that does not have character type, the behavior is undefined." Okay, das habe ich bisher auch überlesen. Gebe ich zu. Ich kann also offenbar in unions immer character-weise rumstochern. Dann hast Du recht: Ob ich char-Pointer oder (unsigned) char union member nehme, ist schnurz.
Frank M. schrieb: > offenbar in unions immer character-weise rumstochern. In alle Kürze: Worum gehts denn. es geht um die strict-Aliasing Sache. Der Compiler darf immer (mit Ausnahmen) davon ausgehen, dass es keine 2 Wege zum selben Objekt gibt, über die das Objekt modifiziert wird. Eine dieser Ausnahmen ist ein char-Typ. Sobald ein char-Typ im Spiel ist, ist die strict-Aliasing Regelung mehr oder weniger abgeschaltet und der Compiler muss von Aliasing ausgehen. Es gibt gute Artikel zu dem Thema im Web. Ein guter Anlaufpunkt sind fast immer die Artikel, die auf http://stackoverflow.com/ zu finden sind. Vor allen Dingen, seit die klassischen Newsgroups massiv an Bedeutung verloren haben - leider. Denn in den Newsgroups war es nicht ungewöhnlich, dass man dort auch auf die Leute traf, die am jeweiligen Standard mitgearbeitet haben und die Standard-Schreiber selbst um eine Klarstellung bitten konnte. http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule http://dbp-consulting.com/tutorials/StrictAliasing.html
Danke.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.