RS-485-Modul überträgt LF und CR nicht

Ich arbeite an einem Projekt, bei dem zwei ATMEGA328p-MCUs über große Entfernungen kommunizieren (zwischen zwei Stockwerken eines Gebäudes). Einer ist Herr und der andere ist Sklave. Der Master initiiert die Kommunikation immer, indem er kundenspezifische AT-Befehle sendet, die am Ende einen Wagenrücklauf '\r' und einen Zeilenvorschub '\n' als Abschlusszeichen haben.
Ich verwende UART (9600 bps mit gerader Parität). Folgendes ist mir aufgefallen: Bei Verwendung von direktem UART funktioniert alles wie erwartet. Aber als ich den Kommunikationspfad durch ein sehr langes Kabel (ca. 5-10 m) ersetzte, begann der UART, Probleme zu verursachen.
Also musste ich aus offensichtlichen Gründen RS-485-Module verwenden.

Das Problem, das ich sehe, ist, dass der gesamte AT-Befehl über den RS-485-Pfad übertragen wird, aber die beiden ASCII-Codes „\r“ und „\n“ überhaupt nicht empfangen werden. Ich habe mit einem FTDI-Klon überprüft, dass der Eingang zum senderseitigen RS-485-Modul wie erwartet CR und LF hat, aber am Empfangsende (nach der RS485-zu-UART-Konvertierung) wird der gesamte Befehl mit Ausnahme von CR und LF empfangen .

Bitte schlagen Sie mir vor, was zu tun ist, da mein gesamter Softwarecode von der Erkennung von CR und LF als Protokoll abhängt. Ich habe viele Blogs/QAs durchlaufen, konnte mein Problem jedoch nicht lösen. Es scheint, als würde das RS-485-Modul CR und LF nicht senden.

Dies sind die beiden UART-Funktionen, die auf der untersten Ebene arbeiten. Ich habe überprüft, dass mein Code immer 1 als trm-Argument übergibt

void UART_TxSTRING (char string[], int trm)     //This string function does not sends the NULL character '\0'
{   
    int i = 0;
    while (string[i] != '\0')       //Detect end of string
    {
        UART_TxByte(string[i]);
        i++;
    }
    if (trm == 1)                   //if trm=1, terminators will be sent with string
    {
        UART_TxByte('\r');          //Terminator
        UART_TxByte('\n');          //Terminator
    }
}

void UART_TxByte(char tx_data)
{   
    UCSR0B  &= ~RXIE;               //Disable Rx interrupts while sending data
    while (!(UCSR0A & TXC_FLAG));   //Check flag before transmitting
    UDR0 = (tx_data & 0xFF);        //Send the ASCII code
    UCSR0B  |= RXIE;                //Enable Rx interrupts again after transmission
}

Update: Ich habe den Code geändert, um das CR durch @ zu ersetzen und LF durch $ zu ersetzen. Immer noch gehen nur die Abschlusszeichen verloren, der Rest des Befehls (lang oder kurz) wird normal übertragen. Ich habe das Gefühl, dass es ein Problem im Zusammenhang mit dem Timing gibt, da die if (trm == 1) -Anweisung dazu führt, dass der RS-485-IC nachfolgende Zeichen verwirft.

