hallo miteinander
Ich habe seit neustem ein Projekt übernommen, an dem ich jetzt schon 1
Tag lang herumgebastelt habe, wie es mit der UART aussieht.
Die Grundidee:
-Ein Linux-Server sendet über RS232 steuerbefehle
-MCU gibt Register (32bit) zurück
-Mögliche Steuerbefehle: read, write, reset
=> nach write sollten 32Bit übertragen werden, vom MCU in eine Variable
übernommen und dann weiter im Programm
Die ganze Kommunikation sollte über Hex-werte laufen :
1) 01 => write
2) FFFFFFFF => register
3) 03 => ok (vom mcu)
Bis jetzt läuft mehr oder weniger das senden, aber das empfangen noch
gar nicht.
hier ist der code:
UCSR0B = (1<<RXCIE0)|(1<<RXEN)|(1<<TXEN); //Enable receiver and transmitter
5
UCSR0C = (1<<USBS)|(1<<UCSZ01)|(1<<UCSZ00); //Set frame format: 8data, 2stop bit
6
7
void USART_Transmit(unsigned char data){ //Senden-Funktion mit Variable
8
while (!( UCSR0A & (1<<UDRE0))){} //Wait for empty transmit buffer
9
UDR0 = data; //Put data into buffer, sends the data
10
}
11
ISR(USART0_RX_vect){ //RS232 Receive
12
receive = UDR0; //Take data of buffer
13
}
1. Problem: wie kann ich machen, dass senden/empfangen via hex-werte
funktioniert?
2. Problem: funktioniert das überhaupt? 32Bit über uart oder muss ich 4
mal 8 bit senden?
3. Gibt es etwas, dass ich unbedingt beachten sollte?
Ich wäre froh, wenn jemand meinen Code rasch verifizieren könnte und
eventuell noch tips für das Hex-Problem hat.
Danke im foraus für die Hilfe
P51D
der uartbuffer ist nur 8 bit breit
ebenso sendet jede uart RS232 nur 8bit daten
wenn du 32bit senden oder empfangen willst musst du ein paket schnüren
wie das paket aussieht musst du dir überlegen oder von einer anwendung
übernehmen
da das senden klappt wie du sagst is das schonmal ok
ISR(USART0_RX_vect){ //RS232 Receive
receive = UDR0; //Take data of buffer
}
hier landen die daten zwar in einer variable receive ... aber dann ???
man sollte hier die daten in einen buffer werfen
wenn du von ausgehen kannst maximal 32bit zu erhalten sollte ein
buffer[4] reichen
wenn nun was im buffer steht
also buffer[0] != '/0'
vergleichst du es mit den werten auf die du reagieren willst
is nix dabei ... buffer[0] = '/0'
wenn nun im buffer[0] == 0xFF steht ..
und in den nächsten auch ... dann haset dein FF FF FF FF gefunden
wenn da 0x01 steht ...eben write erkannt
wenn da 0x03 steht war es ein OK
usw ,,,
entsprechend auswertung starten und buffer leeren für neue daten
Der Code zeigt lediglich die Low-Level-Routinen für UART-Init,
UART-Sendeeinzeichen und UART-Empfangsinterruptroutine.
Es fehlt der komplette High-Level Code also die Abwicklung des eigenen
Protokolls.
1. Sorry, das ist mir zu umfangreich.
2. 4 mal 8 bit ist richtig, wenn du den 32-Bit Wert binär
transportierst. Du kannst auch 8 mal 8 Bit senden, wenn du den 32-Bit
Wert in ASCII Form transportierst.
3. Gehe nicht davon aus, dass du eine fehlerfreie Übertragung hast. Mach
dein Protokoll so stabil, dass die Telegramme (write, register, ok) auf
Vollständigkeit und Korrektheit geprüft werden können. Verwende
eindeutige Start und Endezeichen für dein Telegramm, die in der Nutzlast
(register) nicht vorkommen können. Bsp. wenn du register in ASCI
überträgst, sind nur die Zeichen 0123456789ABCDEF möglich und es müssen
8 Stück sein. Diese Zeichen sollten beim Start/Endezeichen nicht
vorkommen. Bei binärem Versand ist die Beschränkung der Zeichen schlecht
möglich. Vermeide bestimmte binäre Steuerzeichen, die bei fehlerhaft
eingestelltem RS232 Kanal die Übertragung stoppen (Software-Handshake
XON/XOFF). Verwende nach Mäglichkeit keine Zeichen mit gesetztem 8. Bit.
erstmals danke für eure Antworten.
das Empfangs-Problem habe ich mittlerweile gelöst, wenn auch nicht
wirklich:
Bis jetzt verwendete ich ein normales Terminal, bei dem ich zwar
umstellen konnte ob ich ASCII oder Hex-Werte empfange, aber beim Senden
wusste ich nicht, was es war. Heute hatte ich Docklight installiert und
siehe da, es funktionierte.
@"gast"
ich hatte das mir in etwa so vorgestellt, dass receive als buffer dient.
Die 32Bit werden dann über schiebebefehle zusammengesetzt. Aber
irgendwie passt mir deine Variante besser. Sie scheint mir etwas
sicherer zu sein, es können keine Daten verlohren gehen, durch verfühtes
überschreiben von receive.
@Stefan B.
ZITAT:
1
Der Code zeigt lediglich die Low-Level-Routinen für UART-Init,
2
UART-Sendeeinzeichen und UART-Empfangsinterruptroutine.
Das ist beabsichtigt so, denn ich habe im main nur noch auf receive
abgefragt, ob es != 0 ist, und dann ein Port gesetzt. Banal, aber
effektif.
ZITAT:
1
Sorry, das ist mir zu umfangreich.
Kein Problem, es läuft ja mitlerweile.
Zu 2) Was macht mehr sinn? ASCII oder Hex Werte? Man muss beachten, dass
das ganze von einem Linux server gestuert wird(Consolen-Aufbau)
ZITAT:
1
...fehlerfreie Übertragung hast...stabil...auf
2
Vollständigkeit und Korrektheit geprüft werden können
Fehlerfrei wird es nicht immer laufen, ist auch meine Ansicht.
stabil?? wie kann ich die Übertraung stabiler machen?
Eine Überprüfung fand ich auch sinfoll, da es recht viele Daten sind.
Das Paritätsbit ist mir allerdings zu ungenau. Da dachte ich mir, dass
ich nach empfangen der Daten vom Rechner gleich alles zurückschicke,
damit der PC die Werte überprüfen kann. Beim senden des
Registerzustandes werde ich wohl 2 mahl den Wert senden.
ZITAT:
1
Vermeide bestimmte binäre Steuerzeichen, die bei fehlerhaft
2
eingestelltem RS232 Kanal die Übertragung stoppen (Software-Handshake
3
XON/XOFF)
Das verstehe ich nicht. könntes du mir das erklähren?
Nochmals danke für eure Hilfe. Ich werde nächste woche mal schauen, ob
ich noch etwas am Projekt machen kann...
MFG
Patrick
Patrick B. schrieb:
> Zu 2) Was macht mehr sinn? ASCII oder Hex Werte? Man muss beachten, dass> das ganze von einem Linux server gestuert wird(Consolen-Aufbau)
Das ist nicht das entscheidende Kriterium.
Entscheidend ist, welche Vorgaben hast du in Bezug
Übertragungsgeschwindigkeit. In dem einen Fall überträgst du einen Wert
in 4 Bytes im anderen Fall in 8 Bytes, also doppelt so lange.
Wenn das kein Problem darstellt, würde ich auch zu ASCII raten.
Mit Binärzahlen, in denen grundsätzklich jedes Byte vorkommen kann, ist
es schwierig ein zuverlässiges Protokoll hinzubekommen. Mit ASCII ist
das leichter, weil du dir selbst die Synchronisierzeichen aussuchen
kannst (=deine Steuerbuchstaben). Das Problem ist vom Schwierigkeitsgard
analog zu: Du hebst den Telefonhörer ab und platzt mitten in ein
Gespräch, mitten in ein Wort hinein. Deine Aufgabe ist es jetzt aus dem
Buchstabensalat den Beginn des nächsten Wortes, des nächsten Satzes
herauszufiltern. Ohne spezielle Zeichen im Datenstrom geht das aber so
gut wie gar nicht.
> Fehlerfrei wird es nicht immer laufen, ist auch meine Ansicht.> stabil?? wie kann ich die Übertraung stabiler machen?
Indem man ein Protokoll entwirft, welches es auch verkraftet, wenn das
Kabel einfach abgezogen und wieder angesteckt wird.
> Da dachte ich mir, dass> ich nach empfangen der Daten vom Rechner gleich alles zurückschicke,> damit der PC die Werte überprüfen kann.
Eine Checksumme mitschicken tuts auch.
> ZITAT:
1
> Vermeide bestimmte binäre Steuerzeichen, die bei fehlerhaft
2
> eingestelltem RS232 Kanal die Übertragung stoppen (Software-Handshake
3
> XON/XOFF)
4
>
> Das verstehe ich nicht. könntes du mir das erklähren?
Im ASCII Code wird für jeden möglichen (7-Bit) Byte Wert ein Zeichen
definiert. Da gibt es zb das Zeichen 'A' oder 'Z' oder '0' oder '%'. Es
gibt aber auch spzielle Zeichen, die die Übertragung selbst steuern
können. Der eine Partner kann zb zum anderen das Zeichen XOFF schicken,
um ihn auzufordern mit dem Senden kurzzeitig aufzuhören.
Google nach Software Handshake.