Hallo,
ich habe mal eine Frage bezüglich der seriellen Kommunikation. Da ich
nicht wirklich weiter komme, dachte ich, ich versuche mir mal Hilfe
ranzuholen. Ich habe schon viele Foren Beiträge gelesen, wurde daraus
aber nicht wirklich schlauer.
Ich versuche eine serielle Kommunikation zwischen einem FPGA und einem
DSPACE herzustellen. Dafür will ich die RS-485 Schnittstelle verwenden.
Auf den FPGA will ich einen UART-Code (vhdl) flashen und den DSPACE
entweder als Empfänger oder Sender verwenden. Es geht mir erstmal darum,
dass die zwei Geräte untereinander kommunizieren können.
Der UART-Code soll dafür sorgen, dass die Signale richtig empfangen bzw.
gesendet werden. Hierfür tastet er das Signal ab und erkennt die Start
Bit, 8 Data Bits und die Stop Bit. Die Clock-Frequenz und die Baudrate
gebe ich dabei vor (50 MHz und 115200 baud). Den UART-Code habe ich
unten verlinkt.
Nun zu meinen Fragen:
1) Die RS485 Schnittstelle arbeitet mit den Spannungspegeln von maximal
-7V (logisch '1') und +12V (logisch '0'). Da der untere Pegel (-7V) die
'1' darstellt, muss das Signal invertiert werden. Dies geschieht über
einen TTL to RS485 Converter. Dies habe ich zumindest nach meiner
Recherche so verstanden. Ist das richtig so? Es sollte dann ja reichen,
wenn er das Signal auf -5V und +5V konvertiert oder?
2) Ich verstehe noch nicht so ganz, wie die Signale aus meinem UART Code
den Signalen A und B der RS-485 Schnittstelle entsprechen. Die Leitungen
A und B sollen ja symmetrisch sein, d.h. A ist das Komplementär von B
und umgekehrt. Der UART Code gibt ja aber nur ein Signal raus, entweder
RX oder TX. Geschieht die Invertierung des zu sendenden bzw. zu
empfangenden Signal dann ebenfalls in dem Converter oder wie muss ich
das implementieren? Ist mein UART-Code generell korrekt für eine RS-485
Schnittstelle?
3) Ich bin noch nicht genau schlau daraus geworden, wie ich meine
Signale mit dem Converter verbinden muss. Angennommen der FPGA soll
senden und der DSPACE empfangen. Der FPGA bekommt von mir den zu
sendenen Wert über das i_TX_Byte Signal zugewiesen (z.B. X"AA"). Die
Clock erhält er auch intern. Über einen Knopfdruck gebe ich dem FPGA das
Signal, dass er senden darf (i_TX_DV). Aus meinem Verständnis her würde
ich dann das TX Signal (o_TX_Serial) an den Converter führen (an TX).
Ich verstehe aber nicht, wie ich meine restlichen Signal herausfürhren
soll, da ich ja effektiv nur 2 Leitungen habe. Bei meinem aktuellen Code
brauche ich ja aber z.B. mein o_TX_Done Signal, damit eine neue
Übertragung beginnen kann
Ich wäre über jede Hilfe sehr dankbar, da ich jetzt echt schon lange
daran sitze und am mittlerweile echt am verzwifeln bin.
Meinen UART-Code habe ich von hier:
https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html
Bei UART_RX habe ich die Signal o_RX_DV und o_RX_Byte auskommentiert, da
diese ja nur Feedback über eine richtige Übertragung geben. Soll ich die
Signal bei UART_TX dann auch auskommentieren (also o_TX_ACTIVE und
o_TX_Done)? Das macht den Code aus meiner Sicht aber fehleranfälliger.
Der Code ist soweit ich weiß, aber auch für alle 9 Pins des Sub-D
Steckers gedacht.
Jonas schrieb:> Ich versuche eine serielle Kommunikation zwischen einem FPGA und einem> DSPACE herzustellen.
Meine Kommunikation mit DSPACE läuft über einen Browser, das Internet
und deren Webserver.
Du darfst gerne konkreter werden, welche Hardware tatsächlich zum
Einsatz kommt. Auch auf FPGA-Seite.
> Es sollte dann ja reichen,> wenn er das Signal auf -5V und +5V konvertiert oder?
Mit diesen Spannungen bekommst Du Deinen FPGA mit Sicherheit kaputt,
wenn die direkt auf die Pins gehen.
Der Leitungstreiber macht üblicher die Pegelanpassung und die
differentielle Signalaufbereitung.
Mit welchen Spannungen Dein FPGA arbeiten kann, kannst Du aus dem
Datenblatt entnehmen. Wenn Du ein fertiges Board hast, hat der Designer
sich üblicherweise für eine feste Logikspannung entschieden (die aber je
nach Pin auch anders sein kann, Stichwort: IO-Bänke).
Heutzutage sind da maximal Spannungen von 3,3 V üblich, z.T. deutlich
weniger.
Duke
Also auf der FPGA Seite ist ein Spartan 6 Board. Das FPGA (XC6SLX100)
liegt auf einem Trägerboard TE0603.
Auf der DSPACE Seite ist der Prozessor eine DS1007 Prozessor Karte und
ein DS2202 Board auf dem direkt die RS485 Schnittstelle vorhanden ist.
Das heißt auf dieser Seite stecke ich den Sub-D ganz normal ein.
So wenn ich das jetzt richtig verstanden habe geht ich jetzt auf der
anderen Seite (FPGA) Seite von dem Sub-D Stecker auf einen
Treiberbautstein (z.B. MAX490CSA+), welcher mit 5V versorgt wird und
mein Signal in 3.3V umwandelt, sodass das FPGA Board dies vertragen
kann. Der Treiberbaustein invertiert das Signal und löst bzw. stellt die
Differenz der Leitungen A und B auf.
Stimmt das so? Vielen DAnk schonmal für die schnelle Antwort
Moin,
ohne jetzt den VHDL-Code angesehen zu haben: Schau dir doch erst mal die
Funktionsweise eines RS485-Transceivers an, angefangen mit den einfachen
MAX485 (aber in 3.3V Ausführung). Wichtig ist nur der DE, der bestimmt,
wann der Treiber auf den Bus treibt, während eines Datenpakets im
half-Duplex-Betrieb geht der bloss HIGH. Beim einfachen UART wird der
RTS für den DE 'missbraucht', das geht auch in den meisten Fällen. Nur
wenn die Timings kritisch sind (Modbus oder Realtime-Systeme) kann's mit
der software-mässigen Implementierung knifflig werden, dann empfiehlt
sich ein UART-Core mit HW-implementiertem RS485-Modus. Ist aber erst mal
was für später...
Hier grad noch einen Link ausgegraben:
https://www.logic-control.com/datasheets/4/Tech%20Note/The%20Secrets%20of%20RS-485%20Half%20Duplex%20Communication.pdf
Also ein RS485 transceiver wird nach meinem Verständnis mit einer
Spannung versorgt(hier 3.3V). Die Pins für die eigentliche RS485 Leitung
sind dann A und B (oder D+ und D-), wobei A das Komplementär von B ist
und umgekehrt. Das sind dann die beiden Leitungen, die ich auch an den
Sub-D Stecker anschließen kann. Über den D Eingang bekommt der RS485
Transceiver den DATA Input und über R den DATA Output.
Der DE Pin (Driver Enable) ist der wichtigste Pin (wahrscheinlich um
Kollisionen zu vermeiden) und gibt an, ob Daten gesendet werden (dann
High-Pegel). Das heißt, wenn ich das so richtig verstehe sollte ich
diesem Pin das Signal o_TX_Active meines UART Codes zuweisen, damit ich
sagen kann, wann Daten gesendet werden sollen.
Ich verstehe aber nicht wie der RTS (Request to send) für den DE
missbraucht wird. Der DE gibt doch an, wann Daten gesendet werden. Der
RTS gibt doch aber bevor die Daten gesendet werden ein Signal, dass
signalisiert, dass gleich Daten gesendet werden
Der RE Pin (Receiver Enable) gibt an, ob der Receiver empfängt (mit
einem Low Pegel). Wenn ich diesen Pin frei lasse, ist dann der Receiver
dauerhaft aktiv, solange der Transceiver nicht aktiv ist? Ich vermute
mal nein...
Jonas schrieb:> Ich verstehe aber nicht wie der RTS (Request to send) für den DE> missbraucht wird. Der DE gibt doch an, wann Daten gesendet werden. Der> RTS gibt doch aber bevor die Daten gesendet werden ein Signal, dass> signalisiert, dass gleich Daten gesendet werden>> Der RE Pin (Receiver Enable) gibt an, ob der Receiver empfängt (mit> einem Low Pegel). Wenn ich diesen Pin frei lasse, ist dann der Receiver> dauerhaft aktiv, solange der Transceiver nicht aktiv ist? Ich vermute> mal nein...
Das ist ok wenn das timingmässig passt.
In Einzelfällen hat man einen langsamen Receiver, der das Ready signal
haben mus, bevor es beginnt. Wenn das aber echt hardware ist, muss der
Sender sicherstellen, dass er nicht beginnt zu senden, solange der
andere oder "ein anderer" aktiv ist. Das ist eine Aufgabe der time slot
Verwaltung im System.
HW-technisch ist das Jacke wie Hose.
Wir haben solche Signale auch schon über Gates gezogen, um sie noch ein
paar Dutzend ns zu verschleppen, damit es keine Kollisionen gibt.
Mal dir mal ein Timing auf.
Jonas schrieb:> Der DE Pin (Driver Enable) ist der wichtigste Pin (wahrscheinlich um> Kollisionen zu vermeiden) und gibt an, ob Daten gesendet werden (dann> High-Pegel).
Richtig.
So wie im Anhang sollte es nicht aussehen.
Duke
Jonas schrieb:>> Der DE Pin (Driver Enable) ist der wichtigste Pin (wahrscheinlich um> Kollisionen zu vermeiden) und gibt an, ob Daten gesendet werden (dann> High-Pegel). Das heißt, wenn ich das so richtig verstehe sollte ich> diesem Pin das Signal o_TX_Active meines UART Codes zuweisen, damit ich> sagen kann, wann Daten gesendet werden sollen.> Ich verstehe aber nicht wie der RTS (Request to send) für den DE> missbraucht wird. Der DE gibt doch an, wann Daten gesendet werden. Der> RTS gibt doch aber bevor die Daten gesendet werden ein Signal, dass> signalisiert, dass gleich Daten gesendet werden>
Mach doch mal ne Simulation, damit man deine Timings sieht. Kann schon
klappen bei ner niedrigen Baudrate.
Ein dauernd toggelndes TX_Active für jedes einzelne Byte kann allerdings
unter Umständen Probleme machen, insbesondere wenn du was wie Modbus
laufen hast, da sind die Timings und Timeouts essentiell.
Mit dem RTS hast du mehr softe Kontrolle über den enable über die Dauer
deines Datenpakets, bzw. harte Kontrolle wenn du einen RS485_MODE
implementierst.
> Der RE Pin (Receiver Enable) gibt an, ob der Receiver empfängt (mit> einem Low Pegel). Wenn ich diesen Pin frei lasse, ist dann der Receiver> dauerhaft aktiv, solange der Transceiver nicht aktiv ist? Ich vermute> mal nein...
Den Pin solltest du typischerweise nicht floaten lassen, da er
invertiert, hängt man ihn normalerweise mit dem DE zusammen, am FPGA
kannst du sie ja logisch gleichzeitig treiben und hältst dir weitere
Optionen ("Shutdown/Loopback") offen.
Duke Scarring schrieb:> Richtig.> So wie im Anhang sollte es nicht aussehen.
Ja das macht Sinn. So sieht es bei mir aber derzeit nicht aus
Martin S. schrieb:> Mach doch mal ne Simulation, damit man deine Timings sieht. Kann schon> klappen bei ner niedrigen Baudrate.> Ein dauernd toggelndes TX_Active für jedes einzelne Byte kann allerdings> unter Umständen Probleme machen, insbesondere wenn du was wie Modbus> laufen hast, da sind die Timings und Timeouts essentiell.> Mit dem RTS hast du mehr softe Kontrolle über den enable über die Dauer> deines Datenpakets, bzw. harte Kontrolle wenn du einen RS485_MODE> implementierst.
Ich habe meinen UART-Code in ModelSim bereits simuliert. Dort klappt
alles soweit. Mein TX_Active toogelt aber quasi pro Byte. Die Baudrate
ist 115200 und die Clock des FPGA 50 MHz. Ich würde gerne ein Bild der
Simulation anhängen, allerdings ist es schwer dort alles zu erkennen.
Ich habe es dennoch mal angehangen. Nach dem Senden wird bei mir
testweise ein Byte zum Empfangen geschickt.
Mit meiner aktuellen Baudrate würde ich schätzen, dass das toggle nicht
zu stark ist.
Den DE und RE Pin werde ich dann zusammen schalten
Ich habe nochmal eine Frage:
Auf der DSPACE-Seite sitzt jetzt eine DS1007 Prozessorkarte und eine
DS2202 HiL I/O Karte inkl. Controller Panel. Auf dem Panel befindet sich
die Schnittstelle RS232/RS422, an die ich gerne mit meinem Sub-D Stecker
gehen möchte. Damit ich eine serielle Kommunikation zwischen dem FPGA
und DSPACE über RS485 herstellen kann, muss ich ja auf der DSPACE Seite
einstellen können, wann der Sender und wann der Empfänger aktiv ist,
damit es nicht zu Kurzschlüssen kommt.
So wie ich das verstanden habe ist der UART Code, sowie der
Treiberbaustein für RS232 bzw. RS485 ja bereits in dem DSPACE Board
verbaut, d.h. ich habe da ja nicht wirklich Einfluss drauf. Schaltet das
DSPACE Board dann automatisch zwischen Sender und Empfänger über das RTS
Signal hin und her oder muss ich da noch was machen?
Leider ist in der Uni das passende Handbuch zu der Karte abhanden
gekommen, sodass ich dort nicht direkt reinschauen kann..
Ich wäre über jede Hilfe sehr dankbar :)
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