Hallo, simple frage ich messe eine frequenz und möchte nur kiloherz in einer variable haben: 500000 --> in variable soll nur 500 stehen. nun das problem: mit uint16_t freq; freq = overflows * 0.256; klappt alles ich komme auf reale werte. nur knallt er mir wegen der Gleitkommazahlen 3kb in den Flash... freq = (overflows * 256) / 1000; gibt mir nur unsinnige Ergebnisse (bei einer Frequenz von 77khz bekomme ich 12) wie löse ich am besten mein Problem und warum geht mein 2. Lösungsansatz nicht? danke
du hast da mit der variablendeklaration mist gemacht... ...ich würds lieber lassen... mfg, hannis
uint_16t ist, wie der Name sagt, 16bit groß, kann also maximal (2^16)-1=65535 annehmen. 500e3 passt da nicht rein, 500e3*256 erst recht nicht. Du musst also mit uint_32t rechnen
1 | freq = (uint16_t)(((uint32_t)overflows * (uint32_t)256) / (uint32_t)1000); |
newbie schrieb: > was soll ich denn lassen? deine kläglichen versuche, einen microcontroller zu programmieren...
Meine Hochleistungs-Kristallkugel sagt, dass deine Integers nur 16 Bit haben, und du deswegen einen überlauf hast (77000 - 2^16 ~ 12000). Besser wäre es, du würdest mal vollständige Informationen liefern (welcher Prozessor/Compiler, wie ist overflows deklariert).
Poste mal die Schaltfrequenz und mach ein Bild von deinem Aufbau. Schaltplan nicht vergessen!
denke für eure Antworten... ich wahr der Annahme das er wenn ich freq = (overflows * 256) / 1000; rechne dass er dann z.b. 300*256 rechnen und durch 1000 teilt und DANN erst das Ergebnis zuweist. Somit hätte es auch in die 16bit Variable gepasst. Das es nicht in einen "rutsch rechnet" und dann das fertige Ergebnis zuweist wusste ich nicht. Dankeschön
newbie schrieb: > dass er dann z.b. 300*256 rechnen und durch 1000 teilt und DANN erst das > Ergebnis zuweist. Ja, das ist auch der Fall, aber der GCC rechnet, wenn man es ihm nicht anders sagt mit 16 bit. Deshalb muss man casten.
Hannis schrieb: > du hast da mit der variablendeklaration mist gemacht... > > ...ich würds lieber lassen... > > > mfg, hannis man mach immer wieder die Erfahrung das viele vergessen wie sie selbst mal angefangen haben...
Mann kann sich allerdings auch mit ein bischen Mathe der Sache annähern und realisieren, dass man den ganzen Bruch durch 256 kürzen kann. freq = overflows / 4; Zack. Und schon stimmt dann auch das Ergebnis, weil es zu besagten Overflow erst gar nicht kommt. Ganz abgesehen davon, dass eine Division durch 4 für den µC ein Kinderspiel ist, eine Division durch 1000 aber nicht.
Lukas K. schrieb: > newbie schrieb: >> dass er dann z.b. 300*256 rechnen und durch 1000 teilt und DANN erst das >> Ergebnis zuweist. > > Ja, das ist auch der Fall, aber der GCC rechnet, wenn man es ihm nicht > anders sagt mit 16 bit. Deshalb muss man casten. Immer diese Halbwahrheiten. Der GCC rechnet, so wie jeder andere C Compiler immer im höchsten an einer Operation teilnehmenden Datentyp, mindestens jedoch in int. freq = (overflows * 256) / 1000; overflows dürfte wohl ein int sein, 256 ist ein int. Also wird eine int*int Multiplikation gemacht und das Ergebnis ist wieder ein int. Wenn overflows von Haus aus ein long gewesen wäre, dann würde an dieser Stelle auch eine long*long Multiplikation durchgeführt. Genauso wenn 256 ein long wäre, was sich durch einen Suffix erzwingen liesse´ overflows * 256L ---- Und da der Teilausdruck overflows * 256 eine int*int Multiplikation ist, kommt da auch ein int Teilergebnis raus. Damit verbleibt für die Division, dass ein int durch einen int dividiert wird und das ganze daher auch als int-Division realisiert wird. Hätte man geschrieben (overflows * 256L) / 1000 dann wäre die Division ebenfalls als long-Division gemacht worden. Warum? Weil der linke Teilausdruck der Division als Ergebnis einer long*long Multiplikation ebenfalls den Datentyp long hat. Damit steht aus Sicht der Division die Sache so aus, dass sie einen long durch einen int dividieren soll, der kleinere der beiden Datentypen wird entsprechend vergrößert und man landet bei einer long/long Division. Der GCC rechnet also nicht einfach generell in 16 Bit und wenn man etwas anderes haben will muss man casten, sondern er hält sich an die C-Regeln. Und die sind eindeutig: entscheidend ist der Datentyp der beteiligten Operanden einer Operation.
newbie schrieb: > denke für eure Antworten... > > ich wahr der Annahme das er wenn ich > > freq = (overflows * 256) / 1000; rechne > > dass er dann z.b. 300*256 rechnen und durch 1000 teilt und DANN erst das > Ergebnis zuweist. Ja, tut er auch. > Somit hätte es auch in die 16bit Variable gepasst. > Das es nicht in einen "rutsch rechnet" und dann das fertige Ergebnis > zuweist wusste ich nicht. Wie sollte das gehen? Es gibt nun mal nicht als einzelne Assembler-Instruktion sowas wie "Multipliziere Register x mit Register y und dividiere das Ergebnis gleich noch durch z", sondern diese beiden Operationen müssen natürlich separat gemacht werden. Das bedeutet aber, daß es ein Zwischenergebnis gibt, und auch das hat eine Größe, in die es auch reinpassen muß. Das wird dann für die Division weiterverwendet, und deren Ergebnis wird dann an die Variable zugewiesen.
Hannis schrieb: > ...ich würds lieber lassen... newbie schrieb: > was soll ich denn lassen? Hannis schrieb: > deine kläglichen versuche, einen microcontroller zu programmieren... Du hast nie klein angefangen oder? Du solltest mal dein Sozialverhalten überprüfen.
Na ja... 256 / 1000 ist nicht ganz 1/4. Man kann aber trotzdem ganzzahlig Kürzen. Mach mal eine Primfaktorzerlegung, dann kann man da viel kürzen. Aus 256/1000 wird 128/500, 64/250, 32/125. Ab jetzt gibt es Rundungsfehler. newbie schrieb: > dass er dann z.b. 300*256 rechnen Und genau jetzt tritt ein Überlauf auf. 256*256 benötigt bereits 17Bit zur Darstellung. Mit Vorzeichen wird die Sache dann noch lustiger :-) tschuessle Bernhard
Bernhard Spitzer schrieb: > Na ja... 256 / 1000 ist nicht ganz 1/4. Bin schon in Eckerl und schäme mich.
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.