Forum: Mikrocontroller und Digitale Elektronik Festkommaarithmetik + ADC


von Malte (Gast)


Lesenswert?

Nabend,
seit geraumer zeit beschäftige ich mich jetzt mit der 
Festkommaarithmetik, das Tutorial habe ich soweit verstanden und ich 
glaube der Wurm liegt an einer anderen Stelle :(
1
void my_itoa(int32_t zahl, char* string) {
2
  uint8_t i;
3
 
4
  string[11]='\0';                  // String Terminator
5
  if( zahl < 0 ) {                  // ist die Zahl negativ?
6
    string[0] = '-';              
7
    zahl = -zahl;
8
  }
9
  else string[0] = ' ';             // Zahl ist positiv
10
 
11
  for(i=10; i>=1; i--) {
12
    string[i]=(zahl % 10) +'0';     // Modulo rechnen, dann den ASCII-Code von '0' addieren
13
    zahl /= 10;
14
  }
15
}
und die Ausgabe auf dem LCD
1
void my_print_LCD(char* string, uint8_t start, uint8_t komma, uint8_t frac) {
2
 
3
  uint8_t i;            // Zähler
4
  uint8_t flag=0;       // Merker für führende Nullen
5
 
6
  // Vorzeichen ausgeben  
7
  if (string[0]=='-') lcd_data('-'); else lcd_data(' ');
8
 
9
  // Vorkommastellen ohne führende Nullen ausgeben
10
  for(i=start; i<komma; i++) {
11
    if (flag==1 || string[i]!='0') {
12
      lcd_data(string[i]);
13
      flag = 1;
14
    }
15
    else lcd_data(' ');         // Leerzeichen
16
  }
17
 
18
  lcd_data(',');                // Komma ausgeben
19
 
20
  // Nachkommastellen ausgeben
21
  for(; i<(komma+frac); i++) lcd_data(string[i]);
22
 
23
}
Alle klar so soweit.

ich lesen den ADC ein und Multipliziere ihn mit k = 586 die zahl ist 
dann maximal ~600000
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include "lcd-routines.h"
4
#include <util/delay.h>
5
#include "cpu-routines.h"
6
#include <stdint.h>
7
8
9
char mein_string[10];
10
unsigned long x;
11
int k=586; // mit 1,10,100 getestet siehe unten
12
13
int main(void)
14
15
{   cpu_init();
16
    lcd_init();
17
18
19
    while(1)
20
  {  
21
        x = ReadChannel(0) * k; // ADC 0 lesen mit k Multiplizieren 
22
        my_uitoa(x,mein_string); // 
23
        my_print_LCD(mein_string, 0, 10, 0);
24
  }
25
}
Soweit so gut auf dem Display werden jetzt auch die Werte korrekt bis 
~32000 angezeigt wenn ich k auf 1,10,100 stell. ab ~32000 gibt es dann 
aber einen Sprung :( und alles spinnt. Ich denke es liegt an der 
Multiplikation aber warum?

vielleicht hat jemand einen Tip?!

lg Malte

von Falk B. (falk)


Lesenswert?

@Malte (Gast)
1
        x = ReadChannel(0) * k; // ADC 0 lesen mit k Multiplizieren

>~32000 angezeigt wenn ich k auf 1,10,100 stell. ab ~32000 gibt es dann
>aber einen Sprung :( und alles spinnt. Ich denke es liegt an der
>Multiplikation aber warum?

32000 klingt verdächtig nach Zahlengrenze bei int ;-)

>vielleicht hat jemand einen Tip?!

Die Zeile oben ist der Übeltäter, klassischer Fehler bei C. Versuchs mal 
damit, k als unsigned long zu deklarieren. Oder mit einem cast
1
        x = ReadChannel(0) * (long)k; // ADC 0 lesen mit k Multiplizieren

Denn die RECHNUNG wird in INT durchgeführt, weil das der größte 
Zahlenbereich der Variablen rechts ist. Dabei kommt es zu einem 
Überlauf. Erst danach wird in unsigned long umgewandlet :-0

MFG
Falk

von Malte (Gast)


Lesenswert?

Danke :D,
habe es im gleichen Moment im Forum entdeckt...
1
x = (unsigned long)ReadChannel(0) * k;

so habe ich es jetzt gemacht :), das war mir aber neu :D

aber ich denke dir!

lg Malte

von Anja (Gast)


Lesenswert?

noch was:

char mein_string[10];

string[11]='\0';                  // String Terminator

Du Schreibst 2 Zeichen mehr in den String als darin platz haben.

Gruß Anja

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
Noch kein Account? Hier anmelden.