Я написал это очень давно ( с 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>говорится: