Forum: FPGA, VHDL & Co. UART-Empfänger verliert Sync


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von S. R. (svenska)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen UART-Transmitter und einen UART-Receiver in VHDL gebaut. 
Der Eingangstakt liegt bei 50 MHz, und bei 16x-Abtastung brauche ich 
einen Teiler von ~325, um auf 9600 Baud zu kommen. Soweit richtig?

Der Transmitter scheint zuverlässig zu funktionieren, ein
1
  data    <= x"30";
2
  trigger <= '1' when ready = '1' else '0';
sendet einen unendlich langen String aus Nullen.

Der Receiver funktioniert auch, verliert aber nach einiger Zeit den Sync 
(d.h. wenn ich Sender und Empfänger verbinde, dauert es knapp 80 
Zeichen, dann kommt Müll). An sich taste ich jedes Bit mittig ab und 
versuche, aufs nächste Startbit zu synchronisieren. Irgendwas mache ich 
da aber falsch.

Wie machen das bessere UARTs? Der USB-Seriell-Wandler auf dem Board 
schluckt meinen Transmittertest auch bei abweichendem Timing problemlos.

Ich habe außerdem die Vermutung, dass sowohl Transmitter als auch 
Receiver besser gemacht werden könnten. Für Verbesserungsvorschläge bin 
ich offen. :-)

Gruß,
svenska

von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bin kein FPGA-Spezi, aber wenn ich das richtig sehe, synchronisiert dein 
Receiver nach dem Stop-Bit nicht neu sondern machst einfach weiter.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> dann kommt Müll
Und was kommt denn anstelle der erwarteten 0x30?
Was macht die Simulation in diesem Szenario? Ist die Umschaltung dieser 
"enables" knapp beieinander?

> versuche, aufs nächste Startbit zu synchronisieren
Was passiert, wenn du 2 Stopbits sendest und dem Empfänger eine bessere 
"Synchronisationschance" gibst?

> Wie machen das bessere UARTs?
Von meiner Implementation weiß ich, dass sie vielfach eingesetzt wird 
und soweit problemlos läuft:
http://www.lothar-miller.de/s9y/categories/42-RS232

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
foobar schrieb:
> Bin kein FPGA-Spezi, aber wenn ich das richtig sehe, synchronisiert dein
> Receiver nach dem Stop-Bit nicht neu sondern machst einfach weiter.

Wenn ich das Enable nach dem Stopbit abschalte, bekomme ich meine 
Test-Textdatei auch nicht korrekt zurück.

Allerdings ist der Fehler an einer anderen Stelle: Meine Zeilenenden 
haben nur ein Byte (LF, weil Unix), mein Terminalprogramm (picocom) 
erwartet aber beide Bytes (CRLF). Mit "--imap lfcrlf" passt jetzt alles.

Insofern lag es also tatsächlich daran (und an meiner Inkompetenz). 
Danke für die Hilfe.

Lothar M. schrieb:
>> dann kommt Müll
> Und was kommt denn anstelle der erwarteten 0x30?

In der Simulation funktioniert alles. Im System kam die erste Zeile 
sauber an, irgendwann fehlen ein paar Zeichen und schließlich kamen 
Binärdaten, bis es irgendwann mit dem korrekten Text weiterging (für 
eine gewisse Zeit).

Laut Taschenrechner müsste mein Teiler 50 MHz / (16 * 9600) = 325.5 
sein. Mit 326 verliere ich viele Daten, mit 325 hin und wieder welche, 
mit 324 nicht. Bisschen seltsam.

Lothar M. schrieb:
>> Wie machen das bessere UARTs?
> Von meiner Implementation weiß ich, dass sie vielfach eingesetzt wird
> und soweit problemlos läuft:

Ja, an dem Empfänger habe ich mich ein bisschen orientiert. Ein Lob 
übrigens auf deine Webseite. Danke.

Ansonsten habe ich noch immer das Gefühl, dass meine Implementation 
irgendwie... ineffizient ist, aber immerhin funktioniert sie jetzt.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Also ein UART geht grob so:

Warten auf fallende Flanke.
Die Zeit von 1,5 ganzen Bits abwarten, bei 9600 Bd sind das also 
1,5*104,2 us = 156.3 us
Dann nacheinander 9 Bits in ein Schieregister schieben (jeweils die Zeit 
eines ganzen Bits warten).
Prüfen ob das 9te Bit eine "1" ist (Stoppbit).
Man ist jetzt in der Mitte vom Stoppbit. Also nochmal die Zeit eines 
ganzen Bits warten, dann ist man ein halbes Bit hinter dem Stoppbit. Ab 
jetzt kann eine neue Übertragung beginnen. Es geht also von vorne los, 
es wird auf eine fallende Flanke gewartet.

Edit:
Die Idee ist, dass man durch das anfängliche Warten von 1,5 mal der 
Dauer eines Bits alle weiteren Bits möglichst mittig erwischt wenn der 
Pegel stabil anliegt.

: Bearbeitet durch User
von uart-kenner (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Man ist jetzt in der Mitte vom Stoppbit. Also nochmal die Zeit eines
> ganzen Bits warten, dann ist man ein halbes Bit hinter dem Stoppbit. Ab
> jetzt kann eine neue Übertragung beginnen. Es geht also von vorne los,
> es wird auf eine fallende Flanke gewartet.

Ein halbes Bit hinter dem Stopbit hat man aber die fallende Flanke des 
nächsten Startbits vielleicht schon verpasst... Das kann nämlich auch 
direkt am Stopbit anschließen.

von Gustl B. (-gb-)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/RS-232_timing.svg/440px-RS-232_timing.svg.png

Das erste Datenbit muss sogar direkt hinter dem Startbit kommen. Und die 
Flanke von den Datenbits ist völlig egal. Es interessiert nur der Pegel.

Wenn die Leitung krasse Störungen hat kann man vielleicht noch gucken ob 
sich der Pegel seltsam ändert, aber wenn die Hardware passt genügt es 
jedes Bit nach dem Startbit einmal in dessen Mitte zu erfassen.

Im Anhang meine UART. Die ist getestet und funktioniert seit einigen 
Jahren im Dauereinsatz. Auch am FT(2)232H mit 12 MBaud. Man kann da den 
Takt und die Baudrate als Generic einstellen. Das ist jetzt vielleicht 
keine solderlich elegante Beschreibung, ist schon alt. Aber wenn ihr da 
echte Fehler drinnen findet, dann immer her damit.

: Bearbeitet durch User
von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Man ist jetzt in der Mitte vom Stoppbit.

Eher unwahrscheinlich. Man synct sich auf die Mitte des Startbits, damit 
man maximale Toleranz zu Taktunterschieden hat (schneller oder 
langsamer). Die Unterschiede summieren sich und beim Stopbit hängt man 
irgendwo im Bit, von ganz am Anfang bis ganz am Ende. Deshalb sollte man 
nach samplen des Stopbits sofort wieder in den 
"Warten-auf-Startbit-Flanke"-Zustand wechseln - da noch zu warten ist 
kontraproduktiv.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Und wenn nach dem Startbit eine "0" (Low) gesendet wird? Dann kommt 
keine Flanke. Tolle Wurst. Ausserdem sollten die Bits ziemlich sehr 
genau ähnlich lange sein. Zumindest als ich das letzte mal nachgemessen 
habe mit dem LA war das auch der Fall bei den CP2102, FT232R und 
FT(2)232H Bausteinen. Da liegt man also immer ziemlich perfekt in der 
Mitte.

von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich rede nicht von unterschiedlichen Bitlängen, sondern von den 
Taktunterschieden zwischen Sender und Empfänger!

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
OK, aber Quarze sind heute echt gut genug. Selbst wenn sich der Takt um 
1% was echt krass viel ist unterscheiden sollte fällt das am Ende nicht 
auf. Es macht jedenfalls keinen Sinn nach dem Startbit auf irgendwelche 
Flanken zu warten, es könnte ja auch "00000000" gesendet werden.

von foobar (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Wenn deine Quarze so gut sind, kannst du ja gerne das "A" aus UART 
weglassen und dir deine persönliche URT machen.

Und les bitte nochmal genauer was ich geschrieben habe - ich sagte 
nirgendwo, dass man nach dem Startbit auf ne Flanke warten soll.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
UPS, stimmt, sorry, habe heute eine Leseschwäche. Ich nehme alles zurück 
und behaupte das Gegenteil.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Nach dem Einlesen des Stopbits, das ja in der Mitte des Stopbits 
passiert, macht man sich natürlich sofort bereit für das nächste 
Startbit...

foobar schrieb:
> Man synct sich auf die Mitte des Startbits
Man kann doch nicht auf die Mitte des Startbits synchronisieren  wenn 
man nicht weiß, wo es aufhören wird. Ich nehme deshalb die Startflanke, 
lese dann nach einer halben Bitdauer das Startbit ein und schiebe es 
einfach durch das Empfangswort, bis es wieder rausfällt.

S. R. schrieb:
> Mit 326 verliere ich viele Daten, mit 325 hin und wieder welche, mit 324
> nicht. Bisschen seltsam.
Das ist der Wert für den Empfänger? Welchen Wert hast du dann beim 
Sender?

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
>> Mit 326 verliere ich viele Daten, mit 325 hin und wieder welche, mit 324
>> nicht. Bisschen seltsam.
> Das ist der Wert für den Empfänger?
> Welchen Wert hast du dann beim Sender?

Ja, der Wert wird für den Empfänger benutzt. Der Sender ist ein auf dem 
Board verbauter CP2102 (USB-Seriell-Wandler).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.