#c #linux #serial-port
#c #linux #последовательный порт
Вопрос:
Я пытаюсь написать код на c в системе Linux, где я устанавливаю параметры последовательного порта, затем открываю последовательный порт, затем я обнаружил, что, хотя код компилируется и запускается, я не могу читать и записывать с этого последовательного порта (поэтому последовательный порт не был успешно открыт)!
Работающий код (не требуется):
int fd;
char *portname;
portname = "/dev/ttyUSB0";
struct termios tty;
fd = open(portname, O_RDWR | O_NOCTYY | O_SYNC );
memset(amp;tty,0,sizeof tty);
tty.c_cflag amp;= ~PARENB;
tty.c_cflag amp;= ~CSTOP;
tty.c_cflag amp;= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag amp;= ~CRTSCTS;
tcsetattr(fd,TCSANOW,amp;tty);
Код, который не работает (необходим)
int fd;
char *portname;
portname = "/dev/ttyUSB0";
struct termios tty;
memset(amp;tty,0,sizeof tty);
tty.c_cflag amp;= ~PARENB;
tty.c_cflag amp;= ~CSTOP;
tty.c_cflag amp;= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag amp;= ~CRTSCTS;
tcsetattr(fd,TCSANOW,amp;tty);
fd = open(portname, O_RDWR | O_NOCTYY | O_SYNC );
Серьезный вопрос: моя последовательность приложений требует, чтобы я установил параметры последовательного порта, а затем открыл последовательный порт. Есть ли способ сделать это? если да, то как?
Я ценю вашу помощь.
Комментарии:
1. Разрешено ли вашей программе открывать последовательный порт?
2. Поскольку у вас еще нет файлового дескриптора, вы не можете установить какие-либо параметры для подключения. Почему вашему приложению требуется такой дизайн?
3. -alk: да, я просто вставил фрагменты своего кода. -значение имеет значение: да, я добавил себя в группу удаленного доступа. -Лукаш: Моему приложению требуется такой дизайн, потому что программа была перенесена из Windows и должна была поддерживать ту же структуру. Спасибо всем за ваши комментарии. Теперь я понимаю проблему.
Ответ №1:
Обновление: удален код C , замеченный @Alter Mann.
Обновление: удалено обнуление termios
структуры, замеченной @sawdust.
В первом случае вы получаете фактический дескриптор файла fd
и после его использования. Во втором случае вы пытаетесь настроить неинициализированный дескриптор файла fd
(возможно 0
, если он объявлен в глобальной области видимости) и после получения его фактического значения.
Ниже приведен обходной путь, который работает для меня:
#include <fcntl.h>
#include <termios.h>
#include <strings.h>
#include <stdlib.h>
int main (int argc, char * argv [])
{
struct termios tty;
const char * portname = "/dev/ttyUSB0";
const int fd = open (portname, O_RDONLY);
if (-1 == fd) {
// Problem...
return EXIT_FAILURE;
}
if (tcgetattr (fd, amp;tty) < 0) {
// Problem...
return EXIT_FAILURE;
}
cfsetospeed (amp;tty, (speed_t) B9600);
cfsetispeed (amp;tty, (speed_t) B9600);
tty.c_cflag |= B9600;
tty.c_cflag |= (tty.c_cflag amp; ~CSIZE) | CS8;
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag amp;= ~(PARENB | PARODD);
tty.c_cflag |= IGNPAR;
tty.c_cflag amp;= ~(CRTSCTS);
tty.c_cflag amp;= ~(CSTOPB);
tty.c_iflag |= IGNBRK;
tty.c_iflag amp;= ~(IXON | IXOFF | IXANY);
tty.c_lflag = 0;
tty.c_oflag = 0;
tcflush (fd, TCIFLUSH);
if (tcsetattr (fd, TCSANOW, amp;tty) ) {
// Problem...
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Комментарии:
1. Обнуление структуры termios является плохой практикой кодирования. Предпочтительным / правильным методом является использование системного вызова tcgetattr(). См. раздел Правильная настройка режимов терминала
2. @sawdust, спасибо за полезный совет! Я исправил свой ответ.