Уважаемые участники форума!
Помогите, пожалуйста, с последовательным портом. Никак не получается решить одну проблему.
Для освоения программирования COM-порта решил воспользоваться Serial Programming Guide for POSIX Operating Systems, достаточно классическим трудом. Решил попробовать открыть порт с помощью open() - проблем нет. Записал в порт с помощью write() - тоже все получилось. Закрытие порта посредством close() - тоже проблем не вызвало. А вот с чтением с помощью read() не получается.
Решил прочитать заведомо пустой порт (никакого устройства к нему не подключено):
char buffer[4];
int number_O_Rd_Bytes;
number_O_Rd_Bytes = read(fd_COM_1, buffer, 4);
if(number_O_Rd_Bytes == -1)
{
perror("Unable read COM_1\n");
}
else
fcntl(fd_COM_1, F_SETFL, 0)
В руководстве сказано, что если использовать одну только функцию read() в данной ситуации, то в том случае, если во входных буферах последовательного порта ничего нет (а это как раз мой случай), то программа остановиться и будет ждать появления чего-либо в этих буферах. Если же использовать fcntl(), то функция read() должна в случае пустого порта возвратить 0.
В общем, не получается у меня. На строчке с read() программа замирает - и все.
Поясните, пожалуйста, правильно ли я использую функцию fcntl()? Нужна ли она здесь вообще? Может, я вообще неправильно читаю последовательный порт?
Заранее благодарен за ваши ответы.
COM-порт (Помогите запрограммировать)
Модератор: Модераторы разделов
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
-
elide
- Бывший модератор
- Сообщения: 2421
- Статус: Übermensch
- ОС: лялих
Re: COM-порт
мне кажется, что лучше забыть про fcntl и юзать select.
во всяком случае, я не понял, как обнудение флагов может привести к использованию неблокирующего В/В...
во всяком случае, я не понял, как обнудение флагов может привести к использованию неблокирующего В/В...
слава роботам!
-
Shade
- Сообщения: 40
- ОС: ArchLinux
Re: COM-порт
У тебя вначале выполняется read, который и ждет (бесконечно) данных из порта.
Нужно сначала с помощью fnctl задать неблокирующий режим работы, а потом уже читать. В неблокирующем режиме, если данных нет, read вернет 0, а когда данные появяться, программа получит сигнал SIG_IO и можно будет их считать. Можно использовать и select для определения, есть ли данные.
Вот пример кода, написанного после чтения всё того же Serial Programming HOWTO (простенькая терминальная программа для модема)
Нужно сначала с помощью fnctl задать неблокирующий режим работы, а потом уже читать. В неблокирующем режиме, если данных нет, read вернет 0, а когда данные появяться, программа получит сигнал SIG_IO и можно будет их считать. Можно использовать и select для определения, есть ли данные.
Вот пример кода, написанного после чтения всё того же Serial Programming HOWTO (простенькая терминальная программа для модема)
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
-
DeMenchev
- Сообщения: 1
- ОС: Debian
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: COM-порт
Код: Выделить всё
void tty_init(){
int i;unsigned char c[1000];
fprintf(outfile,"\nОткрываю порт...\n");
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
fprintf(stderr,"Can't use port %s\n",comdev);
exit(1);
}
fprintf(outfile, " OK\nПолучаю текущие настройки порта...\n");
ioctl(comfd,TCGETA,&oldtty); // Узнаем текущие параметры порта
tty = oldtty;
tty.c_lflag = 0;
tty.c_iflag = BRKINT;//|PARENB|CMSPAR;
tty.c_oflag = 0;
tty.c_cflag = B9600|CS8|CREAD|CLOCAL|PARENB;//|CMSPAR;
tty.c_cflag &= ~PARODD;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 1;
ioctl(comfd,TCSETA,&tty);
fprintf(outfile," OK\n");
}
unsigned char read_tty_raw(){ // считываем 1 байт (с ожиданием сигнала)
unsigned char rb = 0; // то, что считываем
fd_set rfds; // набор файловых дескрипторов
struct timeval tv; // время ожидания
int retval; // возвращаемое ф-й select значение
tty.c_iflag &= ~PARODD; // принимаем с девятым битом = 0
ioctl(comfd,TCSETA,&tty);
// Ждем, сигнала с порта
FD_ZERO(&rfds); // очищаем набор
FD_SET(comfd, &rfds); // теперь это - свойства порта
tv.tv_sec = 0; tv.tv_usec = 5000; // ждем 5мс
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
if (!retval) return 0; // если сигнала нет, возвращаем ноль
if(FD_ISSET(comfd, &rfds)){
if(read(comfd, &rb, 1) < 1) return 0; // ошибка считывания
}
else return 0; // ошибка
#ifdef __TEST__
fprintf(stderr, "считан сигнал: %d\n", rb);
#endif
return rb;
}(кусок кода из рабочего проекта)
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка