Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : Serielle Schnittstelle - Non-standard Baudraten ?



comer352l
18-03-2007, 11:47
Hallo zusammen,

ich möchte (muss) die serielle Schnittstelle mit einer Baudrate von 10400 betreiben, also keinem Standard-Wert. Bis jetzt habe ich trotz intensiver Suche nichts hierzu finden können...
Den einzigen Ansatzpunkt, den ich im Moment habe, wäre die Verwendung eines externen Taktgebers ?
In der Termios-Struktur (termios.h) lassen sich ja für c_cflag die Konstanten EXTA und EXTB ("external clock rate") verwenden... Damit wäre ich mit meinem Latein dann aber auch schon am Ende.

Irgendwelche Ideen dazu ? Wäre echt dankbar...

peschmae
18-03-2007, 12:10
So ein Problem in die Richtung hatte ich auch mal - nur in meinem Falle waren die Rate genug nahe bei einer Standardrate so dass ich das einfach vernachlässigen konnte. Scheint mir bei dir etwas riskant zu sein.

Eventuell hilft dir das (http://www.linuxquestions.org/questions/showthread.php?t=6532) weiter? - hab nur mal schnell bei Google vorbeigeguckt.

Oder das geht mit den cfsetispeed/cfsetospeed - Funktionen. Da kannst du direkt die Baudrate angeben (wobei das natürlich nicht heisst dass er non-standard raten auch frisst)

MfG Peschmä

comer352l
16-07-2007, 13:02
Hallo zusammen,

es ist zwar nun schon einige Monate her, aber ich könnte mir vorstellen, dass das Thema auch für Andere interessant ist...
Um Non-Standard-Baudraten zu relisieren, muss man zusätzlich auch noch direkt auf den Treiber zugreifen, wodurch das Ganze leider nicht mehr 100% POSIX-konform ist. Außerdem funktioniert das Folgende nur, wenn die serielle Schnittstelle des Rechners mit dem seriellen Standard-Treibern betrieben wird...
Unter http://www.easysw.com/~mike/serial/serial.html findet man eine exzellente Zusammenfassung zur Programmierung der seriellen Schnittstelle unter Unix/POSIX-Systemen, weshalb ich mich hier lediglich auf das Thema Non-Standard-Baudraten beschränke.

Zunächst MUSS die Baudrate in der Termios-Struktur auf 38400 gesetzt werden, da sonst alle weiteren Maßnahmen ignoriert werden.
Als nächstes wird das ASYNC_SPD_CUST Flag im Treiber gesetzt. Die Baudrate kann nun mit Hilfe von "custom-divisor" eingestellt werden, dessen Werte zwischen 0 unf 65535 liegen müssen. Als Berechnungsbasis dient der Wert des Feldes "baudbase", so dass sich die Baudraten ergeben als

baudrate = new_serdrvinfo.baudbase / new_serdrvinfo.divisor;

Der Wert von Baudbase beträgt in der Regel (UART 16550A) 115200.
Eine Baudrate von 10400 (wie ich Sie benötig habe) entspricht also einem Custom-Divisor von 115200/10400=11,077 ~= 11. Die Nächstmögliche Baudrate ist also 115200/11=10472,72..., was in meinem Fall ausreichend ist (0,7% Abweichung).

Das Ganze schaut dann so aus:


#include <termios.h>
#include <linux/serial.h> // serial standard driver
...
struct termios newtio; // termios struct
struct serial_struct new_serdrvinfo; // serial driver struct
...
// Set baudrate to 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
tcsetattr(fd, TCSANOW, &newtio );
...
// Change serial driver settings:
ioctl(fd, TIOCGSERIAL, &new_serdrvinfo); // read driver settings
new_serdrvinfo.flags |= ASYNC_SPD_CUST; // activate custom baudrate
... // Benötigten Custom-Divisor ermitteln
new_serdrvinfo.custom_divisor = customdivisor; // set custom divisor
ioctl(fd, TIOCSSERIAL, &new_serdrvinfo); // write new driver settings
...


Ich hoffe, dass sich der Eine oder Andere so eine Menge Sucherei ersparen kann...

Gruß,

Frank