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.
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.
brhans
Rodo
Manisch Verma
Manisch Verma
Manisch Verma
Peter Bennett
Manisch Verma
Rodo
Manisch Verma
Mitu Raj
Kartmann
Manisch Verma
Mitu Raj
Lundin
Lundin