Forum: Compiler & IDEs Variablen uint16_t hat falsche Werte


von Matthias K. (gidarrnmatze)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
für unsere Abschlussarbeit entwickeln wir ein Messgerät.

Allerdings weiß ich momentan nicht mehr weiter:

Ich weise in meiner Funktion "Einstellen" der Variablen uint16_t 
parameter[4] Werte zu.
die Variablen initialisiere ich mit 0 am Anfang.

ich lasse mir die Variablen parameter[1] und [2] ausgeben.
in der Funktion "Einstellen" sind diese noch in Ordung.

Wenn ich aber nun zurückkehre ins "main.c" haben die Werte 
Parameter[0],[1],[3] in meiner Testausgabe irgendwelche Werte. Einzig 
Parameter [2] ist in Ordnung.

Ich bin absolut ratlos....

von troll (Gast)


Lesenswert?

Das gleiche Problem wenn du die Reihenfolge der Variablen in der 
Headerdatei vertauschst?

von Roland (Gast)


Lesenswert?

Stack-Überlauf..?

von Timmo H. (masterfx)


Lesenswert?

Wollte gerade sagen...
bist du dir sicher, dass du die ganzen Strings z.B.
1
  uart_puts("\033[2J");   // clear screen
2
  uart_puts("\n\r*********************************************************");
3
  uart_puts("\n\r************************HAUPT MENUE**********************");
4
  uart_puts("\n\r*********************************************************");
5
  uart_puts("\n\rBitte waehlen Sie:\n\r1) Parameter einstellen\n\r2) Messung starten\n\r3) Werte Auslesen\n\r4) EEPROM loeschen");
im RAM haben willst? Schau dir mal Progmem an: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

Aber auch selbst damit sind die ganzen "*" absolute 
Speicherverschwendung, da kann man lieber eine Funktion schreiben 
"print_stars(uint8_t numberof_stars)..."

Um welchen Controller handelt es sich überhaupt?

von Matthias K. (gidarrnmatze)


Lesenswert?

Hallo zusammen,

ich habe jetzt mal Spaßhalber folgendes gelöscht. (wie Timmo 
vorgeschlagen)
1
   uart_puts("\033[2J");   // clear screen
2
  uart_puts("\n\r*********************************************************");
3
  uart_puts("\n\r************************HAUPT MENUE**********************");
4
  uart_puts("\n\r*********************************************************");

nun funktioniert es wieder....
was kann der Hintergrund sein? der von Roland genannte Stacküberlauf?

PS: der Controller ist ein ATMEGA 16

von (prx) A. K. (prx)


Lesenswert?

Wieviel RAM wird vom Programm verwendet?

von Walter S. (avatar)


Lesenswert?

Matthias Kugler schrieb:
> was kann der Hintergrund sein? der von Roland genannte Stacküberlauf?

wahrscheinlich,
ist nun Mal ein mikrocontroller und da muss man sich schon Gedanken um 
den Speicherverbrauch machen

von Roland (Gast)


Lesenswert?

Vermutlich eine Mischung aus zu viel RAM-Verbrauch und zu kleinem Stack.

Deklariere deine Strings als "const", dann landen die (bei korrekter 
Implemetierung des Kompilers) erst mal im ROM und kosten weniger RAM.

von Timmo H. (masterfx)


Lesenswert?

Roland schrieb:
> Deklariere deine Strings als "const", dann landen die (bei korrekter
> Implemetierung des Kompilers) erst mal im ROM und kosten weniger RAM.
Nicht beim AVR.
Bei AVR-GCC verwendet man dafür PROGMEM bei IAR __flash
Um die Strings zu lesen kann man aber nicht einfach printf nehmen 
sondern printf_P bzw. eine selbst programmierte Funktion wie uart_puts_P 
via pgm_read_byte

Alleine diese 4 Zeilen fressen schonmal ~280 Bytes. Und wenn man sich 
die ganzen anderen Strings so ansieht, dann sind auch schon fast die 1K 
RAM voll und der Stack braucht ja auch noch ein bissl.

Auf einem µC kann man nunmal nicht einfach wie auf dem PC programmieren, 
die Ressourcen sind da nunmal begrenzt. Also Strings kurz halten und 
brav im Flash liegen lassen via PROGMEM bzw. PSTR

von Karl H. (kbuchegg)


Lesenswert?

Timmo H. schrieb:

> Also Strings kurz halten und
> brav im Flash liegen lassen via PROGMEM bzw. PSTR

... oder die ganze Sache noch etwas intelligenter (und fauler :-) 
angehen.
1
void printStars( uint8_t number )
2
{
3
  uint8_t i;
4
  for( i = 0; i < number; i++ )
5
    uart_putc( '*' );
6
}
7
8
void printStarLine( uint8_t number )
9
{
10
  printStars( number );
11
  uart_puts( "\r\n" );
12
}
13
14
void printHeader( uint8_t number, const char* title )
15
{
16
  uint8_t len = strlen( title );
17
18
  uart_puts("\033[2J");   // clear screen
19
  printStarLine( number );
20
  printStars( len / 2 );
21
  uart_puts( title );
22
  printStars( len - len/2 );
23
  uart_puts( "\r\n" );
24
  printStarLine( number );
25
}

Dann erzeugt ein
1
  ...
2
  printHeader( 80, "HAUPT MENUE" );
3
  ...
... den kompletten Kopf, wobei man dann den Vorteil hat, dass alle 
Menüköpfe aller Menüs immer gleich aussehen und wenn einem dieser Kopf 
nicht mehr gefällt man nur an einer einzigen Stelle den Hebel ansetzen 
muss. Letzteres könnte zb dann interessant werden, wenn er den "special 
graphics character set" des VT100 entdeckt :-)

von Roland (Gast)


Lesenswert?

Timmo H. schrieb:
> Roland schrieb:
>> Deklariere deine Strings als "const", dann landen die (bei korrekter
>> Implemetierung des Kompilers) erst mal im ROM und kosten weniger RAM.
> Nicht beim AVR.
> Bei AVR-GCC verwendet man dafür PROGMEM bei IAR __flash
> Um die Strings zu lesen kann man aber nicht einfach printf nehmen
> sondern printf_P bzw. eine selbst programmierte Funktion wie uart_puts_P
> via pgm_read_byte...

Urks. Da rächt sich wohl die Harvard-Architektur in einem 
Mikrokontroller...

Roland

von Timmo H. (masterfx)


Lesenswert?

Alles reine Gewöhnungssache

von Matthias K. (gidarrnmatze)


Lesenswert?

HAllo zusammen,

vielen Dank für Eure Hilfe. Ich habe etwas nachgelesen und hoffe ich 
habe es verstanden:
Durch deklarieren eins Strings mit char xyz[] wird dieser beim Starten 
direkt aus dem Flash in den SRAM geladen.

Zu Peters Funktion:

was passiert bei folgender Zeile:
1
 void printHeader( uint8_t number, const char* title )

Der Funktion wird ein char-Arrray übergeben, die Funktion erwartet einen 
Zeiger auf das erste Element, da es mit const angegeben ist, sucht der 
AVR im Flash-Speicher danach?

@ Roland was hat das mit der Harvard-Technologie zu tun?
@ A. K.  Woher sehe ich wieviel RAM das Programm belegt?

Vielen Dank für Eure Hilfe.
Matthias

von Karl H. (kbuchegg)


Lesenswert?

Matthias Kugler schrieb:
> HAllo zusammen,
>
> vielen Dank für Eure Hilfe. Ich habe etwas nachgelesen und hoffe ich
> habe es verstanden:
> Durch deklarieren eins Strings mit char xyz[] wird dieser beim Starten
> direkt aus dem Flash in den SRAM geladen.

JEDER String wird aus dem Flash ins SRAM geladen.
Es sei denn du markierst ihn explizit als 'bleibt im Flash'.

>
1
 void printHeader( uint8_t number, const char* title )
>
> Der Funktion wird ein char-Arrray übergeben,

In C werden keine Arrays übergeben. Die Funktion kriegt einen Pointer 
auf den Anfang des Strings. Immer. Das ist die Art und Weise, wie in C 
Arrays übergeben werden.

->  du brauchst ein C-Buch!


> Zeiger auf das erste Element, da es mit const angegeben ist, sucht der
> AVR im Flash-Speicher danach?

Nein.
Das const ist nur die Zusicherung an den Aufrufer, dass die Funktion 
nicht versuchen wird, das worauf der Zeiger zeigt zu verändern. Dies ist 
insforn wichtig, weil ja eine String-Konstante "Haus" für dich als 
Programmierer unveränderbar ist.

Auf dem AVR-GCC ist mit dem const keinerlei Speicherzuordnung (Flash 
oder SRAM) verknpft.

von Matthias K. (gidarrnmatze)


Lesenswert?

Karl Heinz Buchegger schrieb:
>> Der Funktion wird ein char-Arrray übergeben,
>
> In C werden keine Arrays übergeben. Die Funktion kriegt einen Pointer
> auf den Anfang des Strings. Immer. Das ist die Art und Weise, wie in C
> Arrays übergeben werden.
Tschuldigung, das ist mir klar, ich hab mich falsch ausgedrückt.

das "bleibe im Flash" passiert dann durch "PROGMEM" ??

Danke für die Erklärung zu const, allerdings verstehe ich noch nicht 
ganz den Nutzen.
Der Aufrufet weiß, das die Funktion "printHeader" die String Konstante 
nicht ändert. Aber das ist doch im Vorfeld schon klar, da ich das ja als 
Programmierer so programmiert habe, oder?

von Karl H. (kbuchegg)


Lesenswert?

Matthias Kugler schrieb:

> Der Aufrufet weiß, das die Funktion "printHeader" die String Konstante
> nicht ändert. Aber das ist doch im Vorfeld schon klar, da ich das ja als
> Programmierer so programmiert habe, oder?

Dann bist du der erste Programmierer, der mir begegnet, der unfehlbar 
ist.

1
void printHeader( uint8_t number, const char* title ) 
2
{
3
  title[0] = 'a';
4
}
und schon klopft dir der Compiler auf die Finger, weil du dein 
'Versprechen' nicht einhältst.
Ein Versprechen, auf das sich der Aufrufer hier
1
   printHeader( "Hallo" );
blind verlässt.

von Karl H. (kbuchegg)


Lesenswert?

Matthias Kugler schrieb:

> das "bleibe im Flash" passiert dann durch "PROGMEM" ??

Ja.
Oder bei einem neuern AVR-GCC dadurch, dass man den Modifier _flash 
vergibt.

AVR-GCC-Tutorial
Abschnitt: 15.2 Programmspeicher_(Flash)

von Matthias K. (gidarrnmatze)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Dann bist du der erste Programmierer, der mir begegnet, der unfehlbar
> ist.

:-) Das würde ich nie behaupten, ich wollte nur den Hintergrund 
verstehen.

Vielen Dank, für die Infos.

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.