Ich habe das vor langer Zeit geschrieben ( von 1985 bis 1992, mit nur wenigen Änderungen seitdem ) und einfach die benötigten Teile kopiert und in jedes Projekt eingefügt.
Sie müssen cfmakeraw
einen von tty
erhalten tcgetattr
. Sie können nicht Null-out ein struct termios
, konfigurieren Sie ihn, und legen Sie das tty
mit tcsetattr
. Wenn Sie die Zero-Out-Methode verwenden, treten unerklärliche intermittierende Fehler auf, insbesondere bei BSDs und OS X. "Unerklärte intermittierende Fehler" umfassen das Einhängen read(3)
.
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
int
set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
if (tcgetattr (fd, &tty) != 0)
{
error_message ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
error_message ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void
set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
error_message ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
error_message ("error %d setting term attributes", errno);
}
...
char *portname = "/dev/ttyUSB1"
...
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
error_message ("error %d opening %s: %s", errno, portname, strerror (errno));
return;
}
set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0); // set no blocking
write (fd, "hello!\n", 7); // send 7 character greeting
usleep ((7 + 25) * 100); // sleep enough to transmit the 7 plus
// receive 25: approx 100 uS per char transmit
char buf [100];
int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
Die Werte für die Geschwindigkeit sind B115200
, B230400
, B9600
, B19200
, B38400
, B57600
, B1200
, B2400
, B4800
, usw. Die Werte für die Parität sind 0
(dh keine Parität), PARENB|PARODD
(Parität ermöglichen und ungerade verwenden), PARENB
(enable Parität und verwendet sogar), PARENB|PARODD|CMSPAR
(mark Parität) und PARENB|CMSPAR
( Raumparität).
"Blockieren" legt fest, ob ein read()
am Port auf das Eintreffen der angegebenen Anzahl von Zeichen wartet. Wenn Sie keine Blockierung festlegen, wird read()
zurückgegeben, wie viele Zeichen verfügbar sind, ohne auf weitere zu warten, bis zur Puffergrenze.
Nachtrag:
CMSPAR
wird nur für die Auswahl der Markierungs- und Leerzeichenparität benötigt, was ungewöhnlich ist. Für die meisten Anwendungen kann es weggelassen werden. Meine Header-Datei /usr/include/bits/termios.h
kann CMSPAR
nur definiert werden, wenn das Präprozessorsymbol __USE_MISC
definiert ist. Diese Definition erfolgt (in features.h
) mit
#if defined _BSD_SOURCE || defined _SVID_SOURCE
#define __USE_MISC 1
#endif
In den einleitenden Kommentaren von <features.h>
heißt es:
/* These are defined by the user (or the compiler)
to specify the desired environment:
...
_BSD_SOURCE ISO C, POSIX, and 4.3BSD things.
_SVID_SOURCE ISO C, POSIX, and SVID things.
...
*/