Я написал это очень давно ( с 1985 по 1992 год, с тех пор было внесено всего несколько изменений ) и просто копирую и вставляю нужные биты в каждый проект.
Вы должны позвонить cfmakeraw
по tty
полученному от tcgetattr
. Вы не можете обнулить a struct termios
, настроить его, а затем установить с tty
помощью tcsetattr
. Если вы используете метод обнуления, то вы будете испытывать необъяснимые периодические сбои, особенно в BSD и OS X. «Необъяснимые периодические сбои» включают зависание 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;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 5;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~(PARENB | PARODD);
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;
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_blocking (fd, 0);
write (fd, "hello!\n", 7);
usleep ((7 + 25) * 100);
char buf [100];
int n = read (fd, buf, sizeof buf);
Значения скорости являются B115200
, B230400
, B9600
, B19200
, B38400
, B57600
, B1200
, B2400
, B4800
и т.д. Значение четности не 0
(то есть без проверки четности), PARENB|PARODD
(включить четность и использовать нечетный), PARENB
(включить четность и использовать даже), PARENB|PARODD|CMSPAR
(четность знака), и PARENB|CMSPAR
( пространственный паритет).
«Blocking» устанавливает, read()
ожидает ли порт на порту прибытия указанного количества символов. Установка отсутствия блокировки означает, что read()
возвращается любое количество доступных символов, не дожидаясь большего, до предела буфера.
Дополнение:
CMSPAR
нужен только для выбора четности меток и пробелов, что редко. Для большинства приложений его можно не указывать. Мой заголовочный файл /usr/include/bits/termios.h
позволяет определять CMSPAR
только в том случае, если определен символ препроцессора __USE_MISC
. Это определение встречается (в features.h
) с
#if defined _BSD_SOURCE || defined _SVID_SOURCE
#define __USE_MISC 1
#endif
Во вступительных комментариях <features.h>
говорится: