Forum: Compiler & IDEs Speicherprobleme mit LCD Ansteuerung


von Michael (Gast)


Lesenswert?

Hallo,

ich habe mir bei Pollin ein LCD (16x2) bestellt und erfolgreich an 
meinen Atmega8 gehängt. Ich habe mir dazu die LCD Libary von Peter 
Fleury´s verwendet und mir ein kleines Programm mit irgendwelchem 
Beispiel Text geschrieben.

Mittels eines Linux Shell Skriptes lasse kann ich mir einen beliebig 
langen Text in eine Switch Case C Routine automatisch ändern lassen, 
auch das funktioniert wunderbar.

Die einzige Aufgabe meines Atmega ist, mit jeweils 2 Tastern langsames 
Vor- und Rückblättern sowie schnelles Vor- und Rückblättern des Textes 
im Display zu ermöglichen. Dabei habe ich allerdings ein Problem: Sobald 
ich mehr als

Nur ein Problem habe ich: Sobald ich mehr als 29 Case aufrufe 
unterbringen will, ist der Data Speicher zu über 100% gefüllt. Der 
Programmspeicher ist erst zu ca. 25% gefüllt. Ich habe gelesen das 
Statische Strings die nicht verändert werden sollen in das EEPROM 
ausgelagert werden können, wenn ich das richtig sehe, ist dies aber nur 
ein halbes k groß und ich habe leider nirgendwo hinweise darauf gefunden 
wie man das bei der lcd_puts() Funktion machen könnte.

Vielleicht kann mir jemand helfen wie ich diesen C-Code weiter 
optimieren kann so das ich mehr Speicher für den Text zu Verfügung habe.

Vielen Dank im Voraus !!
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <inttypes.h>
4
#include <lcd.h>
5
#define F_CPU 4000000
6
#include <util/delay.h>
7
#include <lcd.c>
8
9
10
11
int main(void)
12
{ 
13
lcd_init(LCD_DISP_ON);    // LCD initialisieren
14
uint8_t a=0;        // Hilfsvariable a deklarieren
15
uint8_t x=0;        // Hilfsvariable x deklarieren
16
17
while(1)          // Endlos schleife
18
  {
19
  x=a;          // x auf den gleichen Wert wie a setzen
20
  if ( PINB & (1<<PINB1) )
21
    {
22
    }
23
  else
24
    {
25
      a--;
26
      _delay_ms(40);  // 40 ms Warten, mehr oder weniger auch Tasterenprellung (langsam rückwärts blättern)
27
    }
28
  
29
  if ( PINB & (1<<PINB0) )
30
    {
31
    }
32
  else
33
    {
34
      a++;
35
      _delay_ms(40);  // 40 ms Warten, mehr oder weniger auch Tasterenprellung (langsam vorwärts blättern)
36
    }
37
  if ( PINB & (1<<PINB2) )
38
    {
39
    }
40
  else
41
    {
42
      a--;
43
      _delay_ms(10);  // 10 ms Warten, mehr oder weniger auch Tasterenprellung (schnell rückwärts blättern)
44
    }
45
  
46
  if ( PINB & (1<<PINB3) )
47
    {
48
    }
49
  else
50
    {
51
      a++;
52
      _delay_ms(10);  // 10 ms Warten, mehr oder weniger auch Tasterenprellung (schnell vorwärts blättern)
53
    }
54
55
  if ( x!=a)        // Wenn a verändert wird, anzeige im Display ändern
56
    {
57
    switch (a) 
58
      { 
59
      case 0: 
60
      lcd_clrscr(); 
61
      lcd_puts("Da die Standard-"); 
62
      lcd_puts("Shell keine arit"); 
63
      break; 
64
      case 1: 
65
      lcd_clrscr(); 
66
      lcd_puts("hmetischen oder "); 
67
      lcd_puts("logischen Ausdrü"); 
68
      break; 
69
      case 2: 
70
      lcd_clrscr(); 
71
      lcd_puts("cke auswerten ka"); 
72
      lcd_puts("nn, muss dazu ei"); 
73
      break; 
74
      case 3: 
75
      lcd_clrscr(); 
76
      lcd_puts("n externes Progr"); 
77
      lcd_puts("amm benutzt werd"); 
78
      break; 
79
      case 4: 
80
      lcd_clrscr(); 
81
      lcd_puts("en. (if und Kons"); 
82
      lcd_puts("orten prüfen nur"); 
83
      break; 
84
      case 5: 
85
      lcd_clrscr(); 
86
      lcd_puts("den Rückgabewert"); 
87
      lcd_puts("eines aufgerufen"); 
88
      break; 
89
      case 6: 
90
      lcd_clrscr(); 
91
      lcd_puts("en Programmes --"); 
92
      lcd_puts("0 bedeutet true,"); 
93
      break; 
94
      case 7: 
95
      lcd_clrscr(); 
96
      lcd_puts("alles andere bed"); 
97
      lcd_puts("eutet false, sie"); 
98
      break; 
99
      case 8: 
100
      lcd_clrscr(); 
101
      lcd_puts("he auch Rückgabe"); 
102
      lcd_puts("werte) Dieses Pr"); 
103
      break; 
104
      case 9: 
105
      lcd_clrscr(); 
106
      lcd_puts("ogramm heißt tes"); 
107
      lcd_puts("t. Üblicherweise"); 
108
      break; 
109
      case 10: 
110
      lcd_clrscr(); 
111
      lcd_puts("besteht auf alle"); 
112
      lcd_puts("n Systemen auch "); 
113
      break; 
114
      case 11: 
115
      lcd_clrscr(); 
116
      lcd_puts("noch ein Link na"); 
117
      lcd_puts("mens [ auf diese"); 
118
      break; 
119
      case 12: 
120
      lcd_clrscr(); 
121
      lcd_puts("s Programm. Dies"); 
122
      lcd_puts("er Link ist abso"); 
123
      break; 
124
      case 13: 
125
      lcd_clrscr(); 
126
      lcd_puts("lut gleichwertig"); 
127
      lcd_puts("zu benutzen. Dem"); 
128
      break; 
129
      case 14: 
130
      lcd_clrscr(); 
131
      lcd_puts("entsprechend ist"); 
132
      lcd_puts("es auch zwingend"); 
133
      break; 
134
      case 15: 
135
      lcd_clrscr(); 
136
      lcd_puts("erforderlich, na"); 
137
      lcd_puts("ch der Klammer e"); 
138
      break; 
139
      case 16: 
140
      lcd_clrscr(); 
141
      lcd_puts("in Leerzeichen z"); 
142
      lcd_puts("u schreiben. Das"); 
143
      break; 
144
      case 17: 
145
      lcd_clrscr(); 
146
      lcd_puts("dient dazu, Bedi"); 
147
      lcd_puts("ngungen in if-Ab"); 
148
      break; 
149
      case 18: 
150
      lcd_clrscr(); 
151
      lcd_puts("fragen u. ä. les"); 
152
      lcd_puts("barer zu machen."); 
153
      break; 
154
      case 19: 
155
      lcd_clrscr(); 
156
      lcd_puts("Um dieses Konzep"); 
157
      lcd_puts("t der Lesbarkeit"); 
158
      break; 
159
      case 20: 
160
      lcd_clrscr(); 
161
      lcd_puts("zu unterstützen,"); 
162
      lcd_puts("sollte man diese"); 
163
      break; 
164
      case 21: 
165
      lcd_clrscr(); 
166
      lcd_puts("öffnende Klammer"); 
167
      lcd_puts("auch wieder schl"); 
168
      break; 
169
      case 22: 
170
      lcd_clrscr(); 
171
      lcd_puts("ießen (obwohl da"); 
172
      lcd_puts("s nicht zwingend"); 
173
      break; 
174
      case 23: 
175
      lcd_clrscr(); 
176
      lcd_puts("nötig ist). Das"); 
177
      lcd_puts("test-Programm bi"); 
178
      break; 
179
      case 24: 
180
      lcd_clrscr(); 
181
      lcd_puts("etet sehr umfang"); 
182
      lcd_puts("reiche Optionen "); 
183
      break; 
184
      case 25: 
185
      lcd_clrscr(); 
186
      lcd_puts("an. Dazu gehören"); 
187
      lcd_puts("Dateitests und V"); 
188
      break; 
189
      case 26: 
190
      lcd_clrscr(); 
191
      lcd_puts("ergleiche von Ze"); 
192
      lcd_puts("ichenfolgen oder"); 
193
      break; 
194
      case 27: 
195
      lcd_clrscr(); 
196
      lcd_puts("ganzen Zahlen. D"); 
197
      lcd_puts("iese Bedingungen"); 
198
      break; 
199
      case 28: 
200
      lcd_clrscr(); 
201
      lcd_puts("können auch durc"); 
202
      lcd_puts("h Verknüpfungen "); 
203
      break; 
204
      case 29: 
205
      lcd_clrscr(); 
206
      lcd_puts("kombiniert werde"); 
207
      lcd_puts("n. Dateitests:"); 
208
      break; 
209
      
210
      
211
      }
212
    }
213
214
  _delay_ms(10);
215
  }  // While Klamer zu
216
  
217
218
} // Main Klammer zu

von Karl H. (kbuchegg)


Lesenswert?

Du willst den Text ins Flash auslagern. Davon hast du noch jede Menge. 
Die Fleury Lib unterstützt das auch prächtig mit einem lcd_puts_P, 
sodass du nahezu keine Arbeit damit hast.

NB: Ist es wirklich notwendig, da so kompliziert mit switch-case auf die 
einzelnen Seiten zu gehen. Mann kann doch die Startadresse des ersten 
Buchstabens wunderbar aus der Seitenzahl errechnen. Ebenso weißt du 
wieviele Zeichen du jeweils auszugeben hast. Damit kann man sich auch 
eine spezielle Routine bauen, die
aus der übergebenen Seitenzahl die Startadresse berechnet.
Von dort weg 16 Zeichen ausgibt.
In die nächste LCD Zeile wechselt
und dort nocheinmal 16 Zeichen ausgibt (natürlich nur, wenn auch noch 
wirklich 16 Zeichen vorhanden sind).

-> Dein Anzeigeteil im Programm schrumpft auf 10 Zeilen zusammen. Nicht 
zu verachten der Komfort, der ensteht, wenn du den Text irgendwann 
einmal ändern musst.

lcd_puts_P kannst du dann zwar nicht mehr so direkt nehmen, aber die 
Technik die Zeichen aus dem Flash zu lesen, bleibt die Gleiche.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

von Michael (Gast)


Lesenswert?

Also erstmal vielen Dank für den super Tipp! Irgendwie muss ich bei den 
ganzen anderen Problem die ich mit dem LCD usw. hatte die lcd_puts_P() 
Funktion übersehen haben. Hab das Programm gerade geändert und bekomme 
jetzt beim compilieren
1
AVR Memory Usage
2
----------------
3
Device: atmega8
4
5
Program:    2088 bytes (25.5% Full)
6
(.text + .data + .bootloader)
7
8
Data:          0 bytes (0.0% Full)
9
(.data + .bss + .noinit)
10
11
12
Build succeeded with 0 Warnings...
angezeigt! was schonmal sehr gut ist!! Wann ist denn der Flash Speicher 
voll ? die Daten müssen ja irgendwohin geschrieben werden, aber der 
Compilier zeigt mir nichts an... irgendwie verwirrt mich die ganze Sache 
mit dem Speicher des Mc. Muss ich mich mal in Ruhe mit befassen.

Die Switch Anweisung wird mir mittels eines kleinen Linux Shell skriptes 
erzeugt, also Text unformatiert rein und komplette Switch Case Anwendung 
raus. Dabei werden im Moment schon überflüssige Leerzeichen am 
Zeilenanfang entfernt. Was noch kommen soll ist: ä in ae, Leerzeichen 
nach Punkt oder Komma entfernen usw.... das is aber eine andere 
Baustelle, mit der Shell kann ich wesentlich besser umgehen als mit gcc, 
daher habe ich auch diese Switch Case Lösung gewählt. Was anderes ist 
mir auch gar nicht eingefallen, ich werde deine Idee aber mal 
aufgreifen.

PS: Gerade mal ins Datenblatt des MCT geschaut, versteh ich das richtig 
das ich mich mit meinem Ursprünglichen lcd_puts() nur im SRAM ( 1K ) 
aufgehalten habe und mit lcd_puts_P() im 8K großem Flash befinden ?

von lecroix (Gast)


Lesenswert?

Das hast Du richtig verstanden.

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:

> angezeigt! was schonmal sehr gut ist!! Wann ist denn der Flash Speicher
> voll ? die Daten müssen ja irgendwohin geschrieben werden, aber der
> Compilier zeigt mir nichts an...

Doch das tut er.
Deine Texte sind in den 25% enthalten.
Der Grund warum dieser Wert nicht größer geworden ist, ist ganz einfach: 
Die Texte waren auch vorher schon im Flash. Denn irgendwie müssen diese 
Texte ja beim Programmstart auch ins SRAM gelangen. Die sind ja nicht 
von Anfang an dort. Das Runtime System kopiert sie am Programmanfang vom 
Flash in den SRAM von wo sie sich dein Programm dann abgeholt hat. Da du 
die Texte jetzt direkt aus dem Flash holst, besteht auch keine 
Notwendigkeit mehr, sie zunächst ins SRAM umzukopieren.
* der Startvorgang wird schneller
* der SRAM Verbrauch steigt nicht an

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.