Probleme mit UART

Gast #448505
Lesenswert?
• ▲
▼
Hallo,

Ich habe ein kleines Problem mit meiner seriellen Schnittstelle. Und 
zwar sende ich einen String von einem Terminalprogramm in meinen µC. 
Dort angekommen wird dieser in einer Variable gespeichert und sofort 
wieder an das Terminal zurückgegeben. Nur unterscheidet sich der 
gesendete String sehr vom empfangengen, obwohl diese identisch sein 
müssten. Es ist, als ob der µC den String "durcheinander würfelt". Auch 
die Länge stimmt nicht überein. Was könnte da sein?

Ich programmiere den ATmega8 in BASCOM!

Vielen Dank für eure Hile!!

mfg
Andy
Gast #448512
Lesenswert?
• ▲
▼
Also, die Baudraten stimmen und der Quarz ist auch richtig aktiviert. 
Der serielle Interrupt sieht folgendermaßen aus:


Onserial:
  Daten = Inkey()

  Buf = Buf + Chr(daten)
  Print Buf
Return


Alos denkbar einfach. Aber wenn ich zum Beispiel den Text "qwertzuiop" 
runtersende, kommt "qwertqweupqwepqwep" zurück. Komisch, oder gibt es 
dafür eine logische Erklärung?
Gast #448537
Lesenswert?
• ▲
▼
Inkey() wartet doch nur auf irgendein Zeichen, oder?

Dann ist klar, was läuft. Der AVR empfängt ein Zeichen, addierts in den 
Buffer und gibts sofort wieder aus. Beim nächsten Zeichen das Gleiche - 
nur dass er jetzt 2 Zeichen augibt, währenddessen kann er zwar eines 
empfangen, aber das Zweite nicht usw.
Der Print-Befehl ist der Übeltäter, so kann das nicht funktionieren.
Welche Funktion erwartest Du von dem Programm? Dass es den Text exakt 
zurücksendet und dabei speichert? Dann solltest Du nicht bei jedem 
Aufruf den kompletten Text mit Print ausgeben, sondern nur das aktuelle 
Zeichen.
Oder: Den ganzen String lesen und erst am Ende ausgeben.
#448553
Lesenswert?
• ▲
▼
Print sollte in diesem Falle eigentlich nicht das Problem darstellen 
(abgesehen davon, dass es zeit verschlingt und in einer ISR nix zu 
suchen hat).

Problematisch kann hingegen die Verwendung von Inkey() innerhalb einer 
ISR sein, da fuer das Anlegen und Fuellen des inkey Buffers selbst eine 
URXC-ISR genutzt wird. Allerdings setzt der Compiler den Aufruf dieser 
internen ISR zwischen die Sicherung der Register und die User-ISR. 
Sollte also dennnoch laufen. Ich tippe allerdings auf nebenbei laufende 
Timer, deren ISRs zu lang sind. Sowas bringt Bascom leider sehr schnell 
aus dem Takt und das Prog macht, was es will. Ich wuerde folgendes 
machen:

1. Den kompletten Code hier posten...
2. Die ISR umbenennen. In Onserialx o.ae.
2. HWStack, SWStack und Framesize ueberpruefen. Sollte man testweise 
alle auf  >60 setzen, wenn mal gar nix laeuft.
3. Alle anderen Interrupts deaktivieren.
4. Ueberpruefen, ob in den Variablendeklarationen Overlay genutzt wird. 
Diese Variablen testweise loeschen (nicht 0 setzen, sondern deren 
Deklarationen loeschen).

Beste Gruesse
Gast #448559
Lesenswert?
• ▲
▼
@ Marvin und André

Vielen Dank für eure ausführlichen Antworten. Ich habe nun den Tipp von 
Marvin befolgt und das Print weggelassen und erst zum Schluss meine 
Variable ausgegeben und... Es hat funktioniert. Anscheinend hat das 
Print, wirklich dazu geführt, dass einzelne Zeichen "verschlungen" 
wurden.

Naja, trotzdem vielen Dank für eure Bemühungen.

mfg
Andy
#448560
Lesenswert?
• ▲
▼
> Anscheinend hat das
> Print, wirklich dazu geführt, dass einzelne Zeichen "verschlungen"
> wurden.

Das Print selbst wahrscheinlich nicht.
Dein eigentliches Problem wird eher darin liegen,
dass du ohne Handshake auf der Leitung fährst. D.h.
der µC teilt dem PC nicht mit, dass er momentan beschäftigt
ist und daher zur Zeit nicht senden kann.
Der Print braucht seine Zeit. Da er aber innerhalb der ISR
augeführt wird, kann der µC in dieser Zeit nichts empfangen.
Nur: Das weiss der PC nicht und sendet weiter munter
drauflos. Da aber niemand die Zeichen abholt: -> Null-Device
#448583
Lesenswert?
• ▲
▼
Kannst du softwaremässig einen Interrupt auslösen?

Normalerweise macht man das so, dass man ein Flag
(also eine globale Variable) benutzt, die anzeigt
ob Daten komplett empfangen wurden oder nicht.

Innerhalb der Empfangsfunktion wird einfach nur
das nächste Zeichen von der UART geholt und in
den Buffer gestellt. Die Funktion stellt dann
noch fest, ob die Übertragung der Daten damit
vollständig ist oder nicht. Ist sie nicht
vollständig macht sie nichts weiter. Ist
sie aber vollständig, so wird das Flag (die
globale Variable) auf zb 1 gesetzt.

Im Hauptprogramm, also ausserhalb der Empfangsroutine
wird nun ständig diese globale Variable beobachtet.
Solange sie 0 ist, passiert nichts weiter. Wenn die
aber plötzlich 1 wird, dann hat die UART-Empfangsroutine
einen kompletten Datensatz empfangen und der muss verarbeitet
werden. Danach wird das Flag wieder auf 0 gesetzt und
wieder solange gewartet, bis diese 1 geworden ist, ...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren