Hallo Leute,
ich hab hier ein wohl einfaches Problem, wo ich einfach nicht
weiterkomme. Ich programmiere einen Atmega16 in C mit WinAvr.
Mein Programm besteht im Moment nur darin ein vom PC gesendeten String
über die serielle Schnittstelle aufzunehmen und zurückzugeben.
Das ganze Funktioniert auch soweit, deshalb denke ich brauche hier nicht
dan ganzen Code zu posten.
Die vom PC empfangenen Daten werden in einem
1
charuart0_tx_buffer[255];
gespeichert. Dabei wird das Ende eines Telegramms vom PC mit einem
Terminierungszeichen erkannt und eine Variable gesetzt, sodass die
Hauptschleife weiß, wann es die Daten wieder zurücksenden soll.
In er Hauptschleife sieht das dann so aus:
1
while(1)
2
{
3
4
5
if(uart0_rxd_complete==1)
6
{
7
i=0;
8
9
if(uart0_rxd_DataLength!=0)
10
{
11
putch('\r',0);
12
putstring("\nFolgende Daten wurden empfangen: \n",0);
13
putch('\r',0);
14
// zahl=string_to_dec_value(uart0_rx_buffer);
15
16
while(uart0_rx_buffer[i]!='\0')
17
{
18
putch(uart0_rx_buffer[i],0);
19
i++;
20
}
21
putch('\r',0);
22
}
23
24
uart0_rxd_DataLength=0;
25
uart0_rxd_complete=0;
26
UCSRB|=(1<<RXCIE);// Empfangsinterrupt wieder aktivieren
27
}
Ihr seht die Zeile "zahl=string_to_dec_value(uart0_rx_buffer);" ist noch
auskommentiert, denn genau hier ist mein Problem. Mit dieser Zeile will
ich den uart0_rx_buffer, also das Array mit den Empfangenen Zeichen, per
Pointer an die Funktion string_to_dec_value übergeben. Diese Funktion
ist noch völlig leer:
1
unsignedintstring_to_dec_value(char*inputStr)
2
{
3
4
return0;
5
}
Und trotzdem kommt nur Müll raus, wenn ich diese Zeile einbinde. Es ist
so als ob das Array uart0_rx_buffer manipuliert wird, denn nach dem
aufruf der Funktion string_to_dec_value kehre ich ja wieder zur
Hauptschleife zurück und gebe das Array aus. Dann ist es aber so, das
die Ausgabe manchmal ganz normal Funktioniert und manchmal Fehlen
Zeichen oder wurden durch andere ersetzt, die ich garnicht gesendet
hatte....
Ich möchte noch anmerken, das die Empfangsroutine und die Funktion
string_to_dec_value in der Datei "uart.c" stehen und auch dort das Array
"char uart0_tx_buffer[255];" definiert ist. Die Hauptschleife befindet
sich in der "main.c" und das Array ist mit "extern char
uart0_rx_buffer[];" eingebunden.
Also warum manipuliert der Funktionsaufruf mein Array ? Es sieht auch so
aus, als währe immer nur das erste Zeichen im Array davon betroffen,
aber es kann auch sein das ich mir das jetzt nur einbilde.
Ich bekomme auch übrigens keine Warnungen vom Compiler angezeigt.
Vielen Dank
Das ist mal wieder so ein Fall, bei dem das Problem nicht im gezeigten
Code liegt.
Wenn der Effekt wirklich tatsächlich nachweislich an der einen Zeile
"zahl=..." liegt (du siehst, mir fehlt da etwas der Glaube), dann
überschreibt die zurückgegebene Null andere Daten. Warum, musst du
rausfinden. Das ist auf jeden Fall kein Problem von "zahl", sondern von
den Buffern davor oder dahinter.
Es kann aber auch was ganz anderes sein.
Oliver
Also ich kann dir versichern dass das Problem nur besteht wenn die
Funktion string_to_dec_value aufgerufen wird. Ich dachte halt deshalb,
das es mit der Übergabe an die Funktion zusammenhängt also mit dem
Pointer.
Und es passiert auch nicht immer. Sagen wir ich sende 10 mal den selben
String, dann kommt er halt z.B.: 4 mal richtig zurück und 6 mal Fehlt
das erste Zeichen oder wurde durch irgendetwas anderes ersetzt. Dachte
zuerst es liegt an meinem USB zu RS232 Wandler der am PC hängt, aber ich
habe es auch auf einem anderem PC mit "richtiger" RS232 Schnittstelle
ausprobiert.
Markus Wi*** schrieb:> Also ich kann dir versichern dass das Problem nur besteht wenn die> Funktion string_to_dec_value aufgerufen wird.
Nun, ich kann dir versichern, daß das Problem auch ohne diese Zeile
besteht. Es äussert sich dann nur anders, und fällt vielleicht auch gar
nicht direkt auf.
Du kannst davon ausgehen, das der Compiler sowohl Parameter als auch
Rückgabewert richtig übergibt. Daran kann es nicht liegen.
Oliver
Was stellt denn sicher, daß uart0_rx_buffer nicht außerhalb dieser
Funktion verändert wird?
Wenn der beispielsweise von einer ISR befüllt wird ... nichts.
Hallo,
das oben beschriebene Programm enthält einige typische Fallstricke, die
robuste Programme von Bastelprogrammen unterscheiden:
1) was passiert, wenn das Ende-Kennzeichen fehlt ? Rennt dann das
Programm durch den Speicher und sucht die '\0' ?
2) ist i ein unsigned char ? Dann ist uart0_rx_buffer für i=255 zu kurz.
Gruß,
Michael
Michael Appelt schrieb:> Hallo,>> das oben beschriebene Programm enthält einige typische Fallstricke, die> robuste Programme von Bastelprogrammen unterscheiden:>> 1) was passiert, wenn das Ende-Kennzeichen fehlt ? Rennt dann das> Programm durch den Speicher und sucht die '\0' ?>> 2) ist i ein unsigned char ? Dann ist uart0_rx_buffer für i=255 zu kurz.>> Gruß,> Michael
1) Das Endezeichen wird durch meine Empfangsisr angehängt, siehe
Quellcode unten (in uart.c)
2) Nein es ist ein Int
Rufus Τ. Firefly schrieb:> Was stellt denn sicher, daß uart0_rx_buffer nicht außerhalb dieser> Funktion verändert wird?>> Wenn der beispielsweise von einer ISR befüllt wird ... nichts.
Naja die einzigste Funktion bzw. ISR die darauf zugreift ist der
Empfangsinterrupt. Diese wird aber eben nicht mehr aufgerufen, nachdem
der PC die Daten an den µC gesendet hat. Anstonsten gibt eh halt noch
nicht ;)
Hier mal der Code:
main.c:
// functiondescription: Interrupt für USART0 recieve. Schreibt die empfangenen Zeichen in einen Empfangsbuffer bis das Endezeichen (CR=0x0D) erkannt wurde
if(uart0_tx_buffer_pointer>255)uart0_tx_buffer_pointer=0;// Zur Sicherheit, kann hier aber nicht passieren, da unsigned char sowieso überläuft
Denn hier kann der Index ja erlaubterweise auch 255 werden. Du kannst
also 256 Elemente adressieren. Blöd, wenn dein Array nur 255 Elemente
reserviert hat...
> if(uart0_tx_buffer_pointer>255) uart0_tx_buffer_pointer=0; // Zur
Sicherheit, kann hier aber nicht passieren, da unsigned char sowieso überläuft
Wie du richtig kommentierst, sind diese Checks sinnlos. Aber was
schlimmer ist, deine Puffer sind ein Byte zu klein:
> char uart0_rx_buffer[255];
Bei einem maximalen Index von 255 brauchst du 256 Byte.
Deine extern-Definitionen und tatsächlichen Deklarationen unterschieden
sich bzgl. volatile.
Wenn ich das richtig verstehe, sieht uart.c nur die uart.h, in der
einige volatiles bei den Bufferindices fehlen, die sowohl in der TX-ISR
und in putch benutzt werden. Ob das jetzt tatsächlich etwas ausmacht,
darfst du selber herausfinden.
Oliver
Uwe S. schrieb:> Hi, dann läuft deine cpu zu langsam:> Für 9600Baud@16Khz
Na aber dann würde doch das Problem immer bestehen und nicht nur wenn
ich die eine Funktion aufrufe
Karl Heinz schrieb:> Eine Frage noch.> Was läuft auf dem PC?> Sitzt du selber am Terminal und gibst ein, oder ist da ein Programm,> welches den AVR über die UART versorgt?
Ich nutze ein einfaches Terminalprogramm
Lothar Miller schrieb:> Denn hier kann der Index ja erlaubterweise auch 255 werden. Du kannst> also 256 Elemente adressieren. Blöd, wenn dein Array nur 255 Elemente> reserviert hat...
Oh ja ... war natürlich etwas dämlich. Danke für den Tip, leider ändert
es hieran nichts.
Oliver schrieb:> Wenn ich das richtig verstehe, sieht uart.c nur die uart.h, in der> einige volatiles bei den Bufferindices fehlen, die sowohl in der TX-ISR> und in putch benutzt werden. Ob das jetzt tatsächlich etwas ausmacht,> darfst du selber herausfinden.
und
Quack schrieb:> Das sieht mal wieder nach Code aus, bei dem die Warnings ignoriert> werden. :-/
Ja sorry, ich denk mal ihr meint die Variable uart0_rx_buffer weil sie
in uart.c nicht als volatile steht aber in main.h. Ja da hab ich jetzt
während dem "Basteln" mist kopiert. Sie sind an beiden Stellen NICHT
volatile. Wenn ich sie als volatile deklariere, dann bekomme ich auch
eine Warnung. Ich glaube das meintest du ?
Und ja. Die main.c sieht nur die main.h und die uart.c die uart.h
In der Ausgabeschleife in main versuchst du den Ringbuffer als String
auszugeben. Nimm mal ein Blatt Papier und einen Stift und mal den
Ringbuffer mit seinen Pointern und den Fall "Daten beginnen hinten im
Puffer und werden vorne weitergeführt". Da hilft kein \0 ans Ende
schreiben, dann funktioniert nie.
Oh weia ich kann auflösen ...
So ein dummer Fehler ohne witz....
Wie ja schon Lothar Miller und Quack bemerkt hatten war mein
uart0_rx_buffer ein Zeichen zu klein. Deshalb der Fehler und es sah
wirklich die ganze Zeit so aus als würde es nur durch die Funktion
aufreten. Verdammter misst ich sollte weniger trinken :D
Danke Danke Danke
>ich sollte weniger trinken
Trinken ist eine sehr gesunde Sache und dem Denkvermögen sehr
förderlich. Wasser wie es aus der Leitung kommt ist dafür aber
eigentlich ausreichend. Verschiedene Zusatzstoffe können das natürlich
wandeln.
Auch wenn die Sting-Problematik nicht ganz neu ist, hab ich mit
Interesse mitgelesen. Man muss ja nicht immer nur durch eigene Fehler
lernen.
besten Dank
Hauspapa
Eine eigene Frage?
Dieser Thread ist über 12 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.