Mein math. Problem: vier Variable sind definiert. (für ATmega128) unsigned long al = 10034456; unsigned long bl = 1254299; float af; float bf; // Die Umwandlung soll hier geschehen: af = al; bf = bl; // Das Ergebniss ist nicht ganz optimal. // In af steht der Wert 1,00345E+7, // und in bf steht 1,2543E+6 // Der C-Compiler CodeVision rechnet nur mit max. 5-stelliger // Genauigkeit. Kennt jemand eine Möglichkeit diese Einschränkung zu umgehen? Vielen Dank Norbert
vielleicht nur ein Darstellungsproblem der float Zahl? Code-Vision arbeitet (wie alle anderen Compiler auch die ich kenne) mit 23bit Mantisse.
Hallo, entweder mit long rechnen und am Ende der Berechung den Nachkommateil errechnen. Also vor dem Rechnen mit 1000 erweitern und nach der Berechnung wieder durch 1000 teilen. Eine weite Möglichkeit ist die Verwendung von double, aber das ist evtl. mit dem Compiler nicht möglich. Selbst wenn alles kompiliert, kann es passieren, das immer noch float verwendet wird. Also immer noch 16-Bit. Dieter
Hi float läßt sich fast immer verhindern. Ich sehe keinen Sinn darin auf 8-Bit Maschinen mit float zu hantieren. Selbst auf dem M16C vermeide ich das wo es geht. Meist rechnet es sich genausogut nur schneller mit int bzw. long. Matthias
Hallo Norbert, letzlich wird Dir nicht der interne float-Wert angezeigt, sondern das, was printf daraus macht. Bei float ist die 7. Dezimalstelle ungenau, sechs Stellen sollten stimmen. Bei 1.2543E+6 wird m.E. nur eine '0' beim Formatieren unterdrückt, nachdem zuvor die letzte '9' richtig gerundet wurde. Ich sehe insgesamt keinen Mangel bei Deinen floats.
Ich möchte mein Problem etwas verdeutlichen: meine Variablen sind: unsigned long al = 10034456; unsigned long bl = 1254299; float af; float bf; Wenn ich die Division der Zahlenwerte von al / bl mit dem Taschenrechner ausrechne, so bekomme ich das Ergebniss 8,000051... Wird jedoch die Division der float-Werte af / bf im Controller durchgeführt, so bekomme ich das Ergebniss 8,000079... Dieses Ergebniss ist nicht brauchbar. Ich benötige eine Berechnung mit 6-stelliger Genauigkeit(ANSI-C-Standart). Mein Compiler(CodeVision), und alle anderen AVR-Compiler machen bei float-Berechnungen nur 5-Stellen genau. Im weiteren Verlauf des Programmes werden die Berechnungen periode = 8,000079 * 1e-7 und frequenz = 1 / periode durchgeführt. Vielleicht finde ich einen Weg, die von Dieter und Matthias vorgeschlagene long-Berechnung durchzuführen. Schönen Gruß Norbert
Hallo Norbert, ich habe testweise mal Deine Berechnung auf nem 8051 laufen lassen: unsigned long test( unsigned long a, unsigned long b ) { float af, bf; af = a; bf = b; return af / bf * 1e8; } void main( void ) { unsigned long al = 10034456; unsigned long bl = 1254299; al = test( al, bl ); for(;;); } Da kommt als Ergebnis richtig 800005120 raus. Warum alle AVR-Compiler das nicht können sollen, ist mir unverständlich. Da bleibt wohl nur, es in Assembler zu machen. Da kannst Du ganz leicht beliebig genaue Ganzzahldivisionen nach der üblichen Schieben-Testen-Abziehen-Methode machen. Ich habs z.B. mal für einen Frequenzzähler mit 56 Bit / 24 Bit gemacht (siehe Anhang). Peter
Bei solchen Problemen werde ich immer neugierig: ein Turbo-C Compiler aus der 'Steinzeit' liefert mir Dein Taschenrechnerergebnis; ein C-Compiler einer Firma mit drei Buchstaben, die mit 'I' anfängt, liefert mir ebenfalls die 8.000051. Zumindest von WinAvr würde ich auch ein korrektes Ergebnis erwarten. Deine Berechnungen mit long zu machen ist kippsch bezüglich eines großen Meßbereiches - float erleichtert dies erheblich. Falls Du nur Frequenz/Periode messen möchtest, nutzt Dir vielleicht www.mino-elektronik.de/fmeter/fm_software.htm. Dort findest Du .c-Quelle + .hex-Code allerdings für einen 2313.
@Michael: Sicherlich gibt es Compiler die das gewünschte Ergebniss liefern. Aber weder die 'Steinzeitcompiler' noch der IAR ünterstützten den AVRmega128! Für mich entwickelt sich das Ganze zur Farce. Da bietet mir der mega128 die optimale on-Board Hardware, wegen fehlender SW-Tools kann ich ihn aber nicht einsetzen. Als Alternative bleibt mir nur der C166-Compiler von Keil. Denn als Controllerersatz für den m128 kann ich nur den XC161CJ von Infineon einsetzen. Heul... Trotzdem, danke für Eure Meinung! Norbert
Hallo Norbert, der IAR-Compiler unterstützt den 128 voll (V2.xx). Auch die Version 1.xx erzeugt Code dafür, ohne allerdings die neuen Befehle zu nutzen. Die Tage hatte ich hier auch die Zeiten für fmul/fdiv mit unter 50us bei 12MHz angegeben, was einige Gemüter vor 'Erstaunen' aufregte. Das Teil kostet aber richtig Kohle. Wenn der C166 für Dich keine Probleme bereitet, nutze ihn. Zuvor würde ich aber unbedingt WinAvr testen, der auch korrekt rechnen müßte. Frag doch 'mal im Forum AVR-GCC nach der Rechengenauigkeit; da wirst Du sicherlich kompetente Leute finden, die Dein Beispiel 'mal eben schnell' rechnen lassen können.
Michael, laut IAR.com wird der mega128 nicht von Workbench unterstützt. Da ich eh die komplette C166-Umgebung von Keil (µVision2) besitze würde es wenig Sinn machen noch einmal eine sehr teure IDE zu kaufen. Was WinAvr betrifft, so ist es merkwürdig still hier im Forum. Ich gehe davon aus, daß User des AVR-GCC-Forum hier im Allgemein-Forum auch mal 'Querlesen'. Schönen Gruß Norbert
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.