Schauen Sie sich die RS485-Leitungen mit einem Zielfernrohr an - sehen Sie dort das CR/LF? Was genau sind diese Module - haben sie irgendeine Art von "Intelligenz" oder sind sie einfache Leitungstreiber?
Funktioniert das Senden eines CR oder LF mit UART_TxByte()?
@brhans Ich verwende diese Module images-na.ssl-images-amazon.com/images/I/…
@Rodo Ich habe diese Sequenz wiederholt übertragen UART_TxByte ('S'); UART_TxByte('\r'); UART_TxByte('M'); UART_TxByte('\n'); Verzögerungen (100); Und am seriellen Terminal beobachtet, dass nur S und CR empfangen werden, M und LF werden nicht empfangen.
Ich kann den USB-TTL-Konverter nur zum Verfolgen von Paketen verwenden, da ich keinen Zugriff auf irgendeinen Bereich habe. Es gibt etwas mit diesem Modul, das ich nicht herausfinden kann.
Ihr RS485-Modul scheint eine einfache Level-Shifter-Schnittstelle zu sein - es wird nicht die Intelligenz haben, CR/LF fallen zu lassen. Ich könnte vorschlagen, dass Ihre Empfangsroutine CR / LF fallen lässt, oder möglicherweise ein Timing-Problem - die Empfangstaktfrequenz ist zu weit von der Sendetaktfrequenz entfernt.
@Peter Bennett Auf der niedrigsten Ebene sende ich nur LF, aber es wird nichts empfangen. Abgesehen davon werden die restlichen Zeichen korrekt empfangen, aber CR verursacht immer noch das Löschen anderer Zeichen.
Sie brauchen wirklich eine Möglichkeit, die Signale (Oszilloskop) zu betrachten, um zu verfolgen, wo das CR oder LF verloren geht.
Nach dem aktuellen Stand habe ich festgestellt, dass LF verloren geht, und damit auch das Zeichen direkt neben LF. Obwohl CR nicht verloren geht, verhält es sich wie ein LF auf dem Terminal (es erzeugt eine neue Zeile)
Wenn Sie 'A' , '\r', '\n', 'B' senden, erhalten Sie nur A?
Txc wird vor dem Senden des Zeichens getestet. Sie müssen sicherstellen, dass das letzte Zeichen vollständig gesendet wird, bevor Sie die Sendefreigabe am 485-Transceiver deaktivieren. Ist TXC_FLAG der offizielle Bitname oder ist das etwas, das Sie erstellt haben?
Welche Zeichenfolge ich auch immer sende, die letzten beiden Zeichen gehen immer verloren. Wenn ich "DC\r\n" sende, gehen CR und LF verloren; Wenn ich "DC+T1MEAS?$%" sende, gehen nur $ und % verloren. Obwohl der Grund noch nicht bekannt ist, warum dies geschieht. Aber ich habe eine Problemumgehung für dieses Problem gefunden. Welche Zeichenfolge ich auch immer sende, ich habe am Ende der Zeichenfolge zwei zusätzliche nutzlose Leerzeichen angehängt, und die richtige Zeichenfolge wird empfangen (da die nutzlosen Leerzeichen weggelassen werden). Ich sende "DC+T1MEAS?\r\n__" und habe erfolgreich "DC+T1MEAS?\r\n" erhalten.
Es macht keinen Sinn. Und Ihre "Umgehung" funktioniert, wenn Sie kontinuierlich zwei Zeichenfolgen senden, indem Sie diese Funktion zweimal aufrufen? Und Sie haben uns nicht gesagt, wie Sie jedes empfangene Byte bestätigen. Wird ein Oszilloskop oder ein anderes C-Programm/Terminal verwendet? Vielleicht hat es etwas damit zu tun.
"Rx-Interrupts beim Senden von Daten deaktivieren" Eeh? Wenn Sie aus irgendeinem seltsamen Grund erwarten, Daten zu empfangen, während Sie sie übertragen, dann wird das Deaktivieren des Interrupts Sie nicht retten. Sie werden eine Kollision auf dem Bus haben und alle Daten werden beschädigt. Es sei denn, Sie verwenden RS-422-Vollduplex, aber das scheint nicht der Fall zu sein.
Auch mit einem "FTDI-Klon"? Verwenden Sie einfache, dumme RS-485-Transceiver mit Abschlusswiderständen.

Antworten (1)

Nicht 100% sicher, dass dies Ihr Problem lösen wird, aber etwas zu überprüfen:

Laut Atmel-Datenblatt sollten Sie unmittelbar vor dem Übertragen von Bytes auf das UDREn-Bit warten, was bedeutet, dass das UDRn-Register leer ist und ein neues Byte akzeptieren kann.

UDREn unterscheidet sich vom TXCn-Bit, das Sie anscheinend verwenden (aber es ist nicht klar, wie Sie diese Maske definiert haben).

Wie auch immer, TXCn ist für nach , nicht vor . Weitere Unterschiede: UDREn tritt auf, bevor das Byte vollständig übertragen wurde, und TXCn wird möglicherweise nicht automatisch auf die gleiche Weise gelöscht wie UDREn.

Verwenden Sie UDREn, wenn Sie eine Reihe von Daten zuführen, die in einem Block übertragen werden sollen, verwenden Sie TXCn, wenn Sie auf das Ende des letzten Bytes warten, falls dies wichtig ist.

Mir ist aufgefallen, dass mit dem Code nichts falsch ist. Das RS-485-Modul lässt die letzten beiden ASCII-Codes jeder Zeichenfolge weg, die ich sende. Also habe ich den Code geändert, um zwei zusätzliche Leerzeichen nach CR und LF zu senden. Das hat funktioniert.
Achten Sie besonders auf die Richtungslinie. Wenn es während des Sendens geändert wird, wird der Sender/Empfänger die Bytes "weglassen".