Forum: Mikrocontroller und Digitale Elektronik Probleme mit C Code und hilfe bei änderung


von Nadine W. (nadine_w)


Lesenswert?

Hallo,

ich bin nicht so bewandt was C angeht aber bisher hat alles geklappt. 
Nunja. ich habe nun Probleme mit Strings.

Ich habe mit folgende Funktion gebastelt:
1
#include "main.h"
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <stdint.h>
5
#include "mylcd.h"
6
#include <avr/interrupt.h>
7
#include <stdint.h>
8
#include <inttypes.h>
9
#include <avr/pgmspace.h>
10
#include <stdlib.h>
11
#include <stdio.h>
12
#include <avr/eeprom.h>
13
14
int display_run = 0;
15
extern char temp_a;
16
extern char temp_b;
17
extern char temp_c;
18
extern int stunde;
19
extern int minute;
20
char Buffer[20];
21
22
char temp_log_data_1_time[10];
23
char temp_log_data_2_time[10];
24
char temp_log_data_3_time[10];
25
char temp_log_data_4_time[10];
26
char temp_log_data_5_time[10];
27
28
char temp_log_data_1_temp1;
29
char temp_log_data_1_temp2;
30
char temp_log_data_1_temp3;
31
32
char temp_log_data_2_temp1;
33
char temp_log_data_2_temp2;
34
char temp_log_data_2_temp3;
35
36
char temp_log_data_3_temp1;
37
char temp_log_data_3_temp2;
38
char temp_log_data_3_temp3;
39
40
char temp_log_data_4_temp1;
41
char temp_log_data_4_temp2;
42
char temp_log_data_4_temp3;
43
44
char temp_log_data_5_temp1;
45
char temp_log_data_5_temp2;
46
char temp_log_data_5_temp3;
47
48
void write_temp_log(void) {
49
50
  *temp_log_data_5_time = *temp_log_data_4_time;
51
  temp_log_data_5_temp1 = temp_log_data_4_temp1;
52
  temp_log_data_5_temp2 = temp_log_data_4_temp2;
53
  temp_log_data_5_temp3 = temp_log_data_4_temp3;
54
55
  *temp_log_data_4_time = *temp_log_data_3_time;
56
  temp_log_data_4_temp1 = temp_log_data_3_temp1;
57
  temp_log_data_4_temp2 = temp_log_data_3_temp2;
58
  temp_log_data_4_temp3 = temp_log_data_3_temp3;
59
60
  *temp_log_data_3_time = *temp_log_data_2_time;
61
  temp_log_data_3_temp1 = temp_log_data_2_temp1;
62
  temp_log_data_3_temp2 = temp_log_data_2_temp2;
63
  temp_log_data_3_temp3 = temp_log_data_2_temp3;
64
65
  *temp_log_data_2_time = *temp_log_data_1_time;
66
  temp_log_data_2_temp1 = temp_log_data_1_temp1;
67
  temp_log_data_2_temp2 = temp_log_data_1_temp2;
68
  temp_log_data_2_temp3 = temp_log_data_1_temp3;
69
70
  sprintf(temp_log_data_1_time, "foo");
71
  temp_log_data_1_temp1 = temp_a;
72
  temp_log_data_1_temp2 = temp_b;
73
  temp_log_data_1_temp3 = temp_c;
74
}

In der main führe ich folgendes aus:
1
.....
2
  while(1)
