Forum: Compiler & IDEs Variable in einem String


von Daniel P. (daniel90)


Lesenswert?

Hallo,

ich habe ein kleines Problem an dem ich mir zurzeit die Zähne ausbeisse, 
und zwar möchte ich eine Variable in einen String einfügen und diesen 
dann mit Festkommaarithmetik in eine "Komma-Zahl" umwandeln, aber leider 
weis ich nicht wie ich das machen soll. Ich habe mir schon die Seite 
"http://www.mikrocontroller.net/articles/Festkommaarithmetik"; durch 
gelesen und es funktioniert auch soweit alles nur das mit der Variable 
geht nicht?!

Evtl habt Ihr eine Idee oder einen Denkanstoß für mich ?
1
void my_print_LCD(char* string, uint8_t start, uint8_t komma, uint8_t frac)
2
{
3
  uint8_t i;
4
  uint8_t flag=0;
5
  if (string[0]=='-')  lcd_data('-');  else lcd_data(' ');
6
  for (i=start; i<komma; i++)
7
  {
8
    if (flag==1 || string[1]!= '0')
9
    {
10
      lcd_data(string[i]);
11
      flag = 1;
12
    }
13
    else lcd_data(' ');
14
  }
15
  lcd_data('.');
16
  for (;i<(komma+frac); i++) lcd_data(string[i]);
17
}
18
19
char my_test[12]="1234\0";
20
  my_print_LCD(my_test, 0, 2, 2);

soweit funktioniert alles auf dem Display steht 12.34

nur möchte ich jetzt anstatt "1234" eine variable einsetzen. Habt ihr 
eine idee ?

von Georg G. (df2au)


Lesenswert?

Sieh dir mal itoa() und Co an. Da du nichts näheres zu deiner Skalierung 
sagst, kann man schlecht ein Beispiel schreiben.

von Daniel P. (daniel90)


Lesenswert?

Hey, danke für die Antwort mein Ziel ist es mit dem Adc einen Wert 
einlesen den dann umzurechnen und dann mit Komma zu versehen.  z.b 
Adc-wert 1023 dann umrechnen 1023*375/128 wäre 2997 möchte aber dann auf 
dem Display 29.97 stehen haben. Oder gibt es  da einen anderen Weg? Ich 
muss auch zugeben das ich noch am Anfang stehe aber bis jetzt  doch gut 
durch gekommen sind bin:-) Zur Zeit ändere ich noch die variable mit 
tasten da ich den adc noch erstmal aussen vor lasse.

von Rene H. (Gast)


Lesenswert?

Hallo Daniel,

ich weiss nicht, ob ich Deine Frage richtig verstanden habe, aber so wie 
ich das sehe, reicht ja das umrechnen ganz normal. Dann müsstest Du 
einen Float bekommen. Diesen musst Du dann noch in einen String pappen, 
da bietet sich sprintf an.

Grüsse,
René

von Rene H. (Gast)


Lesenswert?

Also so ähnlich:
1
    float wert;
2
    char wertStr[16];
3
4
    sprintf (wertStr, "%2.2f", wert);

Grüsse,
René

von Daniel P. (daniel90)


Lesenswert?

Hallo René

leider klappt das mit dem float und dem sprintf nicht so richtig, auf 
dem Display steht dann leider nichts, ich habe mal meinen ganzen code 
angehangen ich würde schon gerne die Festkomma-Funktion nutzen.
1
#define F_CPU 16000000UL
2
#include <avr/io.h>
3
#include "lcd-routines.h"
4
#include "lcd-routines.c"
5
#include <util/delay.h>
6
#include <stdlib.h>
7
#include <inttypes.h>
8
#include <stdint.h>
9
10
uint32_t i=0;
11
uint32_t t=0;
12
uint32_t d;
13
14
void initial (void)
15
{
16
  DDRD=0xE0;
17
}
18
19
void my_uitoa(uint32_t zahl, char* string)
20
{
21
  int8_t i;
22
  
23
  string[10]='\0';
24
  for(i=9; i>=0; i--)
25
  {
26
    string[i]=(zahl % 10) +'0';
27
    zahl /= 10;
28
  }
29
}
30
31
void my_round(char* string, uint8_t digit)
32
{
33
  uint8_t i;
34
  
35
  if (string[digit]>='5')
36
  {
37
    for (i=(digit-1); i>=0; i--)
38
    {
39
      string[i] +=1;
40
      if (string[i]<='9')
41
        break;
42
         else  
43
           string[i]='0';
44
      
45
    }
46
  }
47
  for (i=digit; i<10; i++) string[i] ='0';
48
}
49
  
50
51
void my_print_LCD(char* string, uint8_t start, uint8_t komma, uint8_t frac)
52
{
53
  uint8_t i;
54
  uint8_t flag=0;
55
  if (string[0]=='-')  lcd_data('-');  else lcd_data(' ');
56
  for (i=start; i<komma; i++)
57
  {
58
    if (flag==1 || string[1]!= '0')
59
    {
60
      lcd_data(string[i]);
61
      flag = 1;
62
    }
63
    else lcd_data(' ');
64
  }
65
  lcd_data('.');
66
  for (;i<(komma+frac); i++) lcd_data(string[i]);
67
}
68
69
int main(void)
70
{
71
          lcd_init ();
72
          initial();
73
      
74
  while(1)
75
  {
76
77
78
  if (PIND & (1<<2))
79
  {
80
    i++;
81
    PORTD = (1<<5);
82
    _delay_ms(1000);
83
  }
84
  else
85
  {
86
    PORTD = 0x00;
87
  }
88
  
89
  if (PIND & (1<<3))
90
  {
91
    i= i+10;
92
    
93
    PORTD = (1<<6);
94
    _delay_ms(200);
95
  } 
96
  else
97
  {
98
    PORTD = 0x00;
99
  }
100
  if (PIND & (1<<4))
101
  {
102
    u++;
103
    PORTD = (1<<5);
104
    _delay_ms(100);
105
  } 
106
  else
107
  {
108
    PORTD = 0x00;
109
  }
110
  
111
  t = i * 375 / 128;
112
  d = t + 1000;
113
114
    
115
    lcd_setcursor( 0, 1 );
116
    
117
    int test = d;
118
    {
119
      char Buffer[20];
120
      itoa( test, Buffer, 10 );
121
      lcd_string ( Buffer );
122
    }
123
        
124
    lcd_setcursor ( 0, 2 ); 
125
    
126
    int variable = i;
127
    {
128
      char Buffer[20];
129
      itoa( variable, Buffer, 10 );
130
      lcd_string ( Buffer );
131
    }
132
    lcd_data ( 'a');
133
    lcd_data ( 'd');
134
    lcd_data ( 'd');
135
  
136
  lcd_setcursor(0,3);
137
138
char my_test[12]="2997\0";
139
my_print_LCD(my_test, 0, 2, 2);
140
  
141
  }
142
  return 0;
143
    
144
}

von Karl H. (kbuchegg)


Lesenswert?

> Evtl habt Ihr eine Idee oder einen Denkanstoß für mich ?
>
> void my_print_LCD(char* string, uint8_t start, uint8_t komma, uint8_t frac)

Die Idee hinter diesem my_print_LCD ist es, so benutzt zu werden
1
char buf[8];
2
int  value = 1234;
3
4
  itoa( value, buf, 10 );
5
  my_print_LCD( buf, 0, 2, 2 );

d.h. das ist in erster Linie eine String-Ausgabe Funktion, die 
allerdings davon ausgeht, dass in diesem String Zahlendarstellungen 
enthalten sind. Ergo musst du dir aus deiner Zahl erst mal einen String 
machen. Und genau da kommt itoa ins Spiel.

Im übrigen hat diese Funktion keinerlei Vorkehrungen dafür, wenn die 
Formatierung nicht mit dem Text übereinstimmt. Um universell benutzbar 
zu sein, müsste man da also noch nachlegen.
1
   char buf[8];
2
   int value = 1234;
3
4
   sprintf( buf, "%2d.%02d", value / 100, value % 100 );
5
   lcd_string( buf );

ist einfacher, wenn du dir das bischen Mehrcode durch sprintf leisten 
kannst.



Edit:
Ich seh grad, du hast dir vom Original auch 2 Funktionen
1
void my_uitoa(uint32_t zahl, char* string)
2
void my_round(char* string, uint8_t digit)

mitkopiert.
Mit denen geht das. my_uitoa ist als Ersatz für itoa gedacht. Die sind 
zum Zusammenspiel mit deiner my_print_LCD gedacht.

von Lukas P. (lks)


Lesenswert?

Daniel Pfeiffer schrieb:
> Hey, danke für die Antwort mein Ziel ist es mit dem Adc einen Wert
> einlesen den dann umzurechnen und dann mit Komma zu versehen.  z.b
> Adc-wert 1023 dann umrechnen 1023*375/128 wäre 2997 möchte aber dann auf
> dem Display 29.97 stehen haben. Oder gibt es  da einen anderen Weg? Ich
> muss auch zugeben das ich noch am Anfang stehe aber bis jetzt  doch gut
> durch gekommen sind bin:-) Zur Zeit ändere ich noch die variable mit
> tasten da ich den adc noch erstmal aussen vor lasse.

Hi,

also hast du den Wert als int/uint vorliegen und möchtest den quasi 
durch 100 Teilen?!

int16_t upper = adc_value/100; //links vom komma
uint16_t lower = adc_value%100; //rechts vom komma

also bei 2997 wäre upper = 29 und lower = 97. Dann brauchst du das nur 
noch ausgeben.

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Edit:
> Ich seh grad, du hast dir vom Original auch 2 Funktionen
>
1
> void my_uitoa(uint32_t zahl, char* string)
2
> void my_round(char* string, uint8_t digit)
3
>
>
> mitkopiert.
> Mit denen geht das. my_uitoa ist als Ersatz für itoa gedacht. Die sind
> zum Zusammenspiel mit deiner my_print_LCD gedacht.

Aber Achtung
1
void my_uitoa(uint32_t zahl, char* string)
2
{
3
  int8_t i;
4
  
5
  string[10]='\0';
6
  for(i=9; i>=0; i--)
7
  {
8
    string[i]=(zahl % 10) +'0';
9
    zahl /= 10;
10
  }
11
}
will ganz offensichtlich ein char Array der Länge 11 haben, um dort den 
String reinzuschreiben.

von Daniel P. (daniel90)


Lesenswert?

Hallo wollte mich für eure Hilfe bedanken mit "sprint" hat alles super 
geklappt :) danke.

Gruß Daniel

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.