Festkommaarithmetik und itoa Problem

OP #3654327
Lesenswert?

Hallo Community,

ich möchte ein Gerät zur Neigungsmessung zusammen bauen und via LCD die 
Werte anzeigen lassen.

der Bereich geht von -90.0° bis 90.0°.

Jetzt wollte ich zu testzwecken auf meinem myAVR Board (inkl. LCD) das 
ganze schon mal mit dem LCD fertigstellen bis das IC und das neue LCD 
kommt.

Also Poti an den ADC und ne kleine Rechnung um meinen Werte-Bereich 
anzeigen lassen zu könnrn:
1
  // Wert aus ADC in Buffer übertragen
2
  buffer = ADC_Wandler(0);
3
  
4
  // Umwandlung von -500 bis +500; x ist eine int32_t und textfeld eine char[12] Variable
5
  x = (((1000*buffer)/255)-500);
6

7
  itoa (x, textfeld, 10);
8

9
  //Variable textfeld ausgeben
10
  lcd_goto(2, 10);
11
  _delay_ms(10);
12
  lcd_writeText(textfeld, 4);
13
  _delay_ms(10);



ADC ist auf 0-255 skaliert und mit der kleinen Rechnung, müsste dann 
-500 bis +500 als Ergebnis erscheinen. Um nun das "," einfügen zu können 
hab schnell diesen Code zusammen gebastelt (ist nicht schön ich weiß, 
aber für meine Zwecke vollkommend ausreichend):


1
//Variable textfeld mit ","
2
lcd_goto(1, 4);
3
if ((x >= (-999)) && (x <= (-100))) {
4
      lcd_write('-');
5
      lcd_write(textfeld[1]);
6
      lcd_write(textfeld[2]);
7
      lcd_write(',');
8
      lcd_write(textfeld[3]);
9
    } else if ((x >= (-99)) && (x <= (-10))) {
10
      lcd_write('-');
11
      lcd_write(' ');
12
      lcd_write(textfeld[1]);
13
      lcd_write(',');
14
      lcd_write(textfeld[2]);
15
    } else if ((x >= (-9)) && (x < 0)) {
16
      lcd_write('-');
17
      lcd_write(' ');
18
      lcd_write('0');
19
      lcd_write(',');
20
      lcd_write(textfeld[0]);
21
    }else if (x == 0) {
22
      lcd_write(' ');
23
      lcd_write(' ');
24
      lcd_write('0');
25
      lcd_write(',');
26
      lcd_write('0');
27
    } else if ((x > 0) && (x <= 9)) {
28
      lcd_write(' ');
29
      lcd_write(' ');
30
      lcd_write('0');
31
      lcd_write(',');
32
      lcd_write(textfeld[0]);
33
    } else if ((x >= 10) && (x <= 99)) {
34
      lcd_write(' ');
35
      lcd_write(' ');
36
      lcd_write(textfeld[0]);
37
      lcd_write(',');
38
      lcd_write(textfeld[1]);
39
    } else if ((x >= 100) && (x <=999)) {
40
      lcd_write(' ');
41
      lcd_write(textfeld[0]);
42
      lcd_write(textfeld[1]);
43
      lcd_write(',');
44
      lcd_write(textfeld[2]);
45
    }

Aber aus mir unerklärlichen Gründen kommt bei x ein falscher Wert raus.

Daher hab ich den ganzen Code kopiert und in Dev-C++ eingefügt und alle 
lcd_write befehle durch print_f ersetzt --> Es funktioniert ohne wenn 
und aber.

Das einzige was ich mir erklären kann, ist das der DEV-C Kompiler eine 
andere Biblitothek für itoa benutzt als der des AVR Studio 6.

Habe auch schon den ABS vonx gebildet und dann erst gewandelt. Ebenso 
die Rechnung in einzelen Rechenschritte einzuteilen mit 
Zwischenergebnissen, es klappt im AVR Strudio einfach nicht.

Hat einer von euch nen Rat? Code sind im Anhang, danke euch im Voraus. 
Ich weiß nicht mehr weiter...

mfg
Hohmi
Angehängte Dateien:
Gast #3654334
Lesenswert?

> uint8_t buffer = 0;
> x = (((1000*buffer)/255)-500);

wenn buffer > 66 ist dann wird 1000*buffer > 66000 und das Passt nicht 
mehr in einen int.

 x = (((1000l*buffer)/255)-500);

müsste funktionieren.
#3654344
Lesenswert?

Huhu Stefan

Nur mal ein Schuss ins Blaue:

Stefan H. schrieb:
> x = (((1000*buffer)/255)-500);

Wenn buffer = 255 ist, wird der Wert (1000 * buffer) natürlich 255000.
Das ist aber vermutlich größer als der MAXINT des AVRs.

Mit anderen Worten: Du hast da einen Zahlenüberlauf. Darum klappt das 
dann auch auf dem PC, der ja mit 32, bzw. 64 bit rechnet.

Grüße
Andreas
OP #3654581
Lesenswert?

Sooooooooo, danke an alle!!!!
an der buffer Variabel hat es nicht gelegen. Die hatte ich als int32_t 
deklariert.

Die Festkommaarithmetik hatte ich mir schon durchgelesen aber nicht 
genau genug...

Die Lösung:

"Man sollte mindestens eine Variable auf der rechten Seite genauso groß 
deklarieren wie das Ergebnis auf der linken Seite oder einen Cast 
benutzen."

ein cast dabei und das Problem hat sich in Luft aufgelöst:
1
x = (((1000 * (long) buffer)/255)-500);


Danke an alle die daran mitgewirkt haben!

mfg Hohmi
Gast #3654599
Lesenswert?

Stefan H. schrieb:
> "Man sollte mindestens eine Variable auf der rechten Seite genauso groß
> deklarieren wie das Ergebnis auf der linken Seite oder einen Cast
> benutzen."

Da ist ein dicker Übersetzungsfehler drin. Richtig muss es heißen:
"Man muss mindestens ...", sonst nützt das alles nichts.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren