Hallo,
ich habe folgendes Problem.
Wenn ich einen String z.B. 1234567 an den µC (atmega8) schicke erhalte
ich auf dem Display nur die ersten drei zeichen und das letzte also
1237.
Bis 4 Zeichen funktioniert alles.
Hat jemand Rat warum er die zwischen Zeichen "verschluckt"???
Als Anhang mein C Programm.
Über eine Hilfe wäre ich sehr dankbar.
Gruß
Denis
Hat der ATmega8 überhaupt einen Empfangsbuffer? Wenn ja, wie gross?
1
do{
2
string[i]=UDR;
3
// UDR=0;
4
// while (UCSRA&32);
5
wait_ms(100);// Damit alle Zeichen im Buffer angekommen sind
6
//lcd_write(UDR);
7
i++;
8
}
9
while(UCSRA&128);
Das wait_ms() ist nicht sehr geschickt, lieber warten, bis ein Zeichen
empfangen wurde und es dann sofort auslesen. So wie im obigen Code
könnte ja ein Zeichen verpasst werden.
Leider kenne ich mich mit AVRs nicht so gut aus, aber die Flags für die
Register sollten doch auch symbolisch definiert sein, oder?
UCSRA&128 und so ist mühsam zum Lesen.
In deinem Programm ist einiges verbockt.
Ein grundsätzlicher Programmaufbau sieht so aus
int main()
{
initialisiere die Hardware
schalte Ports richtig
initialisiere was auch immer das Programm onst noch
so braucht, zb UART oder ADC
while( 1 ) {
arbeite mit der Hardware
}
}
Es gibt (zumindest in deinem Programm) keinen Grund, die
Hardware (in deinem Fall die UART) innerhalb der Hauptschleife
immer wieder neu zu initialisieren. Ganz im Gegenteil, das
kann auch kontraproduktiv sein. Was denkst du wird wohl
passieren, wenn die UART gerade ein Zeichen empfängt und
dein Code initialisiert die UART neu.
do{
string[i]=UDR;
// UDR=0;
// while (UCSRA&32);
wait_ms (100); // Damit alle Zeichen im Buffer angekommen sind
//lcd_write(UDR);
i++;
}
Woher weist du, wenn du das UDR Register ausliest, dass die
UART überhaupt ein Zeichen empfangen hat?
Antwort: Du kannst es nicht wissen. Aber die UART zeigt es
dir mit einem speziellen Bit an. Du musst nur solange warten,
bis dieses Bit den Empfang signalisiert.
Aber: Zuerst auf das Signal warten und dann das Zeichen holen!
while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar
;
string[i] = UDR;
Das mit dem Warten ist Unsinn, du weist nicht wie schnell dein
Benutzer tippt!
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_UART
// Sehr stabil wird ein solcher Code mit diesem Quasi-Timeout
20
// aber nicht.
21
22
wait_ms(2);
23
}
Oder besser die bereits vorhandene Funktion getchar() benutzen
1
string[i++]=getchar();
Allerdings brauchst du dann auch noch einen Weg um festzustellen, ob
alle Zeichen empfangen wurden. Welcher Weg das ist, hängt vom Sender ab
z.B. feste Anzahl Zeichen oder bekanntes Endezeichen oder feste
Sendedauer...
Hallo,
habe mein Programm etwas umgestaltet aber immer noch kein Erfolg.
Mein String den ich vom PC an den µC Sende z.B. 123456
erhalte ich auf dem LCD Display 1236. Die ersten drei Zeichen sind ok
und dann schneidet er 45 raus und hängt das letzte an.
Hingegen wenn mein String nur aus max. 4 Zeichen besteht ist alles OK.
z.B. 1234
Hat jemand Rat???
Als Anhang nochmals das C Programm
Gruß
Denis
David Madl wrote:
> Aber z.B. bei 115200 Baud könnte es sein, dass mehrere Bytes innerhalb> der Millisekunde ankommen, die du wartest...
Stimmt. Und wie könnte man das berücksichtigen?
Mir würde dazu einfallen, dass die Wartefunktion nicht nur trödelt,
sondern auch den Status der UART überwacht und vorzeitig das Trödeln
abbricht, wenn ein Zeichen angekommen ist.
Stefan "stefb" B. wrote:
> David Madl wrote:>> Aber z.B. bei 115200 Baud könnte es sein, dass mehrere Bytes innerhalb>> der Millisekunde ankommen, die du wartest...>> Stimmt. Und wie könnte man das berücksichtigen?
Wie eigentlich immer, wenn es um eine zeitlich begrenzte
Warterei geht und gleichzeitig etwas überwacht werden muss:
* Timer aufsetzen, der die Zeit runterzählt.
* In der Warteschleife neben dem zu überwachenden Signal auch
noch abprüfen, ob der Timer angeschlagen hat.