Hallo C-Gemeinde,
ich habe vier einzelne Bytes, und zwar:
als Highbyte: R4, unsigned char high_count
als Middel1: TCNT3H, unsigned char middel_1_count
als Middel0: TCNT3L, unsigned char middel_0_count
als Lowbyte: PORTC, unsigned char low_count
Wie wird hieraus eine 32-bit Variable?
Bisher habe ich nur einfache I/O-Operationen in C geschrieben.
Aber jetzt gehts, glaub' ich, ans 'Eingemachte'.
Vielen Dank für eure Hilfe Norbert
So, endlich konnte ich eure Diskussionsbeiträge testen.
Es funktioniert wie folgt:
unsigend long x = ((unsigend char) PINC)|((unsigned
int)TCNTL3<<8)|((unsigned long)TCNT3H<<16)|((unsigned long)R4<<24);
Diese Funktion ist aber nur die halbe Wahrheit. Ich habe die
Counterregister TCNT3L und TCNT3H zuerst in Variablen
zwischengespeichert, und zwar erst das L-Byte und dann das H-Byte.
Aber dennoch, es gibt Probleme mit dem Auslesen der Counterregister.
Dazu werde ich im Forum 'Allgemein' einen Thread schreiben.
Erstmal vielen Dank für eure Hilfe Norbert
für sowas ähnliches hab ich das mit einem union gelöst. Ist meiner
Meinung nach wesentlich eleganter als diese Bitschieberei und zudem
wesentlich performanter, da ja die 32-Bit Variable und eine Struktur mit
4 chars den selben Speicherplatz belegen, d.h. nicht mehr umgelagert
werden müssen.
Also z.B.
struct irgendwas
{
unsigned char highbyte;
unsigned char middle1;
unsigned char middle0;
unsigned char lowbyte;
};
union xyz
{
struct irgendwas wasweissich;
unsigned long lange_variable;
};
usw. usf.
Gruss,
Peter
alternativ ginge es auch so:
struct
{
unsigned long int lowbyte:8;
unsigned long int middle0:8;
unsigned long int middle1:8;
unsigned long int highbyte:8;
} lange_variable;
Gruss,
Peter
Hallo Peter,
das mit der Union hat aber 2 Nachteile:
1.
Der Code ist langsamer und größer, da Unions immer im RAM abgelegt
werden.
Ein lokales long kann dagegen in Registern gehalten werden. Auch
optimieren die meisten Compiler sehr gut. Es kann also durchaus sein,
daß die ganze Zeile nur aus 4 Befehlen besteht:
in r16, PINC
in r17, TCNTL3
in r18, TCNTH3
mov r19, R4
2.
Eine Union aus verschiedenen Typen ist immer Compilerabhängig.
Jeder Compiler hat die Freiheit, das höchstwertigste oder das
niederwertigste Byte zuerst zu schreiben.
Peter
@schmittchen
> Setzt aber leider voraus, daß die Variablen hintereinander im Speicher stehen.
von welchen Variablen sprichst du? Ich kann dir leider an diesem Punkt
nicht folgen, irgendjemand von uns beiden muss hier wohl etwas nicht
richtig verstanden haben.
@P. Dannegger
> Der Code ist langsamer und größer, da Unions immer im RAM abgelegt werden.
Also ich weiss ja nicht woher du diese Annahme hast, aber da diese Sache
mich persönlich sehr interessiert habe ich mir die Mühe gemacht und mal
in meiner eigenen (umfangreichen) Literatur und auch im Internet
recherchiert, irgendwas zu finden, dass deine Aussage belegen würde, ->
Fehlanzeige.
Da ich jedoch weiss, dass solche Aussagen dann doch irgendwo bei den
anderen Lesern im Hinterkopf auf einem gewissen "status quo"
hängenbleiben, habe ich mir ganz einfach die Mühe gemacht und es an
einem praktischen Beispiel mit dem avrgcc mal ausgetestet. Natürlich
kann ich ein union mit dem Attribut register versehen und siehe da, es
wurden auch entsprechend Register im übersetzten Code verwendet. Das
Watch-Window des AVR-Studio belegte dies auch mit einer Anzeige des
ersten Registers "(Reg) 24" und das Register-Window zeigte, dass die
Register 24-27 bei meinem Versuch auch entsprechend bei einer Zuweisung
genutzt wurden. Womit diese Behauptung nun wohl eindeutig widerlegt
wäre.
> Eine Union aus verschiedenen Typen ist immer Compilerabhängig.
Diese Aussage ist so nicht ganz richtig. In einer durch einen C-Compiler
angelegten Datenstruktur werden entsprechende Fraktionen immer in
maschinenabhängig aufsteigender Werigkeit gefüllt. D.h. es ist abhängig
davon, ob man sich auf einem big-endian oder einem little-endian System
befindet.
Aber unabhängig davon, es dürfte doch wohl das geringste Problem sein,
solch eine Frage einmalig in einem Versuch zu ermitteln, oder nicht?
Gruss,
Peter
Ich bin von Norberts Angaben ausgegangen. R4, TCNT3H, TCNT3L, PORTC
liegen nicht im Speicher hintereinander. Deshalb kann keine Union
darübergestülpt werden.... und extra nochmal eine Struktur (mit weiteren
4 Bytes) zu verbrauchen, dachte ich zunächst sei auch nicht sinnvoll.
ABER: Die mittels "|" zusammengestücktelte Variable verbraucht ja auch
Speicher. Also alles wieder zurück.
> irgendjemand von uns beiden muss hier wohl etwas nicht richtig verstanden haben.
Hier, ich. :)
Schmittchen.
Hallo Peter,
1.
ich hab das eher allgemein für C-Compiler betrachtet.
Mag sein, daß meiner nicht mehr der neueste ist und da war es so.
Interessant wäre trotzdem, ob die OR-Verknüpfung nicht auch genau so
optimal ist, wie die Union in Registern.
2.
Mit der Byte-Order bin ich mal mächtig reingefallen und deshalb nehme
ich das nie mehr. Der, wenn überhaupt, minimal kleinere Code ist es
nicht wert, sich dafür Fallgruben ins Programm zu nehmen.
Ich will nicht ausschließen, daß alle z.Z. verfügbare AVR-Compiler die
gleiche Byteorder verwenden, aber vielleicht nimmt man ja Routinen auch
mal auf anderen Maschinen, getreu dem Motto "C läuft überall".
Peter
Hallo Namensvetter!
> Interessant wäre trotzdem, ob die OR-Verknüpfung nicht auch genau so optimal
ist, wie die Union in Registern.
ok, aber diesmal bist du an der Reihe, den praktischen Test
durchzuführen.
> Ich will nicht ausschließen, daß alle z.Z. verfügbare AVR-Compiler die gleiche
Byteorder verwenden, aber vielleicht nimmt man ja Routinen auch mal auf anderen
Maschinen, getreu dem Motto "C läuft überall".
Ok, hier hast du Recht, von solchen Konstrukten wird in Lehrbüchern
abgeraten wenn es auf Portabilität des Codes ankommt.
> Mit der Byte-Order bin ich mal mächtig reingefallen und deshalb nehme ich das
nie mehr.
Wenn das so ist, dürfte ich mich z.B. nie mehr mit Frauen befassen ;-)
Aber mal ehrlich, die Realität sieht doch etwas anders aus. Man lernt
etwas dazu und macht halt eben das nächste Mal andere Fehler. Nicht
wahr?
Mit :-) Gruss
Peter
Der Vergleich hinkt:
Ich habe ja mit der OR-Verknüpfung eine vollwertige Alternative, die
Byteorder unabhängig ist.
Aber welche Alternative hast Du zu Frauen ?
Es gibt noch ne Menge Beispiele, wo anderer C-Code vielleicht mal ein
Byte mehr benötigt aber dafür wesentlich stabiler ist.
Wenn man also in C-Lehrbüchern bestimmte Code-Konstrukte als gefährlich
eingestuft findet, sollte man das besser ernst nehmen.
Was weiß ich noch über den kritischen Code im Project von vor 2 Jahren.
Peter D.
> Aber welche Alternative hast Du zu Frauen ?
The System has detected an Internal Processing Error in module
REALITY.SYS. Please shut down your universe and reboot.
Mehr fällt mir dazu nun auch nicht ein.
Gruss,
Peter