Hallo,
nachdem ich in meinem Programm eine weitere Else-Anweisung eingefügt
habe,
funktioniert es nicht mehr vernünftig.
Zum Programm:
Das uart_receive_complete bool wird auf true gesetzt, wenn ein String
über eine UART-Interruptroutine empfangen wurde. Dann wird damit
begonnen, den String zu verarbeiten. Das funktioniert auch, solange kein
weiteres Else verwendet wird.
1
if(uart_receive_complete)
2
{
3
lcd_clear();
4
charcmd=uart_string[0];
5
if(cmd==CMD_HEADER)
6
{
7
strcpy(g_Header,uart_string+1);
8
}
9
elseif(cmd==CMD_TAG)
10
{
11
timer1_disable();
12
timer1_reset();
13
characcepted=uart_string[1];
14
15
if(accepted==UART_TRUE)
16
{
17
lcd_stringCenter("Welcome",1);
18
char*name=(uart_string+2);
19
lcd_stringCenter(name,2);
20
led_toggle(LED_ACCEPT);
21
delay(3000);
22
}
23
elseif(accepted==UART_FALSE)
24
{
25
lcd_stringCenter("ID unknown.",1);
26
lcd_stringCenter("Access denied.",2);
27
led_toggle(LED_DENIED);
28
delay(3000);
29
}
30
/* else
31
{
32
lcd_stringCenter("ID transmitted.", 1);
33
delay(2500);
34
}
35
*/
36
rfid_enable();
37
}
38
else
39
{
40
lcd_stringCenter("Unknown command:",1);
41
lcd_stringCenter(uart_string,2);
42
led_toggle(LED_ACCEPT);
43
led_toggle(LED_DENIED);
44
}
45
46
free(uart_string);
47
uart_receive_complete=false;
48
LED_PORT&=~(1<<LED_ACCEPT);
49
LED_PORT&=~(1<<LED_DENIED);
50
renderHeader();
51
}
Wenn ich aber nun die Else-Anweisung ausklammere um eine weitere
Verarbeitungsmöglichkeit hinzuzufügen, wird g_header nicht mehr
vollkommen erkannt. Es wird lediglich, der erste Buchstabe kopiert.
Ich flashe mit diesem Programm einen Attiny 4313. Der Flashspeicher ist
dann zu etwa 95% voll. Woran könnte das Problem liegen.
So langsam bin ich am verzweifeln.
Wenn Jemandem etwas auffällt würde ich mich über Hinweise oder Lösungen
freuen.
MfG Jonas
Jonas E. schrieb:> free(uart_string);
Du verwendest dynamische Speicherverwaltung auf einem Controller mit 256
Bytes RAM?! Du verwendest fröhlich ewig lange Delays während derer das
Programm auf keine Eingaben reagiert? Eventuell klappt das, eventuell
generiert das aber auch schwierig zu findende Probleme...
>Du verwendest dynamische Speicherverwaltung auf einem Controller mit 256>Bytes RAM?! Du verwendest fröhlich ewig lange Delays
und Strings die vermutlich auch im RAM liegen.
z.B. lcd_stringCenter("Unknown command:", 1);
Das else
lcd_stringCenter("ID transmitted.", 1);
hat dem Stack vermutlich nur noch den Rest gegeben. Aus die Maus.
holger schrieb:>>Du verwendest dynamische Speicherverwaltung auf einem Controller mit 256>>Bytes RAM?>> Es sind nur 128 Byte;)
Nee. Das sind 256. Aber trotzdem...
mfg.
Jonas E. schrieb:> Wie kann aus dem Ram die nicht mehr benötigten Strings entfernen, um> wieder Speicherplatz zu erlangen?
Gar nicht. Allerdings sollte der GCC clever genug sein, die Strings in
den Flash zu packen. Mach dich mal schlau wie man Pointer auf
PROGMEM-Arrays (aka. String-Konstanten) mit dem AVR-GCC an Funktionen
übergibt. Und nimm alle malloc&free aus dem Programm...
>Wie kann aus dem Ram die nicht mehr benötigten Strings entfernen, um>wieder Speicherplatz zu erlangen?
Überflüssige Ausgaben gar nicht erst machen.
lcd_stringCenter("ID unknown.", 1);
lcd_stringCenter("Access denied.", 2);
Da reicht doch auch:
lcd_stringCenter("ID unknown", 1);
lcd_stringCenter("Access denied", 2);
Ich hab jetzt mal die beiden '.' weggelassen. Spart zwei Byte.
Oder
lcd_stringCenter("ID?", 1);
lcd_stringCenter("Access denied", 2);
Nochmal 7 Byte weniger.
Oder einfach nur
lcd_stringCenter("Access denied", 1);
Es gibt immer einen Weg RAM zu sparen.
holger schrieb:> Es gibt immer einen Weg RAM zu sparen.
Wieso RAM?! String-Literale gehören in den Flash! Und können auch direkt
von da byteweise gelesen&verarbeitet werden, braucht 0 Bytes RAM.
>> Es gibt immer einen Weg RAM zu sparen.>Wieso RAM?! String-Literale gehören in den Flash!
Das weiss ich selber, ich bin ja nicht blöd. Im Flash
stehen die sowieso. Woher sollen die sonst ins RAM kommen?
Schreib ihm seine Routine um Daten aus dem Flash zu nehmen
doch einfach. Da hatte ich jetzt im Moment keinen Bock drauf.
Ich hab ihm nur einen Weg gezeigt wie er da ohne grosse
Verrenkungen evtl. noch mal so davonkommt.
>lcd_StringCenter():
Das jetzt auf PROGMEM umzubauen sieht nicht so einfach aus.
Aber mal ein paar andere Tips vor dem schlafen gehen:
>void lcd_stringCenter(const char* data, int row)
int row? Wozu? Kann row negativ werden? Dein Display hat ja
auch nur zwei Zeilen. Wozu brauchst du da einen 16 Bit Wert?
void lcd_stringCenter(const char* data, uint8_t row)
ist doch besser oder nicht?
Der gleiche Müll:
int length = strlen(data);
int column = 0;
Besser
uint8_t length = strlen(data);
uint8_t column = 0;
Noch son Ding. Ausser int scheinst du ja nichts anderes zu kennen.
>void lcd_stringAt( const char *data, int coloumn, int row )
void lcd_stringAt( const char *data, uint8_t coloumn, uint8_t row )
Das gleiche vermutlich mit lcd_setcursor(coloumn, row);
sizeof(data) ist immer grösser 0.
if ( data != 0 )
usw.
Bring erstmal diesen Unsinn in Ordnung.
Das wird dein Programm schon mal ordentlich eindampfen.
Alles klar.
Ich bin noch an das Programmieren mit C# gewöhnt wo man nicht so auf
Speicher achten braucht. Nun habe ich alle 16 bit Ints zu uint8_t
"verwandelt". Spart einen guten Teil an Speicher ein. Nur löst das
leider nicht mein grundlegendes Problem...
Gruß Jonas
Hallo Holger,
ist es möglich, dass du mir deine E-Mail Adresse per PN schreibst,
sodass ich dir das komplette Programm mal schicken könnte und du es dann
einmal ansehen könntest? Was könnte z.B. verbessert werden?
Würde mich echt sehr darüber freuen.
Gruß Jonas
>Hallo Holger,>ist es möglich, dass du mir deine E-Mail Adresse per PN schreibst,
Nö;)
Ich hab mich mal an deiner Funktion vergangen. Nur rein
theoretisch, könnten also noch Fehler drin sein.
So müsste das mit Strings aus dem Flash klappen.
Ohne Gewehr!
1
voidlcd_stringCenter_P(constchar*data,uint8_trow)
2
{
3
charc;
4
5
if(data>0)
6
{
7
uint8_tlength=strlen_P(data);
8
uint8_tcolumn=0;
9
10
if(length<=LCD_COLOUMS)
11
{
12
column=LCD_COLOUMS/2-(length+(length%2))/2;
13
}
14
15
lcd_setcursor(coloumn,row);
16
17
while((c=pgm_read_byte(data++)))
18
{
19
if(coloumn>=LCD_COLOUMS)
20
{
21
coloumn=0;
22
row++;
23
lcd_setcursor(coloumn,row);
24
}
25
lcd_data(c);
26
27
coloumn++;
28
}
29
}
30
}
Du ersetzt jetzt aber nicht deine void lcd_stringCenter() mit dieser
Funktion. Du nimmst dies als eine neue Funktion mit rein.
Da wo du z.B
lcd_stringCenter("ID unknown.", 1);
schreibst musst du jetzt
lcd_stringCenter_P((PSTR)"ID unknown.", 1);
draus machen.
Strings aus dem RAM kannst du damit nicht ausgeben! Also
lcd_stringCenter(name, 2);
bleibt so wie es war.
Viel Spass damit;)