3
  {
4
    write_temp_log();
5
6
    read_temps();
7
8
    itoa(temp_log_data_1_time,Buffer,10);
9
    lcd_set_cursor(7,LINE3);
10
          lcd_puts(small_font,Buffer);
11
.....

Auf dem Display erhalte ich in LINE3 anstatt "foo" 102 angezeigt...

ich möchte allerdings folgendes:
1
sprintf(temp_log_data_1_time, "%d:%d", stunde, minute);

wenn ich nur
1
sprintf(temp_log_data_1_time, "%d", minute);
oder
1
sprintf(temp_log_data_1_time, "%d", stunde);
mache dann bekomme ich in LINE3 auf dem Display die Stunde oder die 
Minute angezeigt.... in
1
temp_log_data_1_time
soll aber die Zeit in Format SS:MM stehen, also z.b. 17:10

wenn ich nun versuche das ganze direkt da rein zu schreiben, also
1
temp_log_data_1_time = "17:10";

bzw
1
*temp_log_data_1_time = "17:10";

dann bekomme ich als Ausgabe auf dem Display "48" angezeigt.

Was mache ich falsch?

Dann ist das ganze ja ziemlich lang.. kann an das nicht irgendwie ein 
ein Array packen?

Also das z.b.
1
LOG_DATA[0][0] = UHRZEIT
2
LOG_DATA[0][1] = TEMPERATUR1
3
LOG_DATA[0][2] = TEMPERATUR2
4
LOG_DATA[0][3] = TEMPERATUR3
5
6
LOG_DATA[1][0] = 2te UHRZEIT
7
LOG_DATA[1][1] = 2te TEMPERATUR1
8
LOG_DATA[1][2] = 2te TEMPERATUR2
9
LOG_DATA[1][3] = 2te TEMPERATUR3

usw...

Ich danke euch vielmals.

P.S.:

Falls wichtig, beim compilieren bekomme ich keine Fehler oder Warnings..
1
make all
2
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 main.c -o main.o
3
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 mylcd.c -o mylcd.o
4
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 gen.c -o gen.o
5
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 ds18S20.c -o ds18S20.o
6
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 display.c -o display.o
7
avr-gcc -c -Os -std=gnu99 -mmcu=atmega128 read_temps.c -o read_temps.o
8
avr-gcc  -mmcu=atmega128 main.o mylcd.o gen.o ds18S20.o display.o read_temps.o -o main.elf
9
avr-objcopy -O ihex -j .data -j .text main.elf main.hex
10
avr-objcopy -O ihex -j .eeprom --change-section-lma .eeprom=1 main.elf main_eeprom.hex

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nadine W. schrieb:
> *temp_log_data_5_time = *temp_log_data_4_time;

Das macht recht sicher nicht das, was Du erzielen willst.

> Auf dem Display erhalte ich in LINE3 anstatt "foo" 102 angezeigt...

Wenn Du itoa aufrufst, und dem als Quelle einen Puffer übergibst, in dem 
"foo" steht, ...

Das ist wirr.

> Dann ist das ganze ja ziemlich lang.. kann an das nicht irgendwie ein
> ein Array packen?

Du könntest die zusammenhängenden Daten in eine Struktur packen, und 
ein Array vom Typ dieser Struktur anlegen.

von zitter_ned_aso (Gast)


Lesenswert?

Nadine W. schrieb:
> char temp_log_data_4_time[10];
> char temp_log_data_5_time[10];
> ....
> ....
> ....
>   *temp_log_data_5_time = *temp_log_data_4_time;

Was  bedeutet das?




Nadine W. schrieb:
> char temp_log_data_1_time[10];
> char temp_log_data_2_time[10];
> char temp_log_data_3_time[10];
> char temp_log_data_4_time[10];
> char temp_log_data_5_time[10];

wäre

char temp_log_data{5][10];

nicht besser?

von Nadine W. (nadine_w)


Lesenswert?

ich will das ganze im timer laufen lassen alle 30min sodass ich mir 
immer die letzten 5 werte ansehen kann....

und der soll dann eben immer einen "weiter rücken" also eintrag 1 nach 
2, 2 nach 3, 3 nach 4 und den neusten eben in 1

von zitter_ned_aso (Gast)


Lesenswert?

Nadine W. schrieb:
> wenn ich nun versuche das ganze direkt da rein zu schreiben, also
> temp_log_data_1_time = "17:10";
>
> bzw
> *temp_log_data_1_time = "17:10";
>
> dann bekomme ich als Ausgabe auf dem Display "48" angezeigt.

Das soll ja ein String sein.

Nadine W. schrieb:
> char temp_log_data_1_time[10];


Also z.B. mit
1
strcpy(temp_log_blablabla, "17:10");
arbeiten

von Vn N. (wefwef_s)


Lesenswert?

Du suchst einen Ringbuffer: 
https://www.mikrocontroller.net/articles/FIFO
Und Strukturen: https://www.mikrocontroller.net/articles/Strukturen_in_C
Du willst auch statt sprintf viel lieber itoa() and friends: 
https://www.mikrocontroller.net/articles/FAQ#sprintf.28.29

Ach, eigentlich willst du ein C-Buch und das Wiki durcharbeiten.

von zitter_ned_aso (Gast)


Lesenswert?

Nadine W. schrieb:
> und der soll dann eben immer einen "weiter rücken" also eintrag 1 nach
> 2, 2 nach 3, 3 nach 4 und den neusten eben in 1

eine Liste wäre wohl dafür geeignet. Z.B. die neuen Werte vorne 
einfügen. Dann muss man nichst "schieben".

von Nadine W. (nadine_w)


Lesenswert?

zitter_ned_aso schrieb:
> Also z.B. mitstrcpy(temp_log_blablabla, "17:10");
> arbeiten

Alles auch schon versucht

gen.c: In function ‘write_temp_log’:
gen.c:71:3: warning: implicit declaration of function ‘strcpy’ 
[-Wimplicit-function-declaration]
   strcpy(*temp_log_data_1_time, "17:10");
   ^


oder

gen.c: In function ‘write_temp_log’:
gen.c:71:3: warning: implicit declaration of function ‘strcpy’ 
[-Wimplicit-function-declaration]
   strcpy(temp_log_data_1_time, "17:10");
   ^

von zitter_ned_aso (Gast)


Lesenswert?

für strcpy(...) braucht man eine entsprechende Header-Datei.

#include <string.h>

Nadine W. schrieb:
> strcpy(*temp_log_data_1_time, "17:10");

warum temp_log.... mit Stern?

Hier ein kostenloses Buch zu C:

http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/

von S. R. (svenska)


Lesenswert?

zitter_ned_aso schrieb:
> für strcpy(...) braucht man eine entsprechende Header-Datei.

Und doppelt einbinden bringt für die existierenden Header auch nichts.

von zitter_ned_aso (Gast)


Lesenswert?

dann halt nicht inkludieren

von leo (Gast)


Lesenswert?

Nadine W. schrieb:
> gen.c:71:3: warning: implicit declaration of function ‘strcpy’
> [-Wimplicit-function-declaration]
>    strcpy(temp_log_data_1_time, "17:10");
>    ^

Dir wurde ja schon gesagt, dass du eine Headerdatei brauchst. Lerne auf 
die Fehlermeldungen und Warnungen zu ragieren.

E.g. im Terminal:
1
$ man strcpy

Bzw. auch im Browser
https://www.google.com/search?q=man+strcpy

Dort findest du u.a. auch die Header:
1
#include <string.h>
2
3
char *strcpy(char *dest, const char *src);
4
...

HTH
leo

von Nadine W. (nadine_w)


Lesenswert?

ja.. habe ich gerade auch alles getestet...

ich habe jetzt alles durch.. ich bekommen es auch OHNE Warnings und 
Fehler...

aber die Ausgabe ist kein Text... sondern aus 17:10 was er anzeigen soll 
zeigt er auf einmal 12336 an...

Also ich bekomme eine ausgabe... nur anstatt "foo" eben 102... 102 wäre 
"f" aber "o" und "o" fehlt usw usw...

da ist einfach irgendwo der Wurm drinne....

Ein
1
temp_log_data_1_time = 35;

das geht auch... dann sehe ich 35 auf dem Display... oder aber

1
temp_log_data_1_time = 9999;

dann sehe ich 9999 auf dem Display....

aber

1
temp_log_data_1_time = "foo";

wird zu

102 statt foo

.......

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nadine W. schrieb:
> Also ich bekomme eine ausgabe... nur anstatt "foo" eben 102... 102 wäre
> "f" aber "o" und "o" fehlt usw usw...

Kein Wunder, itoa wertet nur einen übergebenen Wert aus. Daß hinter dem 
Wert noch andere stehen, interessiert itoa nicht.

> da ist einfach irgendwo der Wurm drinne....

Lies. Ein. C-Buch.

von Dirk B. (dirkb2)


Lesenswert?

Rufus Τ. F. schrieb:

> Lies. Ein. C-Buch.

Arbeite es durch. Nur lesen reicht meist nicht.

von Dirk B. (dirkb2)


Lesenswert?

Nadine W. schrieb:
> ich habe jetzt alles durch.. ich bekommen es auch OHNE Warnings und
> Fehler...

Ist immer noch der Aufruf von itoa drin?
wie sieht der aus?

von zitter_ned_aso (Gast)


Lesenswert?

Nadine W. schrieb:
> temp_log_data_1_time = 9999;
>


bei char-Datentyp?

von Nadine W. (nadine_w)


Lesenswert?

zitter_ned_aso schrieb:
> Nadine W. schrieb:
>> temp_log_data_1_time = 9999;
>>
>
>
> bei char-Datentyp?

Ja alles genau so wie der Code ist... Ich mache einfach
1
temp_log_data_1_time = 9999;

Und dann habe ich auf dem Display 9999 als Ausgabe....

Das Display ist ein ks0108 wenn das weiter hilft.

Aber wenn ich in der main.c
1
itoa(temp_log_data_1_temp1,Buffer,10);
2
lcd_set_cursor(7,LINE3);
3
lcd_puts(small_font,Buffer);

Also die Temperaturen von temp1 bis temp3 durchgehen bekomme ich die 
korrekten Werte dargestellt...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nadine W. schrieb:
> Ja alles genau so wie der Code ist... Ich mache einfach

Das ist mehr als unwahrscheinlich. Eine char-Variable kann numerische 
Werte im Bereich von 0 bis 255 aufnehmen, wenn sie ohne Vorzeichen 
interpretiert wird, oder aber Werte zwischen -128 und 127, wenn sie mit 
Vorzeichen interpretiert wird.

von Dirk B. (dirkb2)


Lesenswert?

Nadine W. schrieb:
> Ja alles genau so wie der Code ist... Ich mache einfach
> temp_log_data_1_time = 9999;

temp_log_data_1_time ist doch ein char-Array.

Einem Array kann man so keinen Wert zuweisen.

Wenn es ein char-Pointer wäre, sollte es eine Warnung geben.

von Lass es besser sein (Gast)


Lesenswert?

Was hilft ihr solchen Leuten eigentlich, wenn sie nicht mal die 
grundregelsten Grundlagen der Grundlagen mitbringen und schon ein 
Raumschiffe steuern wollen, wenn sie nicht mal wissen was ein char ist?

Euch kann man echt nimmer helfen, sorry.

von foobar (Gast)


Lesenswert?

> char Buffer[20];
> char temp_log_data_1_time[10];
> char temp_log_data_1_temp1;
>
> itoa(temp_log_data_1_temp1, Buffer, 10);
> lcd_puts(small_font, Buffer);

Ich denke, du bist etwas verwirrt und deine beschissene Namensvergabe 
hilft da auch nicht gerade.

itoa wandelt eine (int-)Zahl nach Ascii, erster Parameter ist die Zahl, 
zweiter der Puffer, in den er die Ascii-Zeichen reinschreibt, dritter 
die Basis, in der die Umwandlung durchgeführt werden soll.  Also, 
temp_log_data_1_temp1 ist Input, Buffer ist Output.

lcd_puts gibt einen Text aus, erster Parameter ist die Fontgröße, 
zweiter der Puffer mit dem Text.

> sprintf(temp_log_data_1_time, "%d:%d", stunde, minute);

Dies schreibt den formatierten Text in den Puffer temp_log_data_1_time. 
Dann muß auch ein 'lcd_puts(small_font, temp_log_data_1_time);' folgen. 
Alternativ kannst du auch mit 'strcpy(Buffer, temp_log_data_1_time);' 
die Uhrzeit in den Buffer kopieren und den lcd_puts mit Buffer machen.

Tipp: Mach dir Strukturen, z.B.:
1
struct temp {
2
    uint8_t stunde, minute;
3
    int8_t temp1, temp2, temp3;
4
};
5
6
#define LOGSIZE 5
7
struct temp log[LOGSIZE];
8
9
void write_temp_log()
10
{
11
    for (uint8_t i = LOGSIZE-1; i > 0; --i)
12
        log[i] = log[i-1];
13
    //oder: memmove(log+1, log+0, (LOGSIZE-1)*sizeof(*log));
14
}
15
16
...
17
    while(1)
18
    {
19
        char buf[32];
20
21
        write_temp_log();
22
        read_temps();  // fuellt 'log[0]'
23
24
        for (uint8_t i = 0; i < LOGSIZE; ++i)
25
        {
26
            sprintf(buf, "%02u:%02u %3d %3d %3d",
27
                           log[i].stunde, log[i].minute,
28
                           log[i].temp1, log[i].temp2, log[i].temp3);
29
            lcd_set_cursor(0, LINE2 + i);
30
            lcd_puts(small_font, buf);
31
        }
32
    }

von ... (Gast)


Lesenswert?

Ich nehme das mal etwas auseinander.
1
char temp_log_data_1_time[10];
2
temp_log_data_1_time = "foo";

temp_log_data_1_time ist ein Zeiger auf das erste Element eines 
Char-Arrays.
Dieser sollte auf einem AVR 16-Bit lang sein.

itoa wird Dir nur diese Zeigeradresse in einen String wandeln.

Natürlich kannst Du diesen Zeiger auch selber setzen:
1
temp_log_data_1_time = 9999;

Das ist aber kein String. "17:10" wirst Du so nicht ablegen können.

von ... (Gast)


Lesenswert?

... schrieb:
> itoa wird Dir nur diese Zeigeradresse in einen String wandeln.

Ich meine natürlich, so wie Du es benutzt.

von ... (Gast)


Lesenswert?

Nadine W. schrieb:
> *temp_log_data_5_time = *temp_log_data_4_time;

Und damit kopierst Du nur das erste Zeichen des CHAR-Arrays.

von Dirk B. (dirkb2)


Lesenswert?

... schrieb:
> temp_log_data_1_time ist ein Zeiger auf das erste Element eines
> Char-Arrays.

Nein. Das ist die Adresse von dem ersten Element des Arrays

> Natürlich kannst Du diesen Zeiger auch selber setzen:

Nein.
Eine Arrayadresse kann man nicht ändern.

Ein Array ist kein Pointer. Ein Pointer ist kein Array.

von Stefan F. (Gast)


Lesenswert?

Dirk B. schrieb:
>> temp_log_data_1_time ist ein Zeiger auf das erste Element eines
>> Char-Arrays.
> Nein. Das ist die Adresse von dem ersten Element des Arrays

Ist das nicht das Gleiche?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Ist das nicht das Gleiche?



Nein, in diesem Fall ist es das nicht. Zwar verhält es sich wie ein 
Zeiger auf das erste Element eines Arrays, und sobald man es einer 
Funktion übergibt, ist es einer, aber so, wie Du es da hingeschrieben 
hast, ist es kein Zeiger, sondern tatsächlich ein Array.

Den Unterschied zeigt Dir der sizeof -Operator:
1
void test(char[] p)
2
{
3
  printf("sizeof = %d\n", sizeof p);
4
}
5
6
void main(void)
7
{
8
  char array[10];
9
10
  printf("sizeof = %d\n", sizeof array);
11
12
  test(array);
13
}

von Nadine W. (nadine_w)


Lesenswert?

ein
1
sprintf(temp_log_data_1_time, "%s:%s", stunde, minute);

Also %d mit %s tauschen brauchte mich zum Erfolg...

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Stefanus F. schrieb:
> Dirk B. schrieb:
>>> temp_log_data_1_time ist ein Zeiger auf das erste Element eines
>>> Char-Arrays.
>> Nein. Das ist die Adresse von dem ersten Element des Arrays
>
> Ist das nicht das Gleiche?

Nein.
Eine Arrayadresse kann man nicht ändern.
Einen Zeiger schon.

temp_log_data_1_time++; geht beim Array nicht.

temp_log_data_1_time = Null; geht auch nicht.

Ein Array ist kein Pointer. Ein Pointer ist kein Array.

von Dirk B. (dirkb2)


Lesenswert?

Nadine W. schrieb:
> ein
>
>
1
> sprintf(temp_log_data_1_time, "%s:%s", stunde, minute);
2
>
>
> Also %d mit %s tauschen brauchte mich zum Erfolg...

Muhaha.

Ein Integer ist kein Pointer.

Ohne Warnungen zu compilieren bedeutet nicht, die Warnungen 
abzuschalten, sondern die Ursache der Warnungen zu beheben.

von stdc (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Den Unterschied zeigt Dir der sizeof -Operator:
>
>
1
> void test(char[] p)
2
> {
3
>   printf("sizeof = %d\n", sizeof p);
4
> }
5
> 
6
> void main(void)
7
> {
8
>   char array[10];
9
> 
10
>   printf("sizeof = %d\n", sizeof array);
11
> 
12
>   test(array);
13
> }
14
>

Ich verstehe, was du sagen möchtest. Aber ich glaube, dass deine 
Begründung falsch ist/der Vergleich hinkt:
1
char[]
 als Typ für einen Parameter ist lediglich syntaktischer Zucker und wird 
identisch zu
1
char*
 behandelt. Du kannst auch
1
char p[10]
 als Parametertyp verwenden, doch sizeof ist immer noch die Größe eines 
pointers (-Wall wirft hier sogar eine Warnung):
1
$ avr-gcc -O3 -Wall -o foo foo.c 
2
foo.c: In function ‘fun’:
3
foo.c:7:26: warning: ‘sizeof’ on array function parameter ‘p’ will return size of ‘char *’ [-Wsizeof-array-argument]
4
     printf("%d\n", sizeof(p));
5
                          ^
6
foo.c:5:10: note: declared here
7
 fun(char p[10])
8
          ^
9
$ avr-gcc -dumpversion
10
5.4.0

von stdc (Gast)


Lesenswert?

stdc schrieb:
> Ich verstehe, was du sagen möchtest. Aber ich glaube, dass deine
> Begründung falsch ist/der Vergleich hinkt:

Will sagen: Auch wenn die Syntax suggeriert, man könne ein Array als 
Parameter übergeben, geht es trotzdem nicht.

von Nop (Gast)


Lesenswert?

stdc schrieb:

> Will sagen: Auch wenn die Syntax suggeriert, man könne ein Array als
> Parameter übergeben, geht es trotzdem nicht.

Richtig. Man benutzt das nur, wenn die Funktion ein Array fester Größe 
verwendet, damit das schon anhand des Prototypen für den aufrufenden 
Programmierer ersichtlich ist. Also zur Doku.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

stdc schrieb:
> Aber ich glaube, dass deine Begründung falsch ist/der Vergleich hinkt:

Nein, denn genau das ist der Punkt, auf den ich hinauswill.

Dirk hat aber schon das wesentliche geschrieben:

>> Ist das nicht das Gleiche?
>
> Nein.
> Eine Arrayadresse kann man nicht ändern.
> Einen Zeiger schon.
>
> temp_log_data_1_time++; geht beim Array nicht.
>
> temp_log_data_1_time = Null; geht auch nicht.
>
> Ein Array ist kein Pointer. Ein Pointer ist kein Array.

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.