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.
> char data[12];
> sprintf(data, "\x1B""DL""\x1B""ZC""\x03""\x3F""%s"".""%s""\x0D"...
data ist etwas sparsam angelegt oder? Allein die festen Bestandteile
ohne die beiden %s-formatierten Strings fressen schon 11 Zeichen.
Ja schon, habs aber auch einige male vergrößert. Ist jetzt nur der
letzte Wert, den ich verwendet habe.
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.
Außerdem hast du offenbar nicht verstanden, welche Bedeutung der letzte
Parameter der Funktion utoa hat.
> char spg_vor[5], spg_nach[5];
Werden die Werte, die Du hiermit
> utoa( spg, spg_vor, 5 );
> utoa( spg_utoa, spg_nach, 5 );
versuchst umzurechnen (wie Stefan schon anmerkte, ist die 5 hier fehl am
Platz!), denn auch als Dezimalzahlen nie größer als 9999?
Wenn sie das werden, dann sind spg_vor und spg_nach nämlich zu klein.
@rufus:
Könntest du das noch etwas anders ausdrücken? Ich verstehe noch nicht
ganz was du meinst!?
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|