Hallo, ich habe einen Controller Programmiert, welcher über den UART Texte ausgibt. Sobald ich aber mehr text ausgeben will, so hängt er sich auf. Ich hab das Programm mal im AVR-Studio schritt für schritt angeschaut und da viel mir auf, dass das ganze Ram mit dem Text für den UART follgeschrieben wird und damit die anderen Variablen löscht. Auch den Text in mehrere kleine stücke unterteilen bringt nichts, die alten stücke im Ram. Danke, Florian
Hier sind die Code-Fragmente: static volatile unsigned char *uart_data_ptr; static volatile unsigned char uart_counter; SIGNAL(SIG_UART_TRANS) { uart_data_ptr++; if (--uart_counter) outp(*uart_data_ptr, UDR); } void uart_send(unsigned char *buf, unsigned char size) { if (!uart_counter) { uart_data_ptr = buf; uart_counter = size; outp(*buf, UDR); } } Text ausgeben mit: uart_send("Text",länge);
hmm, hat das evtl. damit zu tun, dass er (aus welchem grund auch immer, so firm bin ich da nicht) den stack mit deinem text vollklatscht? Kann eigentlich nur so sein. die frage ist: wieso? wie gesagt, bin da nicht so firm.
Sehe ich das richtig, es wird einfach ein Zeiger ohne allokierten Speicherbereich angelegt und dann munter hineingeschrieben? Das ist aber schon ein grober Schnitzer! Irgendwann treffen sich Heap und Stack und dann ist Ende im Gelände ;-) Gruss, Peter
yo, uart_data_ptr zeigte einst auf buf, welches ja aber nur in uart_send gültig ist. Das war mir auch aufgefallen... allerdings wird da ja nix hingeschrieben, sondern von dort an den UART gesendet... und uart_counter ist ja global, müsste also tatsächlich irgendwann auf 0 stehen... oder seh ich das falsch?
Die Problematik habe ich nun erkannt: Der zeiger uart_data_ptr wird immer um eins erhöht und zeigt so auf immer einen anderen wert. Also auch beim laden von neuen Texten. Kann ich den Zeiger irgendwie zurückstellen, also auf einen festen Speicherbereich zeigen lassen?
Hallo Florian, Du must überhaupt erstmal Speicher für den UART-Puffer zuweisen. Ansonsten schreibst Du mit Deinem Pointer irgendwo ins RAM. char buffer[40]; char * ptr = buffer; und dann im Interrupt: ptr++; if( ptr == (buffer + sizeof(buffer)) ) // am Ende angelangt ? ptr = buffer; // dann wieder von vorne Peter
Ich habe nun die Routienen umgeschrieben. Sie sehen so aus: char buffer[41]; char *ptr = buffer; int laenge; SIGNAL(SIG_UART_TRANS) { ptr++; laenge--; if (laenge) outp(*ptr,UDR); } void uart_send(unsigned char *buf, unsigned char size) { for(;;) { if (laenge==0) { laenge=size; int t; for (t=0;t<=size;t++) { if (t<=40); { buffer[t]=PRG_RDB(buf+t); } } ptr=&buffer[0]; outp(*ptr,UDR); break; } } } wenn ich nur den Aufruf: char *line1 = PSTR("1.Test von Florian"); uart_send(line1,18); schreibe, so funktionierts. wenn ich aber char *line1 = PSTR("1.Test von Florian"); uart_send(line1,18); char *line2 = PSTR("2.Test von Florian"); uart_send(line2,18); schreibe, so wird zwar der 1.Text ausgegeben, jedoch der 2.Text nicht mehr und der Controller reagiert nicht mehr. Ich weiß nicht ob ich einen Fehhler in meiner Denkweise oder in meinem Algoritmus suchen muss.
das liegt daran, dass er nach dem ersten interrupt weitermacht. d.h. er gibt das erste zeichen aus ('1'), springt, macht dann weiter (Line 2 laden). dann mach er die zeile uart_send(line2,18); Irgendwann (wenn er fertig ist, mit dem ersten zeichen, keine ahnung, wielange das dauert), springt er in den interrupt... verstehst?
Danke - Jetzt gehts (ich hab zwischen den Send-Befehle eine Pauseroutiene geschrieben). An das Problem habe ich nicht gedacht. Danke, Florian
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.