COM-порт (Помогите запрограммировать)

Модератор: Модераторы разделов

Аватара пользователя
deninok
Сообщения: 585
Статус: Программист С++
ОС: Debian GNU/Linux

COM-порт

Сообщение deninok »

Уважаемые участники форума!

Помогите, пожалуйста, с последовательным портом. Никак не получается решить одну проблему.
Для освоения программирования 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()? Нужна ли она здесь вообще? Может, я вообще неправильно читаю последовательный порт?
Заранее благодарен за ваши ответы.
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: COM-порт

Сообщение elide »

мне кажется, что лучше забыть про fcntl и юзать select.
во всяком случае, я не понял, как обнудение флагов может привести к использованию неблокирующего В/В...
слава роботам!
Спасибо сказали:
Shade
Сообщения: 40
ОС: ArchLinux

Re: COM-порт

Сообщение Shade »

У тебя вначале выполняется read, который и ждет (бесконечно) данных из порта.
Нужно сначала с помощью fnctl задать неблокирующий режим работы, а потом уже читать. В неблокирующем режиме, если данных нет, read вернет 0, а когда данные появяться, программа получит сигнал SIG_IO и можно будет их считать. Можно использовать и select для определения, есть ли данные.

Вот пример кода, написанного после чтения всё того же Serial Programming HOWTO (простенькая терминальная программа для модема)
Спасибо сказали:
Аватара пользователя
deninok
Сообщения: 585
Статус: Программист С++
ОС: Debian GNU/Linux

Re: COM-порт

Сообщение deninok »

Огромное спасибо за ваши ответы!
Спасибо сказали:
DeMenchev
Сообщения: 1
ОС: Debian

Re: COM-порт

Сообщение DeMenchev »

Shade писал(а):
31.01.2006 15:59
Вот пример кода, написанного после чтения всё того же Serial Programming HOWTO (простенькая терминальная программа для модема)

А где пример-то? Мне бы тоже очень пригодился...
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: COM-порт

Сообщение eddy »

DeMenchev писал(а):
26.08.2009 21:48
А где пример-то? Мне бы тоже очень пригодился...

Код: Выделить всё

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 - патриотичная кодировка Изображение
Спасибо сказали: