www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Datentypen Atmega32


Autor: Madde (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe eine Lichtschranke mit einem Atmega32 gebaut und habe 
anscheinend ein type problem. Die Ausgabe übernehmen 6 7-Segment 
Anzeigen und funktionieren.
Hier das Problem
uint32 mpers;

  uint32_t numerator = calc_d_in_mm()*1000; //get distance
  uint32_t denominator = calc_t_in_ms(); //get time

  mpers = (numerator/denominator+5)/10;  //+5 -> rounding (int cuts off decimals)


Da double und float von vornherein alle Nachkommastellen abgeschnitten 
haben (Wieso denn?), habe ich einfach einen unsigned long benutzt und 
das komma um 3 stellen verschoben.
"mpers" wird anschließend in seine digits aufgeteilt und an die 
einzelnen Anzeigen übergeben:
    LB_v1 = (mpers/1)%10;    //split number to digits
    LB_v2 = (mpers/10)%10;
    LB_v3 = (mpers/100)%10;
    LB_v4 = (mpers/1000)%10;
    LB_v5 = (mpers/10000)%10;
    LB_v6 = (mpers/100000)%10;
mpers = 1234;           //wird richtig dargestellt
mpers = calc_d_in_mm(); //wird richtig dargestellt
mpers = calc_t_in_ms(); //wird richtig dargestellt

ABER:
numerator = calc_d_in_mm()*1000;
mpers = numerator/1000;
//stellt viel zu großen Blödsinn dar, als ob ein type overflow 
stattfinden würde
//das selbe passiert bereits, wenn man mit 10 multipliziert, ABER nicht 
bis 9

Die Distanz hat einen bereich von 0-29999mm.

Ich muss die Arbeit am Dienstag als Abiturarbeit abgeben und wäre euch 
unendlich dankbar, wenn ihr mir sagen könntet woran es liegt...
Anbei noch die komplette Datei.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Madde wrote:
> Da double und float von vornherein alle Nachkommastellen abgeschnitten
> haben (Wieso denn?),
Weil du vermutlich nicht gegen die Fließkomma-Bibliotheken gelinkt hast. 
Aber lass das Fließkomma besser wieder in der Schublade verschwinden...

Ansonsten nur so als Tipp für Festkomma: Man muss ja nicht mit 
10er-Potenzen hochskalieren und nachher wieder teilen. 2er-Potenzen tuns 
auch und sind schneller...

Autor: Madde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du meinst das

mpers = (numerator/denominator+5)/10;

als 2er potenz?

Liebend gerne, aber alles größer 9 ergibt, wie gesagt, fehler :(

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dürft ihr denn keine Debugger benutzen? Im Programm einzelschrittweise 
die Werte ansehen, und prüfen, wo es schiefgeht, ist in 3 Minuten 
erledigt.

Oliver

Autor: Madde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich arbeite zuhause mit linux und eclipse, da bin ich etwas überfragt. 
Im AVR Studio war das recht gut, ja.

Autor: Rik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Madde,
das AVR-Studio 3.x funktioniert problemlos unter Linux mit wine 
(zumindest der Assembler und Simulator, den Rest des Studios benutze ich 
nicht).

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich arbeite zuhause mit linux und eclipse, da bin ich etwas überfragt.
>Im AVR Studio war das recht gut, ja.

Na ja, ist dein Abi. Die einen nutzen linux und Eclipse, die anderen 
sind schon lange fertig. Nichts gegen Eclipse oder linux, aber 
programmieren ohne Debugger ist sinnlos, auch wenn die echten Kerle 
meinen, es ginge auch ohne.

Ich hätte es ja mal schnell durch den Simulator gejagt, aber leider gibt 
mal keinen kompilierbaren Code. Musst du also selber lösen.

Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke mal dein Hauptproblem besteht darin, dass du von falschen 
Vorstellungen ausgehst, wie in C Datentypen für eine Berechnung 
ausgewählt werden. Die Aussage ...

> Da double und float von vornherein alle Nachkommastellen
> abgeschnitten haben (Wieso denn?),

... geht für mich ebenfalls in diese Richtung.

Dein Problem ist, dass du falsche Vorstellungen davon hast, wie der 
Compiler eine Operation auswählt. In

  double m = 7 / 5;

erhält m den Wert 1, obwohl es als double definiert ist! Warum ist das 
so? Weil der Compiler bei der Auswahl der Operation sich ausschliesslich 
an den beteiligten Operanden orientiert! 7 ist ein Integer, 5 ist ein 
Integer. Folgerichtig wird die Division als Ganzzahldivision ausgeführt. 
Und 7 durch 5 als Ganzzahldivision ergibt nun mal 1. Erst danach, wenn 
das Ergebnis feststeht, kommt der Zieldatentyp von m ins Spiel. Das 
Ergebnis ist ein Integer, das Ziel ist ein double. Also wird die Integer 
1 auf eine double 1 umgewandelt und zugewiesen.

Auch in deinem Code sind solche Misverständnisse zu sehen.

zb
  d_in_mm = (LB_d5*10000)+(LB_d4*1000)+(LB_d3*100)+(LB_d2*10)+LB_d1;

LB_d5 ist ein uint8_t, 10000 ist ein int. Der größte gemeinsame Nenner 
zwischen den beiden Datentypen ist ein uint16_t. Und genau diese 
Operation nimmt der Compiler dann auch her. LB_d5 wird mit 10000 per 
16-Bit-unsigned Multiplikation verknüpft. (Zur Erinnerung: ein uint16_t 
kann nicht größer als 65535 werden). Wenn LB_d5 also den Wert 7 erreicht 
hat, dann geht diese Operation schon mal schief. Um das zu vermeiden, 
musst du den Compiler zwingen, die Operation als 32-Bit Operation 
durchzuführen. Es reicht, wenn einer der beteiligten Operanden ein 
uint32_t ist. Also entweder du castest den LB_d5 auf einen 32 Bit 
Datentyp hoch, oder du machst aus den 10000 eine long Zahl: 10000L oder 
besser gleich eine 32 Bit unsigned long Zahl 10000UL

Druchforste mal deinen Code auf derartige Misverständnisse und du wirst 
sehen, dass deine Ergebnisse besser werden.

Autor: Madde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antwort!
Ich habe auch mal die Compileroptimierung ausgeschaltet und nun 
funktioniert es... Dafür aber anscheinend nicht mehr der Timer.
Ich werde mal Deinem Rat folgen und den Code durchgehend mit UL oder 
casts versehen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.