Forum: Mikrocontroller und Digitale Elektronik falsches Verständnis für RTS/CTS Handshake?


von Ralf (Gast)


Lesenswert?

Hi,

ich implementiere gerade RTS/CTS Handshake auf einem Controller. Bei 
meinen HowTo-Recherchen bin ich auf zwei unterschiedliche 
Implementierungen gestoßen:

1) Ein Teilnehmer signalisiert durch RTS, dass Daten gesendet werden 
(wollen). Die Gegenstelle signaliert durch RTS, dass sie für den Empfang 
bereit ist.

2) Ein Teilnehmer signalisiert durch RTS, dass Daten angenommen werden 
können.

Bisher kannte ich eigentlich nur Variante 2, die ich auch gerade zu 
implementieren versuche. Sollte ja soweit passen, denke ich.

Für einen einfachen Test habe ich RTS/CTS der Controllerschaltung 
miteinander verbunden, wie man es auch bei den einfachen Kabeln am PC 
sieht. Der Handshake bedient sich also lokal selbst. Über den PC sende 
ich ohne Handshake Daten zum Controller. Dieser sendet die Daten 
postwendend zurück, also quasi reines Echo.
Wähle ich nun eine Baudrate aus, die so schnell ist, dass der Controller 
die Daten nicht schnell genug umschaufeln kann, bedient er auch 
entsprechend RTS.

So, mein Problem ist nun folgendes: Der Controller sendet nur, wenn CTS 
aktiv ist. Da er aber RTS deaktiviert hat, wird nicht mehr gesendet. Die 
Funktion, die die Daten aus dem Empfangs- in den Sendebuffer schiebt 
bleibt somit hängen, wenn der Sendebuffer voll ist. Somit komme ich gar 
nicht dazu, den Empfangsbuffer zu leeren, um RTS wieder zu aktivieren. 
Quasi Henne-Ei-Problem.
Leider habe ich bei meiner Suche kein FlowChart oder ähnliches gefunden, 
was eine 'ordentliche' Handshake-Implementierung beschreibt. Falls also 
jemand etwas in der Hinsicht kennt, wäre ein Hinweis nett.

Dann wär da noch die Frage, ob mein Test und die Implementierung 
überhaupt stimmig sind: Erstens wär die Frage, ob ich mit dem Senden 
aufhören soll, sobald CTS deaktiviert ist, oder stattdessen einfach 
nichts mehr in den Sendebuffer eintragen, wenn CTS deaktiviert ist, den 
Sendebuffer aber trotzdem noch rauspusten (so macht es glaube ich der 
PC).
Momentan habe ich ersteres implementiert.

Zweitens kam mir die Überlegung, dass ich evtl. nicht einfach aus dem 
Empfangsbuffer in den Sendebuffer schieben darf, sondern für diesen 
speziellen Test eben auch einen Zwischenbuffer anlegen müsste, um einen 
Deadlock zu vermeiden.

Die Implementierung selbst ist wie folgt:
- Ringbuffer für Senden und Empfangen, funktioniert ohne Handshake
- Die Funktion für das Schreiben eines Bytes prüft, ob Platz im 
Sendebuffer ist, wenn nicht, wird gewartet (deadlock?)
- Der Empfangsinterrupt bedient RTS, wenn eine bestimmte Anzahl an Bytes 
im Buffer überschritten ist
- Die Funktion für das Auslesen des Empfangsbuffer bedient RTS, wenn die 
o.g. Anzahl unterschritten wird
- Der Sendeinterrupt sendet das nächste Byte aus dem Buffer nur, wenn 
CTS aktiv ist
- Solange gesendet wird, ist ein Flag gesetzt, dieses wird gelöscht, 
wenn keine Bytes mehr im Buffer sind oder der Sendeinterrupt eine 
inaktives CTS feststellt
- Das CTS-Signal wird mit einem externen Interrupt ausgewertet, wechselt 
CTS zum aktiven Zustand und ist das o.g. Flag nicht gesetzt, wird der 
Sendeinterrupt ausgelöst, dieser prüft dann, ob Bytes zum Senden 
vorhanden sind und agiert entsprechend

