PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Aufteilung int16_t in zwei int16_t, Fehler durch 0ptimierung ?



oberallgeier
09.11.2013, 15:41
Bitte um Hilfe oder Erklärungen.

Aufgabe:

Eine Routine wird mit einem int16_t-Parameter aufgerufen, Beispiel 2008. Beliebige Werte unter 15 (hier die 8 ..) sollen in eine Variable int16_t Il* übernommen werden, Werte über 15 sollen sinngemäß in eine Variable int16_t Iv* übernommen werden. Beide Zielvariablen müssen 16 Bit breit sein.

Mein Code läuft nur mit Tricks - möglicherweise wird etwas wegoptimiert, wahrscheinlicher finde ich meinen fehlerhaften Umgang mit C. Die folgenden Schnippsel zeigen zwei Versionen der betreffenden Routine, wobei nur die zweite Version mit einer Hilfsvariablen läuft.

Der Offset von 1 bei der Umwandlung in den grösseren Wert ist möglicherweise in der Zahlendarstellung begründet, mir ist aber nicht klar, wieso das beim kleineren Wert ohne diese Korrektur geht.



volatile int16_t Iv_sound; // Sound - Vorgabe = maximaler Faktor => Tonhöhe
volatile int16_t Il_sound; // Soundlänge in tupsi, wird in ISR..COMPB decrem.// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//Aufruf:
beep ( 2008 ); // Soundausgabe zur Anmeldung inf


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Version geht nicht
void beep ( int16_t paramtr ) // Soundausgabe Einzelton, parameterisierbar
{ //
Iv_sound = paramtr &= 0x000F; // Soundfaktor (Tonhöhe)
Il_sound = paramtr &= 0xFFF0; // Sounddauer
} // Ende von void beep ( int16_t paramtr )
// Dabei ist Iv_sound 8 und Il_sound 0

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Version geht
void beep ( int16_t paramtr ) // Soundausgabe Einzelton, parameterisierbar
{ //
int16_t dummy = paramtr;
Iv_sound = dummy &= 0x000F; // Soundfaktor (Tonhöhe)
Il_sound = (paramtr &= 0xFFF0) + 1; // Sounddauer
} // Ende von void beep ( int16_t paramtr )
// ================================================== =========================== =

Ein C-Tutorial zur Bitmanipulation (http://www.mikrocontroller.net/articles/Bitmanipulation#Standard_C_2) brachte mir keine Hilfe.

Che Guevara
09.11.2013, 15:55
Hi,

ich glaube, der Fehler liegt darin, dass du bei


Iv_sound = paramtr &= 0x000F;

die Variable paramtr veränderst?!
So sollte es gehen:


Iv_sound = (paramtr & 0x000F);
I1_sound = (paramtr & 0xFFF0);


Gruß
Chris

shedepe
09.11.2013, 16:13
Ja genau. In deinem Code verundest du paramtr mit 0x000F weist das dann paramtr zu und weist dann das Ergebniss Iv_sound zu.

oberallgeier
09.11.2013, 16:18
... der Fehler liegt darin, dass du ... die Variable paramtr veränderst?! ...Danke Chris. Das war superschnell und hilfreich. Ich hatte das schon mit ner Klammer probiert, aber eben dazu noch den Zuweisungsoperator.

ABER : beim
Il_sound = (paramtr & 0xFFF0);kommt trotzdem eins weniger raus (Kopie der Terminalausgabe) siehe Nachtrag unten :
Beep Aufruf mit 2008
Beep 8 1999




.. In deinem Code verundest du ... weist das dann paramtr zu und weist dann das Ergebniss Iv_sound zu.Ach ja, "Vorrang und Assoziativität von Operatoren" im K&R - gibts ja ne Extra Tabelle die ich (natürlich - ähhh - leider) nicht im Kopf habe. Ist ja auch das vorletzte bedruckte Blatt . . .

- - - - - - - -
Nachtrag: Die "Eins weniger" ist geklärt. Die Variable wird anschließend in einer 50µs-ISR runtergetickert - und die testweise UART-Ausgabe braucht eben auch Zeit. Mit "cli();" und "sei();" an der richtigen Stelle passiert das nicht mehr.

Danke für die Hilfe.