Hi, ich habe folgendes Problem: Ich programmiere gerade einen MSP430 in C (IAR Compiler). Nun habe ich eine UINT32 Variable. Die wird ja intern in zwei Registern abgespeichert, weil der Mikrokontroller ja so nur 16bit Variablen speichern kann. Wie könnte ich jetzt direkt auf z.B. die obere hälfte der Variable zugreifen. Direkt bedeutet, ohne große Schiebeoperationen oder Divisionen. Gibt es da einen Trick? Ich hoffe, ihr könnt mir helfen!
Versuchs mal so... typedef union { uint32_t i32; struct { uint8_t i8l1; uint8_t i8l2; uint8_t i8h1; uint8_t i8h2; }; } convert32to8; Aus dem AVR GCC Tutorial... http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#16-Bit_Portregister_.28ADC.2C_ICR1.2C_OCR1.2C_TCNT1.2C_UBRR.29 mfg Andreas
Was stört dich an der einzig universell nutzbaren shift-and-mask Methode?
Hi, A.K., "Was stört dich an der einzig universell nutzbaren shift-and-mask Methode?" Eine Anweisung wie "TCCR1B = BV(WGM12) | BV(CS12);" ist wunderbar, wenn einzelne Bits zu bearbeiten sind. Aber wenn ein PLL-Baustein ein einziges Datenwort verlangt, das auch 3x u12-Zahlen zusammengesetzt ist und 6 Flags, dann bilde ich das lieber in einer Struktur ab und bette die in eine union ein, damit ich einerseits leicht berechnen, schreiben, und auch leicht lesen kann. Ciao Wolfgang Horn
Danke euch. Ich benutze das bei einer Mittelwertberechnung. Anstatt 16mal nach links zu shiften, kann ich jetzt einfach die beiden oberen Byte nehmen. Das geht natürlich deutlich schneller.
und bei einem anderen packing oder gar anderen compiler funktioniert das program nicht mehr! es gibt übrigens für sicherheitsrelevante und automotive anwendung gewisse regeln (siehe MISRA), die auch ihren grund haben. und eine davon ist, dass man unions nicht verwenden soll. aber solange du die software nur für dich schreibst ist mir das egal.
Warum denn gleich so aggressiv??? Es gibt Momente, da sind die Fähigkeiten eines Programmes wichtiger als seine Portabilität. Für eine Lösung mittels shiften hätte ich nicht genug Zeit. So geht es deutlich schneller und es passt. Anstatt Unions zu verwenden, könnte ich natürlich auch inline assembler verwenden. Ich glaube aber kaum, dass das größere Sicherheit bietet und portabler ist.
hans dieter bitte verlaße dieses forum.ich will dich hier nicht schreiben sehen.
@Norbert, "Für eine Lösung mittels shiften hätte ich nicht genug Zeit. So geht es deutlich schneller und es passt." Ich kenne den MSP430 Compiler nicht, aber wenn dem wirklich so ist, dann wäre er extrem grottenschlecht. Alle Compiler, die ich kenne, werden hellhörig, wenn sie sowas wie "<<8" oder "*256" sehen und optimieren das sehr gut. Da sind schlechtestenfalls 1..2 Zyklen überflüssiger Code drin und das merkt keine Sau. Werf doch einfach mal nen Blick ins Assemblerlisting, ob der MSP430 Compiler wirklich so grottenschlecht optimiert. Peter
Hmm...ich habs gerade mal ausprobiert. Es sind doch weniger Befehle als ich dachte beim shiften. Die Union Lösung ist aber immer noch deutlich kürzer. Aber zumindest theoretisch müssten jetzt beide Lösungen passen. ConvertLongToShort Threshold; unsigned long Schaltschwelle; // benötigt 5 Zyklen Threshold.UINT32 -= Threshold.UINT16H + TAR; // benötigt 14 Zyklen Schaltschwelle -= (Schaltschwelle >>16) + TAR; Klar ist die Union Lösung ein wenig, nennen wir es mal hingetrickst. Aber ich denke, solange man weiß, was man da tut, ist das doch okay, oder? Wie würdet ihr das sehen?
Vielleicht nochmal kurz zuim Hintergrund, warum ich hier so ein "Aufstand" mache wegen ein paar Taktzyklen. Die Mittelwertberechnung ist Teil einer AD-Wandlung. Zwischen den einzelnen Messungen habe ich lediglich etwa 50 Taktzyklen Zeit. Zurzeit bin ich zwar erst bei 22 Taktzyklen, es muss aber noch etwas Platz bleiben, da später noch Zähler gesetzt werden müssen usw.
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.