Zeiger Problem aus einer Funktion heraus

OP #2013294
Lesenswert?

Hallo zusammen,

die folgende Funktion befindet sich in meiner funktionen.c (Ich lese 
über ADC0 eine Spannung ein und will diese auf einem LCD ausgeben):
1
void abfrage_spg_hc(void)
2
{
3
  char spg_vor[5], spg_nach[5];                //Variablen für Funktion deklarieren
4
  uint16_t spg_utoa=0, spg=0;
5
  float result=0;
6
  char data[12];
7
  uint8_t len=11;
8
    
9
  ADCSR=0xc7;                          //ADC einschalten und konfigurieren; Teiler 128
10
  
11
  while (!(spg_utoa == 10))                  //arithm. Mittelwert bilden aus 10 Messungen
12
  {  
13
    loop_until_bit_is_clear(ADCSR,ADSC);  
14
    result += ADCW;
15
    ADCSR |= (1<<ADSC);                  //ADC-Einzelmessung neustarten
16
    spg_utoa++;
17
  }
18
  
19
  result /= 10;
20
  
21
  spg = result * 5000/1024;
22
    
23
  spg_utoa = spg % 1000;                    //Wert für Nachkommazahl umwandeln
24
  spg /= 1000;                        //Wert für Vorkommazahl umwandeln
25
  utoa( spg, spg_vor, 5 );                  //Werte in ASCII umrechnen
26
  utoa( spg_utoa, spg_nach, 5 );  
27
  
28
  sprintf(data, "\x1B""DL""\x1B""ZC""\x03""\x3F""%s"".""%s""\x0D", spg_vor, spg_nach);    //String zusammenfügen
29
  send_to_lcd(data, len);                          //String an LCD senden
30
}

Ich möchte die beiden letzten Zeilen aber in meiner main.c benutzen. 
Also habe ich die Funktion so umgewandelt, das die Variablen spg_vor und 
spg_nach mit Hilfe von Zeigern auch ausserhalb dieser Funktion zu 
Verfügung stehen. Wenn ich es denn dann richtig gemacht habe.

funktion.c:
1
void abfrage_spg_hc(char *spg_vor, char *spg_nach)
2
{
3
  uint16_t spg_utoa=0, spg=0;                  //Variablen für Funktion deklarieren
4
  float result=0;
5

6
  ADCSR=0xc7;                          //ADC einschalten und konfigurieren; Teiler 128
7
  
8
  while (!(spg_utoa == 10))                  //arithm. Mittelwert bilden aus 10 Messungen
9
  {  
10
    loop_until_bit_is_clear(ADCSR,ADSC);  
11
    result += ADCW;
12
    ADCSR |= (1<<ADSC);                  //ADC-Einzelmessung neustarten
13
    spg_utoa++;
14
  }
15
  
16
  result /= 10;
17
  
18
  spg = result * 5000/1024;
19
    
20
  spg_utoa = spg % 1000;                    //Wert für Nachkommazahl umwandeln
21
  spg /= 1000;                        //Wert für Vorkommazahl umwandeln
22
  utoa( spg, spg_vor, 5 );                  //Werte in ASCII umrechnen
23
  utoa( spg_utoa, spg_nach, 5 );  
24
}

Das steht jetzt unter anderem in meiner main.c:
1
char spg_vor[5], spg_nach[5];
2
uint8_t len=12;
3
char data[12];
4

5
abfrage_spg_hc(spg_vor, spg_nach);
6
sprintf(data, "\x1B""DL""\x1B""ZC""\x03""\x3F""%s"".""%s""\x0D", spg_vor, spg_nach);    //String zusammenfügen
7
send_to_lcd(data, len);                                    //String an LCD senden

Mein Display gibt aber nur in der ersten Variante Daten aus. Bei meiner 
Änderung wird nichts mehr ausgegeben. Ich hoffe ihr könnte mir bei 
diesem Problem helfen.
#2013363
Lesenswert?

Deine Arbeitsteilung der Funktionen ist nicht gut.

Besser ist es, wenn die Funktion abfrage_spg_hc nur das tut, was ihr 
Name verspricht. Sie misst die Spannung und liefert einen Wert(!) 
(keinen Text) zurück, der der Spannung entspricht.
Was mit dem Wert weiter passiert, ob der jetzt in einen String 
umgewandelt wird und angezeigt wird, oder ob der in eine Regelung geht 
oder .... hat diese Funktion nicht zu interessieren. Sie ist dafür 
zuständig die Spannung zu messen und den Spannungswert als Zahl zu 
liefern.
Insbesondere hat diese Funktion nicht die Aufgabe den Spannungswert in 
den Vorkomma und den Nachkommateil zu splitten.
#2013415
Lesenswert?

Bene Jan schrieb:
> @rufus:
> Könntest du das noch etwas anders ausdrücken? Ich verstehe noch nicht
> ganz was du meinst!?

Sieh dir einfach mal die Doku zu utoa an.
Insbesondere den dritten Parameter.
Der ist nicht das, was du denkst das er ist. Das ist NICHT die Größe des 
char-Buffers.

Allerdings brauchst du utoa hier gar nicht, wenn du

* die Funktion mit einer vernünftigen, brauchbaren Schnittstelle
  versiehst (wie schon weiter oben angedeutet)
* In main dann sowieso ein sprintf benutzt

Damit ist dann auch der Fehler, dass deine Anzeige ab und zu falsche 
Werte anzeigen wird, auch ad Acta gelegt.
utoa erzeugt dir keine führenden 0-en. Das solltest du nämlich bedenken, 
wenn du dich fragst, was den Unterschied zwischen 2.5 und 2.05 in Bezug 
auf den abgetrennten Nachkommaanteil ausmacht.


So in etwa
1
uint16_t abfrage_spg_hc()
2
{
3
  float   result=0;
4
  uint8_t i;
5

6
  ADCSR = 0xc7;                          //ADC einschalten und konfigurieren; Teiler 128
7
  
8
  for( i = 0; i < 10; ++i )
9
  {
10
    //arithm. Mittelwert bilden aus 10 Messungen
11

12
    loop_until_bit_is_clear(ADCSR,ADSC);  
13
    result += ADCW;
14
    ADCSR |= (1<<ADSC);                  //ADC-Einzelmessung neustarten
15
  }
16
  
17
  result /= 10;
18
  
19
  return result * 5000/1024;
20
}
21
 
22
....
23

24

25
  uint8_t len;
26
  char data[50];
27
  uint16_t spg;
28

29
  spg = abfrage_spg_hc();
30

31
  sprintf(data, "\x1B""DL""\x1B""ZC""\x03""\x3F""%d.03d""\x0D", spg / 1000, spg % 1000 );
32

33
  len = strlen( data );
34
  send_to_lcd(data, len);                                    //String an LCD senden

An deiner send_to_lcd Funktion solltest du auch noch arbeiten. Es ist 
unsinnig, die Länge eines Strings im Vorfeld feststellen zu müssen. Eine 
korrekte String-Ausgabefunktion braucht die Länge nicht explizit.

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