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
unsigned long x = R4 | ((unsigned int)TCNT3H << 8) | ((unsigned long)TCNT3L << 16) | ((unsigned long)PORTC << 24); Peter
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
Setzt aber leider voraus, daß die Variablen hintereinander im Speicher stehen.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.