Escribí esto hace mucho tiempo ( desde los años 1985-1992, con solo algunos ajustes desde entonces ), y solo copie y pegue los bits necesarios en cada proyecto.
Debe llamar cfmakerawa un ttyobtenido de tcgetattr. No puede struct termiosponer a cero a , configurarlo y luego configurarlo ttycon tcsetattr. Si utiliza el método de cero, experimentará fallas intermitentes inexplicables, especialmente en los BSD y OS X. Las "fallas intermitentes inexplicables" incluyen el bloqueo 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
Los valores de la velocidad son B115200, B230400, B9600, B19200, B38400, B57600, B1200, B2400, B4800, etc. Los valores de paridad están 0(lo que significa sin paridad), PARENB|PARODD(habilitar la paridad y el uso impar), PARENB(habilitar paridad y usar incluso), PARENB|PARODD|CMSPAR(paridad marca), y PARENB|CMSPAR( paridad espacial).
"Bloquear" establece si un read()en el puerto espera a que llegue el número especificado de caracteres. Si no se configura el bloqueo , se read()devuelve una cantidad de caracteres disponibles sin esperar más, hasta el límite del búfer.
Apéndice:
CMSPARsolo es necesario para elegir la paridad de marca y espacio, lo cual es poco común. Para la mayoría de las aplicaciones, se puede omitir. Mi archivo de encabezado /usr/include/bits/termios.hpermite la definición de CMSPARsolo si el símbolo del preprocesador __USE_MISCestá definido. Esa definición ocurre (en features.h) con
#if defined _BSD_SOURCE || defined _SVID_SOURCE
#define __USE_MISC 1
#endif
Los comentarios introductorios de <features.h>dice:
/* 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.
...
*/