Falsche typenkonvertierung?
-
Hallo,
ich schreibe gerade ein Progamm für einen Mikrocontroller. Dieses soll einen eingegebenen wert (steht in einem Char feld als einfache zahl) umrechnen zerlegen und Seriell ausgeben.
Prinzipill funktioniert es scheinbar auch aber ich bekomme immer bei 32768 einen falschen wert.die Formell zur bereichnung heißt F = eingabe_wert * 2^28 / 25000000HZ
das ergebniss soll ein 28Bit datenwort sein, dieses wird in 2 14bit datenworte zerlegt und mit 0100000000000000 verknüpft (die höchsten 2 bits geben an in welches register des Ziel-ICs geschrieben wird).
Ich habe das ganze versucht so zu implementieren:
rechen_tmp = long double
frequenz = uint32_t
dat = uint16_t
BCD[] = charspeicher = BCD[7] + (BCD[6] * 10) + (BCD[5] * 100) + (BCD[4] * 1000) + (BCD[3] * 10000) + (BCD[2] * 100000) + (BCD[1] * 1000000) + (BCD[0] * 10000000); rechen_tmp = 10.73741824; //Das ergebniss aus 2^28 / 25MHZ frequenz = speicher * rechen_tmp; // Hier vermute ich den fehler dat = (uint16_t)(frequenz & 0x00003FFF); dat |= (1 << 14); wave_send(dat); frequenz >>= 14; dat = (uint16_t)(frequenz & 0x00003FFF); dat |= (1 << 14); wave_send(dat);
im bereich von eingangswerten 32768 bis etwa 50000 liefert die routine nur mist (zumindest laut meinem oszi). wenn ich unter der zeile frequenz = speicher... selbst einen wert einsetzt dann funktioniert es korrekt.
Debuggen fällt mir schwer da meine entwicklungsumgebung das irgendwie nicht wirklich kann (oder ich bin zu doof dazu).
Und im Disassambler finde ich die entsprechende stelle leider auch nicht.
Ich hoffe ihr könnt mir helfen.
Sebastian
-
Für was für einen uC soll das werden? Debuggen geht für AVRs im AVR-Studio, da gibts einen Simulator.
-
Sebastian4768 schrieb:
BCD[] = char
Steht das so im Code?
-
Hallo,
ja ich benutze in der tat avrstudio und programmiere einen ATMega16. Das hielt ich für relativ unerheblich. Ich vermute irgendeinen fehler in meiner Syntax da ich noch nciht lange C programmiere.Mit dem debugger hab ich des öfteren unter asm gearbeitet, leider funktioniert das Unter C nicht so richtig. Ich bin gerade dabei mir eine brauchbare anleitung zu suchen.
-
das letzte post kam zu spät. Nein das steht natürlich nciht so im Code. Ich wollte nur nicht ein ewig langes Programm inklusive aller variablendeklarationen Posten, deshalb hab ich mich darauf beschränkt die daten typen so zu beschreiben (leider etwas zweideutig)
-
16-Bit Integer kann demnach von -(2 hoch15) bist (+2 hoch 15) - 1 gehen (-32768 bis 32767)
Sebastian4768 schrieb:
im bereich von eingangswerten 32768 bis etwa 50000
du schiebst nicht zufällig was in dein register was da nicht rein passt?
-
bzw. schau mal ob nach der eingabe von 32768 nicht zufällig -32768 drin steht, falls doch versuch mal auf unsigned zu wechseln evtl. hilft das?
unsigned short 0 bis 65535
-
das die variable frequenz ist als uint32_t initialisiert. damit dürfte sie nicht 16 sondern 32 bit breit sein, und unsigned sein.
außerdem funktioniert die routine ab etwa 50KHZ wieder. Aber ja das war auch meine erste idee. Ich hab auch vermutet das es etwas weiter unten ist wo ich versuche die
32 bit integer in eine 16bit umzuwandelndat = (uint16_t)(frequenz & 0x00003FFF);
-
Sebastian4768 schrieb:
ATMega16
dachte das teil hat nur 8/16 bit?
kenn mich leider überhaupt nicht damit aus mir ist nur die zahl ins auge gesprungen daher meine vermutung, bin da aber def. der falsche ansprechpartner
Sebastian4768 schrieb:
wenn ich unter der zeile frequenz = speicher... selbst einen wert einsetzt dann funktioniert es korrekt.
dann sollte der fehler schon drüber sein
-
ATMega ist ein 8 bit system aber man kann ja trotzdem mit 16, 32 und sogar 64 bit variablen arbeiten (was natürlich dann extrem rechenzeit erfordert da mehrere 8 bit register benötigt werden)
-
*bump*
hab jetzt nur mal das gefunden
http://www-user.tu-chemnitz.de/~heha/Mikrocontroller/Multiplikation.htm
kpl. ob das der compiler automatisch macht hab noch nie so ein teil in den fingern gehabt...
-
Ja der Compiler macht das automatisch, wenn es ihm sinnvoll erscheint.
Wobei ich bezweifel dass er LUTs benutzt. Bitshifts sind aber ganz normal.
-
Fehler ist gefunden. Danke für eure hilfe. Hier die auflösung:
Ich habe auf dem Display verschiedene werte (mittels itoa) ausgeben lassen. Nachdem ich einige merkwürdige dinge beobachtet habe (seltsame werte, die sich ständig neu aufbauten) bin ich darauf gekommen das es sich um einen überlauf in "speicher" handeln muss.
Und hier die stelle die schuld war:
speicher = BCD[7] + (BCD[6] * 10) + (BCD[5] * 100) + (BCD[4] * 1000) + (BCD[3] * 10000) + (BCD[2] * 100000) + (BCD[1] * 1000000) + (BCD[0] * 10000000);
genau war es: (BCD[3]*10000) die BCD (typ char) ist 8 bit breit und kann 0 bis 9 annehmen. 100000 wird vom compiler vermutlich als uint16_t (oder int16_t) interpretiert. Das ergebniss ist aber breiter als 16 bit. Ich weiß nicht wo der compiler das ergebniss speichert aber offensichtlich in einem 16Bit register (da könnte der compiler schlauer sein weil das 8bit*16bit größer als 16 bit wird war zu erwarten).
Hier meine Lösung:
(BCD[3}*(uint32_t)10000)Nochmal danke.
Sebastian