Attega schrieb:
> @MachMal
>
> Druch volatile würde er die Variable inerhalb einer Funktion auch nach
> dem ende ihere ausführung behalten.
> Das sollte hier nicht das problem sein, da sendezähler und die
> Zeichenkette globale variablen sind.
Es sollte bei dieser Funktion
1 | int Senden(unsigned char z[]) //Es wird ein zeiger auf die zu sendenden Daten übergeben
|
2 | { //Es wird mit 1 ein erfolg zurückgemeldet
|
3 | UDR = z[sendezahler];
|
4 | sendezahler++;
|
5 | return 1;
|
tatsächlich kein Problem sein, da dieser Code sicherlich schneller
ausgeführt wird, als das Zeichen versandt wird und damit ist die
Funktion längst fertig, ehe dann der Transmit Complete Interrupt
anspricht. Bei einem UDRE Interrupt würde das anders aussehen, aber den
Fall hast du nicht.
Die variable volatile zu machen ist nichts desto trotz eine gute Idee.
Denn die Dinge ändern sich auch schon mal.
> @Karl Heinz
> Hab grade nachgemessen, die ISR wird aufgerufen.
> Stimmt _delay_ms( 5000 ); ist praktischer.
>
> Was stimmt nicht mit der Verwaltung des Sendezählers?
> Er beginnt mit dem 1. Element des zu sendenden zeichen.
Spielen wirs durch.
die Sache beginnt mit
1 | int Senden(unsigned char z[]) //Es wird ein zeiger auf die zu sendenden Daten übergeben
|
2 | { //Es wird mit 1 ein erfolg zurückgemeldet
|
3 | UDR = z[sendezahler];
|
soweit so gut. Also, fast so gut. denn senezähler hat hier nur deshalb
den Wert 0, weil er als globale Variable mit 0 initialisiert wurde.
Aber ok.
Wie gehts weiter.
In diesem Moment beginnt die UART zu arbeiten. Die Funktion läuft weiter
sendezahler wird um 1 erhöht und hat jetzt den Wert 1.
Die UART ist immer noch dabei das Zeichen zu versenden.
Die Funktion kehrt zu main zurück und geht dort in die Verzögerung rein.
Das ist jetzt erst mal wichtig, dass diese Verzögerung auch tatsächlich
greift. Dann wenn da nicht verzögert wird und die Funktion Senden in
paar µs später erneut aufgerufen wird, dann wirds schwierig
vorherzusehen, was da alles passiert. Auf jeden Fall hätte sendezahler
dann schon nicht mehr den Wert von 0 (sondern 1), was schon mal ein
Hinweis darauf ist, dass es eine verdammt gute Idee wäre, diese 0 in
sendezahler in der Funktion Senden() sicherzustellen.
Aber seis drum. Nehmen wir an die Verzögerung wirkt.
Die UART arbeitet.
Irgendwann ist das Zeichen draussen, ein TRansmit Complete Interrupt
wird ausgelöst. Wie gehts weiter?
1 | ISR(USART_TXC_vect)
|
2 | {
|
3 | sendezahler++;
|
sendezahler war 1, und wird jetzt auf 2 erhöht.
1 | if(Test[sendezahler]!=0x00)
|
Nun, Test[sendezahler], sendezahler hat den Wert 2, das ist also Test[2]
und das ist
1 | unsigned char Test[3]={0xFE,'3','H',0x00};
|
das 'H'.
Ich halte also fest. Bei der ersten Übertragung wurde das 0xFE auf den
Weg gebracht, bei der nächsten das 'H'. Was ist mit dem '3'?
Die sind unter den Tisch gefallen.
Egal.
'H' ist nicht gleich 0. Daher
1 | {UDR = Test[sendezahler];}
|
ok, also das 'H' wird in die UART gegeben, welches das Zeichen auf den
Weg bringt.
In der ISR passiert nichts weiter mehr, die Kontrolle geht zurück an
main(), welches (hoffentlich) immer noch in der Verzögerung hängt.
Irgendwann ist das 'H' übertragen, ein erneuter Transmit Complete
Interrupt wird ausgelöst.
1 | ISR(USART_TXC_vect)
|
2 | {
|
3 | sendezahler++;
|
sendezahler war 2, wird jetzzt zu 3.
1 | if(Test[sendezahler]!=0x00)
|
2 |
|
3 | ... unsigned char Test[3]={0xFE,'3','H',0x00};
|
Test[3] hat den Wert. Ja welchen eigentlich?
Dein Array ist mit einer Länge von 3 definiert. Du versuchst aber mit 4
Zeichen zu initialisieren. Was passiert in diesem Fall? Welche Angabe
gilt?
Es gilt die 3 in der Arrayangabe. D.h. es gibt ein Test[0], Test[1] und
ein Test[2]. Zähl nach, sind genau 3 Stück. Ein Test[3] existiert aber
gar nicht. D.h. man kann an dieser Stelle überhaupt nicht sagen, welchen
Wert Test[3] eigentlich ergibt, denn der kann alles mögliche sein, je
nachdem was da gerade zufällig im Speicher steht.
Und damit sind alle Wetten zur Makulatur geworden, wie es weiter geht.