Ich würde mich freuen, wenn mir jemand sagen kann, ob ich wenigstens 
einigermaßen auf'm richtigen Weg bin.

Ralf

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Ralf schrieb:
> 1) Ein Teilnehmer signalisiert durch RTS, dass Daten gesendet werden
> (wollen). Die Gegenstelle signaliert durch RTS, dass sie für den Empfang
> bereit ist.
>
> 2) Ein Teilnehmer signalisiert durch RTS, dass Daten angenommen werden
> können.
>
> Bisher kannte ich eigentlich nur Variante 2, die ich auch gerade zu
> implementieren versuche. Sollte ja soweit passen, denke ich.

Beides nicht.

RTS Request to send (ich will senden, sachma)
CTS Clear to send (also schick mal)

von (prx) A. K. (prx)


Lesenswert?

Ralf schrieb:
> 1) Ein Teilnehmer signalisiert durch RTS, dass Daten gesendet werden
> (wollen). Die Gegenstelle signaliert durch RTS, dass sie für den Empfang
> bereit ist.

Als simple Modems üblich waren, signalisierte das Endgerät (DTE = data 
terminal equipment) dem Modem per RTS, dass es senden will, und das 
Modem (DCE = data communication equipment) antwortete mit CTS, wenn es 
das darf. Das war insbesondere bei Halbduplex-Verfahren für die 
Richtungsumschaltung wichtig.

Mit dem heutigen RTS/CTS-Handshake zur Drosselung der Übertragung hat 
das nichts zu tun, ist aber der Grund für den Namen "RTS".

> 2) Ein Teilnehmer signalisiert durch RTS, dass Daten angenommen werden
> können.

Das ist der RTS/CTS Handshake. Man hätte statt RTS auch DTR (data 
terminal ready) verwenden können, um den irritierenden Widerspruch zum 
Namen zu vermeiden. Bei Druckern hat man das auch so gemacht. Bei 
Computer-Terminals aber nicht, und daher stammt diese Methode.

von MaWin (Gast)


Lesenswert?

RS232 stammt aus der Modem-Zeit. An diesen (DCE) ist RTS ein Eingang. 
Solche Endgeräte die über nicht gekreuzte Kabel mit dem PC verbunden 
werden sind aber inzwischen unüblich könnten aber Ursache deiner 
Verwirrung sein.
Ein Moden ist immer übertragungsbereit, es signalisiert mit CTS 
(Erinnerung: Ist dort ein Ausgang,verbunden mit dem Eingang CTS am PC) 
nicht dass es selbst bereit ist (das tut es durch DSR, am Modem ein 
Ausgang, verbundem mit dem Eingang DSR am PC und aktiviert nach dem der 
PC durch seinen Ausgang DTR dem Modem mit dessen Eingang DSR gesagt hat 
dass es sich einschalten soll), sondern dass die Gegenseite bereit ist.

Beim Modem passiert das überkreuzen also auf der Telefonleitung.

Ohne Modem bei PC/PC Direktverbindung sind immer unterschiedlich 
lautende Pins verbunden, RTS-CTS. Wenn derAusgang RTS dem Eingang CTS 
sagt dass nicht mehr gesendet werden soll, muss das aktuelle Byte 
trotzdem noch gesendet wrrden, nicht mittendrin abbrechen.

von (prx) A. K. (prx)


Lesenswert?

Ralf schrieb:
> Dann wär da noch die Frage, ob mein Test und die Implementierung
> überhaupt stimmig sind: Erstens wär die Frage, ob ich mit dem Senden
> aufhören soll, sobald CTS deaktiviert ist, oder stattdessen einfach
> nichts mehr in den Sendebuffer eintragen, wenn CTS deaktiviert ist, den
> Sendebuffer aber trotzdem noch rauspusten (so macht es glaube ich der
> PC).

Der sicherste und verbreitetste Weg ist, direkt das Senden zu 
unterbinden. Bei PCs mit USB/Seriell-Konverter ist das aber nur dem 
USB-Konverter möglich, der PC-Software ist das aufgrund des recht 
happigen Puffers dazwischen nicht möglich. Das muss folglich dem Treiber 
und damit dem Konverter mitgeteilt werden.

von Reinhard Kern (Gast)


Lesenswert?

MaWin schrieb:
> Wenn derAusgang RTS dem Eingang CTS
> sagt dass nicht mehr gesendet werden soll, muss das aktuelle Byte
> trotzdem noch gesendet wrrden, nicht mittendrin abbrechen.

Das ist totaler Blödsinn, das sollte man schon merken wenn man bloss 
etwas Englisch kann. RTS heisst ich möchte senden, CTS heisst du darfst 
senden. Also setzt der PC RTS, wenn er was senden möchte, tut das aber 
erst, wenn das angeschlossene Gerät, z.B. ein Modem, mit CTS 
signalisiert, dass es dazu bereit ist, die Daten zu übernehmen.

Joachims Antwort "Beides nicht" war also korrekt, die übrigen sinnloses 
Geplapper von Leuten die nicht den Schatten einer Ahnung haben.

Gruss Reinhard

von Daniel (Gast)


Lesenswert?

Früher hatten RTS und CTS mal diese Bedeutung.
Heute üblich ist RTS mit CTS der Gegenstelle zu verbinden und dann 
darüber zu signalisieren, ob noch Daten empfangen werden können. Das 
wird dann Symmetrisch in beide Richtungen gemacht. So macht das sowohl 
Windows als auch Linux.

von Ralf (Gast)


Lesenswert?

Guten Morgen zusammen,

vielen Dank für eure Antworten.

@Joachim Drechsel:
> Beides nicht.
> RTS Request to send (ich will senden, sachma)
> CTS Clear to send (also schick mal)
Eigentlich dachte ich, eben genau dieses in meiner Variante 1) 
beschrieben zu haben (allerdings auf RTS beider Teilnehmer bezogen)

@A.K.:
Danke für die Erläuterung, dieser entnehme ich, dass 2) heute wohl 
üblicher ist, zumal mein Controller in dem Sinne ja kein DCE ist.

@MaWin:
> Ohne Modem bei PC/PC Direktverbindung sind immer unterschiedlich
> lautende Pins verbunden, RTS-CTS. Wenn derAusgang RTS dem Eingang CTS
> sagt dass nicht mehr gesendet werden soll, muss das aktuelle Byte
> trotzdem noch gesendet wrrden, nicht mittendrin abbrechen.
Klar, ein bereits im UART befindliches Byte kann man eh nicht mehr 
stoppen (ausser vielleicht Portpin hart auf GND setzen).
Das "aktuelle Byte" ist dann wirklich nur noch das aktuelle Byte (so hab 
ich's aktuell implementiert), oder der aktuelle Inhalt des Sendebuffers 
des UARTs(nicht vom Buffer von Windows, einem Schnittstellenobjekt oder 
sonstwas)?
Ich frag deswegen, weil man ja die Schwelle für das Deaktivieren von RTS 
immer ein paar Bytes unterhalb der eigentlich Buffergröße ansetzen soll, 
da angeblich trotz deaktiviertem RTS immer noch ein paar Bytes 
reintröpfeln könnten...

@Reinhard:
> Das ist totaler Blödsinn, das sollte man schon merken wenn man bloss
> etwas Englisch kann. RTS heisst ich möchte senden, CTS heisst du darfst
> senden. Also setzt der PC RTS, wenn er was senden möchte, tut das aber
> erst, wenn das angeschlossene Gerät, z.B. ein Modem, mit CTS
> signalisiert, dass es dazu bereit ist, die Daten zu übernehmen.
Wird es denn heutzutage auch wirklich noch so gehandhabt? :)
Die Signalnamen, die vor zehn, zwanzig, dreissig oder was weiss ich wie 
vielen Jahren für den damaligen Zweck verwendet wurden müssen heute 
nicht mehr unbedingt etwas mit ihrer tatsächlichen Arbeitsweise zu tun 
haben... Ich weiss leider nicht, ob die Option 'Hardware-Handshake' eine 
BIOS Funktion ist, dann würde sich jeder Rechner nahezu gleich 
verhalten. Wenn nicht, dann ist es Sache des OS oder gar nur der 
jeweiligen Software, welche die Schnittstelle grad im Zugriff hat...

> Joachims Antwort "Beides nicht" war also korrekt, die übrigen sinnloses
> Geplapper von Leuten die nicht den Schatten einer Ahnung haben.
Warum so gereizt? Aber abgesehen davon, es könnte auch einfach sein, 
dass die o.g. Antworten einfach daher kommen, dass den Leuten eben nur 
die jeweiligen Funktionsweisen begegnet sind.

@Daniel:
> Früher hatten RTS und CTS mal diese Bedeutung.
> Heute üblich ist RTS mit CTS der Gegenstelle zu verbinden und dann
> darüber zu signalisieren, ob noch Daten empfangen werden können. Das
> wird dann Symmetrisch in beide Richtungen gemacht. So macht das sowohl
> Windows als auch Linux.
So in etwa kenne ich das auch. Jetzt muss ich aber noch herausfinden, 
wie ich das Henne-Ei-Problem lösen kann.

@Alle:
Nochmals besten Dank für alle bisherigen Antworten. Nach wie vor ist 
jetzt aber immer noch die Frage nach der nicht funktionierenden 
Selbstfreischaltung offen. Alle weiteren dienlichen Infos sind natürlich 
auch willkommen :)

Ralf

von (prx) A. K. (prx)


Lesenswert?

Ralf schrieb:
> Ich frag deswegen, weil man ja die Schwelle für das Deaktivieren von RTS
> immer ein paar Bytes unterhalb der eigentlich Buffergröße ansetzen soll,
> da angeblich trotz deaktiviertem RTS immer noch ein paar Bytes
> reintröpfeln könnten...

So ist es. Die Hardware einer klassischen seriellen Schnittstelle hat 
einen Puffer und wenn diese Hardware nicht selbst schon eine Kopplung 
mit RTS vorsieht, dann will der Inhalt des Puffers trotzdem raus. Simple 
UARTs eines µC mit nur einem Byte Puffer senden also ggf. 2 Bytes bevor 
sie Ruhe geben.

von Rangi J. (rangi)


Lesenswert?

So wie ich es kenne (also nicht die alte Arbeitsweise) sind die 
Leitungen in beide Richtungen erstmal auf Kommunikation erlauben. Dann 
sendet ein Teilnehmer z.b ein paar Daten aber an RTS/CTS ändert sich 
nichts. Erst wenn bei einem Partner die Puffer voll sind, dann wird 
dieser seinen RTS Ausgang auf "Stop" stellen. Dann muss der Gegner 
aufhören zu senden. Das stellt er fest in dem er seinen CTS-Eingang 
überwacht welcher ja mit dem RTS des Empfängers verbunden ist.
Sind die Puffer wieder frei, wird RTS wieder freigegeben und der Sender 
darf weitersenden.
Die Kommunikation zwischen µCs läuft byteorientiert ab. Das meint, das 
wenn die Leitung gezogen wird, wird das aktuelle Byte noch gesendet, 
danach darf aber nichts mehr kommen (Pufferfüllstand 100%). Das macht 
dann die DMA, bzw. Hardware selbsttätig. Mache Implemtationen sind sogar 
so aufgebaut, dass die RTS Leitung gezogen wird nachdem das Byte 
komplett empfangen wurde und losgelassen wird sobald das Byte aus der 
Schnittstelle gelesen wird (z.b. im Interrupt). D.h. das nach jeden Byte 
ein kurzer Spike auf RTS gemessen werden kann.
Das Problem sind PC-Schnittstellen. Hier können nach dem per RTS ein 
Stop signalisiert wurde noch einige Bytes nach kommen. Bei meinem 
aktuellen Rechner und 115200 sind das 9 bis 10 Bytes bevor der aufhört 
Daten zu senden. Deswegen muss man auf Controller-Ebene seinen 
Pufferfüllstand auswerten und ab einem bestimmtem Füllstand (z.b. 75%) 
schon die RTS-Leitung ziehen.

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:


> Das "aktuelle Byte" ist dann wirklich nur noch das aktuelle Byte (so hab
> ich's aktuell implementiert), oder der aktuelle Inhalt des Sendebuffers
> des UARTs(nicht vom Buffer von Windows, einem Schnittstellenobjekt oder
> sonstwas)?
> Ich frag deswegen, weil man ja die Schwelle für das Deaktivieren von RTS
> immer ein paar Bytes unterhalb der eigentlich Buffergröße ansetzen soll,
> da angeblich trotz deaktiviertem RTS immer noch ein paar Bytes
> reintröpfeln könnten...

Du musst damit rechnen, dass dein Gegenüber nicht sofort aufhört, 
sondern noch ein paar Bytes kommen. Wenn der eine UART hat, die nicht, 
wie der AVR nur 1 Byte buffert, sondern ein paar mehr, dann kann nämlich 
er wiederrum nicht sofort den ganzen Vorgang stoppen.

> Wird es denn heutzutage auch wirklich noch so gehandhabt? :)

Was hier noch ins Spiel kommt, ist dass es 2 Arten von Kabeln gibt.
gekreuzte und nicht gekreuzte Kabel. Und damit auch, ob RTS auf CTS 
führt oder ob RTS auf RTS führt.

Ja ich weiß, das alles ist ein ziemliches durcheinander.

> vielen Jahren für den damaligen Zweck verwendet wurden müssen heute
> nicht mehr unbedingt etwas mit ihrer tatsächlichen Arbeitsweise zu tun
> haben...

Doch, denn am Funktionsprinzip hat sich ja nichts geändert.
Der ganze Pallawatsch entstand dadurch, dass man am Anfang keine 
direkten Computer zu Computer Verbindungen hatte, sondern zwischen 2 
Computer 2 Modems hatte, die mit einem 1:1 Kabel an die Computer 
angebunden wurden. D.h. die Verbindung Sendeleitung-Empfängerleitung 
wurde vom Modem 'gekreuzt'. Als man dann dazu überging Rechner direkt 
miteinander zu verbinden, legte man diese Kreuzung naheliegenderweise 
ins Kabel. Aber am Funktionsprinzip hatte sich nichts geändert. Konnte 
auch nicht, denn es wurden ja nach wie vor dieselben Endgeräte mit 
denselben Schnittstellen und dem selben Handshake-Funktionsprinzip 
verwendet.


> So in etwa kenne ich das auch. Jetzt muss ich aber noch herausfinden,
> wie ich das Henne-Ei-Problem lösen kann.

Welches Henne/Ei Problem?

> Nochmals besten Dank für alle bisherigen Antworten. Nach wie vor ist
> jetzt aber immer noch die Frage nach der nicht funktionierenden
> Selbstfreischaltung offen. Alle weiteren dienlichen Infos sind natürlich
> auch willkommen :)

Es läuft praktisch gesehen auf diese Strategie hinaus
Ehe ein Byte gesendet wird, wird der Zustand des CTS-Eingangs überprüft. 
Ist der OK, dann darfst du das Byte wegschicken.
Umgekehrt: empfängst du ein Byte, dann schaust du dir den Füllgrad 
deines Buffers an und entscheidest, ob du deinen eigenen RTS-Ausgang 
zurücknehmen musst. Mit Abarbeitung des Buffers kann der dann irgendwann 
wieder freigegeben werden.

Im Grunde kannst du so vorgehen: RTS hat seine Bedeutung verloren. Der 
Sender fragt nicht mehr wortwörtlich an, ob er senden darf. Sondern das 
Gegenüber signalisiert mit seinem RTS-Ausgang dem Sender (der dieses 
Signal an seinem CTS bekommt), ob er aufnahmebereit ist. Und da das 
natürlich wechselseitig so sein muss, muss es logischerweise auch 2 
Leitungen dafür geben. Heutzutage ist die Bezeichnung RTS irreführend. 
Besser wäre es RTR (Ready to Receive) zu nennen, mit der das jeweilige 
Gerät signalisiert, ob es aufnahmebreit ist oder nicht.

: Wiederhergestellt durch User
von Rangi J. (rangi)


Lesenswert?

@ Karl Heinz Buchegger
CTS ist der Eingang, RTS der Ausgang, so stehts in den Datenblättern der 
Controller die ich kenne, also so als wären sie PCs und keine Modems.

UPDATE: du hast es schon korrigiert

von Karl H. (kbuchegg)


Lesenswert?

Rangi Jones schrieb:
> @ Karl Heinz Buchegger
> CTS ist der Eingang, RTS der Ausgang, so stehts in den Datenblättern der
> Controller die ich kenne, also so als wären sie PCs und keine Modems.

Sag ich doch :-)
(Ne, du hast schon recht. Ich hab beim Korrekturlesen nach dem Posten 
gemerkt, dass ich mitten drinn auch durcheinander gekommen bin und habs 
nachträglich korrigiert. Es ist eben ein Durcheinander mit den 
Bezeichnungen. Genauso, wie es ein Durcheinander gibt, wer jetzt eine 
Buchse haben sollte und wer einen Stecker.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Ich finde, mit dem Bild (aus dem AVR-Tutorial:Uart) ist am besten 
ausgesagt, wer wem was zu signalisieren hat.

von Rangi J. (rangi)


Lesenswert?

Regel 1 beim Verbinden der Schnittstellen: einfach verbinden, du hast 
50% Gewinnchance.
Denn wenn du eine Stunde drauf verwendest es herauszufinden ärgerst du 
sich am Ende doch nur weil es trotzdem falsch war.

von Georg G. (df2au)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich finde, mit dem Bild (aus dem AVR-Tutorial:Uart) ist am besten
> ausgesagt, wer wem was zu signalisieren hat.

Auch, wenn es aus einem Tutorial ist, muss es nicht ganz richtig sein.

RTS und CTS gehören zusammen. Der eine Teilnehmer (PC als Beispiel) sagt 
dem anderen (Modem als Beispiel) per RTS, das er senden möchte. Das 
Modem unternimmt alles notwendige, um diesen Wunsch erfüllen zu können. 
Wenn es bereit ist, gibt es mit CTS die Datenübertragung frei. Wenn es 
dann zwischendurch Probleme gibt, kann das Modem CTS wegnehmen und damit 
die Übertragung stoppen. Wie viele Bytes dann noch nachtröpfeln können, 
ist nicht definiert. Man sollte aber auf bis zu 16 eingestellt sein. 
Uralte UARTs hatten den Handshake per Hardware eingebaut. Da kam noch 
maximal ein Byte.

Für die Gegenrichtung gibt es drei Signale. Mit DCD sagt das Modem dem 
PC, dass ein Empfang unmittelbar bevorsteht (Data Carrier Detected). Ob 
und wie der PC reagiert, ist ihm selbst überlassen. Wenn dann 
tatsächlich Daten bereit sind, aktiviert das Modem DSR und der PC 
erlaubt die Übertragung mit DTR. Der PC kann jederzeit die Übertragung 
stoppen, indem er DTR deaktiviert.

Unter Windows gibt es Fälle, bei denen der PC scheinbar nichts empfängt. 
Ursache ist dann oft, dass DSR und DCD nicht aktiv sind.

Bei Wikipedia findet man unter "nullmodem" einen recht guten Artikel.

von (prx) A. K. (prx)


Lesenswert?

Georg G. schrieb:
> Auch, wenn es aus einem Tutorial ist, muss es nicht ganz richtig sein.

Das Tutorial bezieht sich nicht auf Modems, sondern auf Kommunikation 
zwischen PC und Controller. RTS wird heute nicht mehr so verwendet, wie 
es bei Modems üblich war. Sondern so, wie es bei DEC VT100 Terminals an 
VAXen üblich war. CTS hat dabei seine Bedeutung ungefähr behalten, RTS 
aber nicht.

von Ralf (Gast)


Lesenswert?

@Rangi:
Danke für die Erläuterung. So kenne ich das auch.

@Karl Heinz:
> Du musst damit rechnen, dass dein Gegenüber nicht sofort aufhört,
> ...
> Was hier noch ins Spiel kommt, ...
> ...
> Doch, denn am Funktionsprinzip hat sich ja nichts geändert.
Danke für die Erläuterung.

> Welches Henne/Ei Problem?
Wie oben beschrieben: RTS/CTS lokal verbunden, vom Rechner kommen Daten 
und werden direkt wieder zurückgeschickt. Ist die Baudrate so hoch, dass 
der Controller nicht mehr hinterher kommt, deaktiviert er wie gewünscht 
RTS, allerdings sperrt er damit einerseits das Senden des (ebenfalls 
vollen) Sendebuffers, und zweitens bleibt er momentan in der Abfrage, ob 
Platz im Sendebuffer vorhanden ist, hängen. Das war der Grund für die 
Frage, ob ich den Test überhaupt richtig durchführe.

> Es läuft praktisch gesehen auf diese Strategie hinaus
> Ehe ein Byte gesendet wird, wird der Zustand des CTS-Eingangs überprüft.
> Ist der OK, dann darfst du das Byte wegschicken.
> Umgekehrt: empfängst du ein Byte, dann schaust du dir den Füllgrad
> deines Buffers an und entscheidest, ob du deinen eigenen RTS-Ausgang
> zurücknehmen musst. Mit Abarbeitung des Buffers kann der dann irgendwann
> wieder freigegeben werden.
Genauso mache ich das auch. Nur ist eben noch n Deadlock drin, den ich 
gerne lösen würde.

@Georg:
> Bei Wikipedia findet man unter "nullmodem" einen recht guten Artikel.
Danke, ich schau gleich mal rein.

@A.K.:
> Das Tutorial bezieht sich nicht auf Modems, sondern auf Kommunikation
> zwischen PC und Controller.
Aus dem Grund verwende ich die eingangs erwähnte Variante 2 - oder 
versuche es zumindest :)

Ralf

von Rangi J. (rangi)


Lesenswert?

Ich weiss ja nicht mit welcher Hardware du programmierst, aber du musst 
das Empfangen bzw. Senden von Byte aus dem Puffer programmtechnisch 
trennen von der Weiterverarbeitung der Daten.
Am einfachsten geht das im Interrupt. Hier werden Daten aus dem 
Tx-Puffer gesendet wenn da welche sind, bzw empfangen und im 
Empfangsbuffer abgelegt. Bei der gelegenheit kannst du prüfen wieviel 
noch Platz ist und ggf. das RTS ansteuern.
Ausserhalb der ISR, also im Hauptprogramm liesst du dann die Daten aus 
dem Rx-Puffer, gibst damit wieder Platz frei. Jetzt kann du beim 
Auslesen nachschauen ob in der ISR zuvor das RTS gesetzt wurde und ob 
jetzt nach dem auslesen wieder genügend Platz vorhanden ist. Dann gibst 
du RTS wieder frei.
Beim Senden wird im Interrupt nur dann gesendet wenn CTS als frei 
angezeigt wird. Andernfalls wird der Interrupt abgeschaltet. Um jetzt 
mitzubekommen das der andere wieder Daten haben möchte musst du zyklisch 
das CTS pollen oder gleich eine Port-Pin-Interrupt verwenden, der dich 
informiert wann die CTS-Leitung wieder frei anzeigt. Hier kannst du dann 
einfach den Tx-Interrupt wieder anschalten.
Mit DMA wird das ganze etwas komplexer, für die Erklärung isses mir 
einfach zu warm.

von Ralf (Gast)


Lesenswert?

@Rangi:
> Ich weiss ja nicht mit welcher Hardware du programmierst, aber du musst
> das Empfangen bzw. Senden von Byte aus dem Puffer programmtechnisch
> trennen von der Weiterverarbeitung der Daten.
Das habe ich. Empfangsinterrupt -> Empfangsbuffer -> Empfangsroutine 
sowie Senderoutine -> Sendebuffer -> Sendeinterrupt.

Die Empfangs- und Senderoutine arbeiten unabhängig voneinander, sie sind 
in diesem Fall wirklich nur über das Testprogramm verbunden, indem das, 
was aus dem Empfangsbuffer gelesen wird in den Sendebuffer geschrieben 
wird.

> Am einfachsten geht das im Interrupt. Hier werden Daten aus dem
> Tx-Puffer gesendet wenn da welche sind, bzw empfangen und im
> Empfangsbuffer abgelegt. Bei der gelegenheit kannst du prüfen wieviel
> noch Platz ist und ggf. das RTS ansteuern.
Genauso macht das die gegenwärtige Implementierung. Wird im 
Empfangsinterrupt festgestellt, dass nur noch ein paar Bytes frei sind, 
wird RTS deaktiviert.

> Ausserhalb der ISR, also im Hauptprogramm liesst du dann die Daten aus
> dem Rx-Puffer, gibst damit wieder Platz frei. Jetzt kann du beim
> Auslesen nachschauen ob in der ISR zuvor das RTS gesetzt wurde und ob
> jetzt nach dem auslesen wieder genügend Platz vorhanden ist. Dann gibst
> du RTS wieder frei.
Das habe ich momentan ebenfalls so gelöst.

> Beim Senden wird im Interrupt nur dann gesendet wenn CTS als frei
> angezeigt wird. Andernfalls wird der Interrupt abgeschaltet. Um jetzt
> mitzubekommen das der andere wieder Daten haben möchte musst du zyklisch
> das CTS pollen oder gleich eine Port-Pin-Interrupt verwenden, der dich
> informiert wann die CTS-Leitung wieder frei anzeigt. Hier kannst du dann
> einfach den Tx-Interrupt wieder anschalten.
Auch hier exakt meine Implementierung.

> Mit DMA wird das ganze etwas komplexer, für die Erklärung isses mir
> einfach zu warm.
Das glaub ich dir :) Und DMA kann der Controller eh nicht.

Wie gesagt, ich denke, dass das direkte Zurücksenden das Problem ist, 
evtl. müsste ich zwischen den Empfangs- und Sendebuffer noch einen 
Buffer für den Test einbauen.

Ralf

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:

Es wird Zeit, dass du deinen tatsächlichen Code herzeigst.
Aussagen ala "Hab ich genau so implementiert" haben wir jede wochen 
mindestens 3 Stück. UNd dann stellt sich ein ums andere mal raus, dass 
eben irgendetwas doch nicht so implementiert ist, wie es sein soll.


> Wie gesagt, ich denke, dass das direkte Zurücksenden das Problem ist,
> evtl. müsste ich zwischen den Empfangs- und Sendebuffer noch einen
> Buffer für den Test einbauen.

Genau das sollte überhaupt kein Problem sein. Das Problem muss schon 
irgendwo in der Verwaltung der Sende- Empfangsbuffer und der daraus 
abgeleiteten RTS/CTS Verwaltung liegen.

von Karl H. (kbuchegg)


Lesenswert?

Apropos:
Wenn du 2 µC hast, die sich nur gegenseitig im weitesten Sinne ein Echo 
schicken .... ja, dann kannst du dich in einen RTS/CTS Deadlock 
manövrieren.

Aber wenn einer davon ein PC mit einem Terminalprogramm ist, dann sollte 
das nicht vorkommen.

von Rangi J. (rangi)


Lesenswert?

Irgendwie hab ich das eigentliche Problem aus den Augen verloren. Wenn 
du das alles implementiert hast und einen PC anschliesst, dann sendet 
der nicht?
Verwende mal "HTerm". Da wird der Zustand der CTS-Leitung als grüne LED 
dargestellt. Ausserdem kannste RTS per Button einfach schalten.
Da kannste schon ne Menge mit testen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.