Hallo Leute,
ich habe hier ein eigenartiges Problem. Also ich habe ein Gerät, was mit
mir per RS232 kommuniziert. Das Betriebssystem des Hosts ist Linux, die
Gegenseite ist ein Mikrocontroller. Das funktioniert auch alles soweit.
Aber ich habe folgendes Problem.
Ich sende ein 0xA8 und müsste ein Echo empfangen. Ich empfange aber nur
0x28. Mit anderen Worten: Es fehlt das erste Bit.
Folgender Code ist verantwortlich:
1
intdevicehandle;// Hiermit wird später auf das geöffnete Device zugegriffen
2
structtermiosoptions;// hält die Kommunikations-Konfig-Daten
3
4
unsignedcharbuffer[1];
5
6
//RS232-Kanal öffnen (lesen und Schreiben erlaubt)
options.c_cflag&=~PARODD;/* Turn odd off => even */
25
options.c_cflag&=~CSTOPB;/* Set 1 Stopbit */
26
options.c_cflag&=~CSIZE;/* Mask the character size bits */
27
options.c_cflag|=CS8;/* Select 8 data bits */
28
29
//Disable hardware flowcontrol
30
options.c_cflag&=~CRTSCTS;
31
32
//Raw Data Ausgabe
33
options.c_oflag&=~OPOST;
34
options.c_oflag|=ONLCR;
35
36
//Raw data Einlesen mit Parity-check
37
options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
38
options.c_iflag|=(INPCK|ISTRIP);
39
40
//Set timeout to 1s
41
options.c_cc[VMIN]=0;
42
options.c_cc[VTIME]=10;
43
44
//Software flowcontrol ausschalten
45
options.c_iflag&=~(IXON|IXOFF|IXANY);
46
47
//Neue Einstellungen sofort auf Port übertagen
48
tcsetattr(devicehandle,TCSAFLUSH,&options);
49
50
//Puffer leeren
51
tcflush(devicehandle,TCIFLUSH);
52
53
//Hier geht das senden und empfangen los.
54
55
buffer[0]=0xA8;
56
57
printf("Sende %02X\n",buffer[0]);//reelle Ausgabe ist hier: A8
58
59
write(devicehandle,buffer,1);
60
61
tcdrain(devicehandle);//warten, bis alles gesendet.
62
63
read(devicehandle,buffer,1);
64
65
printf("Empfange %02X\n",buffer[0]);//Ausgabe sollte sein A8, ist aber 28
66
67
close(devicehandle);
Sieht für mich irgendwie normal aus. Das Oszi-Bild ist auf Sende- und
Empfangsseite identisch. Ich gehe also davon aus, dass er tatsächlich
ein richtiges Echo schickt.
Ich versteh die Welt nicht mehr.
Günther
Steck vielleicht mal einen Loopback-Stecker (Selbstbau ist nicht schwer)
an die serielle Schnittstelle vom Linux-Rechner. Dann siehst du, ob es
am µC liegt oder am Linux.
> Ich sende ein 0xA8 und müsste ein Echo empfangen. Ich empfange aber nur> 0x28. Mit anderen Worten: Es fehlt das erste Bit.
Nein, es fehlt das letzte Bit. Das niederwertigste Bit wird zuerst
übertragen.
Könnte ein Problem mit zu großen Baudratenabweichungen sein: die ersten
Bits werden noch richtig übertragen, aber beim letzten Bit sind beide
Seiten zu weit auseinandergelaufen.
So auf den ersten Blick arbeitest du im AVR mit Parity. Parity verwendet
aber das MSB, da dieses Konzept aus dem 7-Bit ASCII Code stammt bei dem
eben jenes Bit unbenutzt ist. Wenn es der USART richtig macht muss er
das höchstwertige Bit mit dem Paritywert überschreiben und der Empfänger
"sollte" es filtern. Für binäre Übertragungen eignet sich nur No-Parity.
(idR. 8N1)
Naja, der Host arbeitet mit Parity, aber auch mit CS8. Das ist ein
9-Bit-Frame-Format, bei dem das Partitätsbit zusätzlich zu den
8 Datenbits untergebracht werden kann.
Den zugehörigen AVR-Code hat er ja nicht gepostet. Prinzipiell
können die USARTs der neueren AVRs auch das 9-bit-Format, aber das
9. Bit ist ein wenig umständlich zu be-/verarbeiten.
Das hüpfende Komma ist das "kann". Das muss man aber warscheinlich
"manuell" das Bit7 ins das Bit8 bringen und der Empfänger wieder zurück.
Zumindest ich, falls ich Chipdesigner wäre, käme nie auf die Idee
jemand würde so etwas versuchen. Kein Standard = Kann gehen oder nicht.
Hier gehts offensichtlich nicht :-/
9-bit RS-232 ist ein Standard, auch wenn in der PeeCee-Welt eher
unbekannt. Von 5-bit (klassischer Fernschreiber) über 7, 8 und 9
bit ist da alles machbar und irgendwo benutzt worden.
Guten Morgen und Danke für eure Hilfe,
@Stefan: Du meinst, einfach RxD mit TxD verbinden? Das ist ne Idee.
@Jörg: Baudratenabweichung klingt übel. Also beide Geräte verwenden die
gleiche Baudrate und in Hinrichtung funktioniert das ja auch. Das Echo
wird nur gesendet, wenn 0xA8 wirklich ankommt. Hab schon probehalber
0x28 gesendet, da bleibt er stille.
@Werner: Eigentlich ist die Gegenstelle kein AVR, sondern ein
RFID-Reader von Feig. Ich werde aber trotzdem mal versuchen, die Parity
auszuschalten. Da gibt es ein Register für.
> Das hüpfende Komma ist das "kann". Das muss man aber warscheinlich> "manuell" das Bit7 ins das Bit8 bringen und der Empfänger wieder zurück.> Zumindest ich, falls ich Chipdesigner wäre, käme nie auf die Idee> jemand würde so etwas versuchen. Kein Standard = Kann gehen oder nicht.> Hier gehts offensichtlich nicht :-/
Das verstehe ich nicht.
@Jörg: Ob 9-bit RS232 eher unbekannt ist, ist mir im Prinzip egal. Die
Frage ist doch, kann Linux damit umgehen?
Hm, also scheinbar dubios.
Danke,
Günther
9-Bit-RS232 wird von den in PCs verbauten seriellen Schnittstellen nicht
unterstützt. Mit viel Aufwand lässt sich das in Software nachbilden (vor
dem Senden eines Bytes die Parität berechnen, Schnittstellenbetriebsart
auf MARK bzw. SPACE umschalten, Byte senden), aber das ist bei üblicher
Betriebssystemarchitektur kaum mit benutzbaren Datenraten hinzubekommen.
Außerdem muss für derartige Aktionen zwingend der Sende-FIFO der
Schnittstelle deaktiviert werden, da es keinen FIFO für die für die zu
sendenden Zeichen zu verwendende Betriebsart gibt.
Vollkommen ausgeschlossen ist 9 Bit mit Parität.
Hallo,
bin jetzt echt zu faul zum Nachsuchen...
8Bit mit Parity ist kein 9Bit-Format sondern 8Bit mit Parity.
Parity wird vom UART in Hardware erzeugt und ausgewertet. Es wird bei
Fehlern eben ParityError gesetzt. So machen es zumindest alle UARTs, an
die ich mich noch erinnere und offenbar auch z.B. der im Mega8.
NoPartity heißt normalerweise, daß Parity immer als H auf der RS232
gesendet wird, für den Empfänger heißt es, daß Parity nicht ausgewertet
wird. Schlimmstenfalls wird es also als das ohnehin erwartete Stopbit
ausgewertet.
Das kann eigentlich nur in der Version Sender mit No Parity - Empfänger
No Parity ein Problem geben, wenn der Sender dann wirklich keine
Parity-Bitzeit sendet, der Empfänger aber eine prüft und verwirft. Dann
würde u.U. sofort das nächste Startbit kommen und verloren gehen können.
Hatte ich aber eigentlich nie, Sender mit 8N1, 8E1, 8O1 und Empfänger
immer mit 8N1 ging immer, gab dann eben nur keine Parity-Auswertung.
Gruß aus Berlin
Michael
Günther Schmidt wrote:
> @Jörg: Baudratenabweichung klingt übel. Also beide Geräte verwenden die> gleiche Baudrate ...
Meine Befürchtung war, dass der Prozessortakt des Empfängers nicht
stimmen würde und damit die Baudrate.
Aber:
> Eigentlich ist die Gegenstelle kein AVR, sondern ein> RFID-Reader von Feig.
Das hattest du uns ja vorenthalten. Damit war ich erst einmal davon
ausgegangen, dass die Gegenseite ein von dir gezimmerter Controller
ist, der dann dieses Problem haben könnte.
> @Jörg: Ob 9-bit RS232 eher unbekannt ist, ist mir im Prinzip egal. Die> Frage ist doch, kann Linux damit umgehen?
Ich kenne mich zwar mit Linux nicht so gut aus (hier werkelt überall
ein FreeBSD), gehe aber stark davon aus, dass es das kann (im Sinne,
dass das 9. Bit ein Paritätsbit ist, wie von Michael beschrieben).
Kann es sein, dass dein Reader 7 bits + gerade Parität haben will,
d. h. dass 0xa8 bereits das Paritätsbit beinhaltet? Wäre aber nicht
ganz klar, warum er dann 7 bits ohne Parität antworten soll.
Hallo Rufus,
Danke für die Info. Also ich habe jetzt mal RxD mit TxD verbunden und
0xAA (alternierend für den Oszi) gesendet.
Es wird auch mit 8 bit ohne Parität um's Verrecken nicht 0xAA
zurückgelesen, sondern nur 0x2A.
Ich habe mal ein Oszibild angehängt. Das sollten 8 bit (0xAA) mit
gerader Parität und einem Stoppbit sein. Irgendwie haut das aber nicht
hin, es müssten doch eigentlich 11 bit sein, ich sehe aber nur 10.
Gemessen habe ich das an meiner Rx-Tx-Brücke.
Das versteh ich aber nicht. Der Reader antwortet mir nur, wenn er
gültige Datenpakete bekommt. Wenn schon das senden nicht richtig klappt,
warum antwortet mir dieser Idiot dann? Oder interpretiere ich das Bild
einfach falsch. Ist das Stoppbit high oder low? Dann würde es nämlich
wieder passen.
Günther
> Kann es sein, dass dein Reader 7 bits + gerade Parität haben will,> d. h. dass 0xa8 bereits das Paritätsbit beinhaltet? Wäre aber nicht> ganz klar, warum er dann 7 bits ohne Parität antworten soll.
Im Datenblatt steht 8E1. Und wie gesagt, der antwortet nur, wenn er mich
versteht (ein ziemlich eigenartiges Protokoll, wie ich finde). Wenn ich
also mit 8E1 senden würde und er würde 7E1 erwarten, würde er mir doch
nicht antworten, oder?
Btw. diese 0xA8 ist nur ein Byte eines ganzen Datenpaketes, jedoch in
dem Fall das einzige, was MSB=1 hat. Das ganze Datenpaket muss also
stimmen.
Günther
Hallo
Ist zwar kein Lösungsvorschlag, aber ich hab ein ähnliches Problem.
Beim Senden aus einem Java-Programm werden alle Bytes die im bereich von
0x80 bis 0xFF sind zum Datenmüll. Liegt also auch am MSB. Habe auch
schon verschiedene Baudraten versucht, ohne erfolg.
Bei mir leuft Ubuntu mir 2.6.15-27-686 Kernel.
mfg
Max
Hallo Max,
Hm, bei mir läuft auch ein 2.6.15-Kernel. Steht das im Zusammenhang?
Kann ich mir bald nicht vorstellen.
Auf jeden Fall habe ich jetzt rausbekommen, dass das Stopbit high ist,
also stimmt mein Oszi-Bild schonmal.
Irgendwie komme ich aber trotzdem nicht weiter.
Günther
> NoPartity heißt normalerweise, daß Parity immer als H auf der RS232> gesendet wird,
Nein. Das tut es nicht. Es wird überhaupt kein Bit übertragen. Was Du
meinst, ist MARK bzw. SPACE Parity, das ist etwas anderes als "no
parity".
Ein Byte, das 8n1 übertragen wird, benötigt exakt 10 Bitzeiten
(Startbit, 8 Datenbits, ein Stopbit). Erst ein Byte, das 8e1 oder 8o1
oder eben 8m1 bzw. 8s1 übertragen wird, benötigt 11 Bits, wobei 8m1 sich
von 8n2 inhaltlich nicht unterscheidet.
> für den Empfänger heißt es, daß Parity nicht ausgewertet> wird. Schlimmstenfalls wird es also als das ohnehin erwartete Stopbit> ausgewertet.
... wenn denn die Polarität stimmt, anderenfalls gibt es einen Framing
Error.
Das Bild entspricht einer 8E1 Einstellung und enthält als Daten 0xAA.
MARK = keine Übertragung
0 Startbit (SPACE)
1 LSB
0
1
0
1
0
1 MSB
0 korrekt bei Even Parity
1 Stopbit
MARK = keine Übertragung
http://www.lammertbies.nl/comm/info/de_RS-232_specs.html
Das Problem kommt vermutlich von der einstellung der TTY Einleselayer
her, also wäre dieser Code zu kontrollieren:
//Raw data Einlesen mit Parity-check
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag |= (INPCK | ISTRIP);
Und dann findet man ;-)
istrip
lösche höchstes (8.) Bit der Eingabezeichen
http://man.cx/stty(1)/de
> istrip> lösche höchstes (8.) Bit der Eingabezeichen
Hm, hab ich jetzt mal rausgenommen, das Verhalten über meiner Brücke
bleibt das gleiche.
Gibt es irgendein Kommandozeilenterminal für busybox? Dann könnte ich
das mal so versuchen, ohne mein Programm.
Günther
Ahäm.
Hüstel.
Schluck!
You made my day.
Wo bitte kann ich die Flasche Wein hinschicken, die du dir jetzt
verdient hast? Trinkst du eher rot oder weiß?
Was bitte nutzt so eine Funktion? Und dann noch als default.
Laut http://www.easysw.com/~mike/serial/serial.html#2_5 ist dieses
ISTRIP dafür da, die Parity-bits zu löschen und nicht das 8. Datenbit.
Was also soll diese Funktion?
Wie auch immer. Danke. Danke. Danke.
Jetzt kann ich endlich rangehen, das hier in Gang zu bringen. Mal sehen,
wann die nächste kleine Hürde sich als Barrikade vor mir auftürmt.
So long,
Günther