Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Таймаут при чтении из серийного порта.


Автор: xStream 12.2.2010, 15:26
Всем привет. Помогите, пожалуйста, разобраться с таймаутами при работе с серийным портом (/dev/ttyS0).
Устанавливаю я него примерно так:
Код

struct termios tconf;
tcgetattr(fd, &tconf);
tconf.c_cc[VTIME] = timeout / 100;
tcsetattr(fd, TCSANOW, &tconf);

Если параметр timeout меньше 2500 мс, тогда тайумаут работает как надо. Если же это значение выставить выше 2500 мс, тогда он перестает нормально работать и, скажем, при значении в 10 сек, read() может ожидать данных с устройства и 30 и 40 сек, а только потом возвращает полученный байт. Причем байт доступен в устройстве практически моментально. Не знаю чего он там ещё ждёт.
В чём может быть проблема? 
Мне нужны таймауты до 120 с. Сейчас вместо tcsetattr() использую select(), но это костыль. 

Автор: bilbobagginz 12.2.2010, 16:22
там есть 2 "локальных" режима:
"канонический", устанвливается:
Код

tconf.c_lflag |= (ICANON);

"неканонический":
Код

tconf.c_lflag &= (~ICANON);

функционал VTIME в каждом режиме свой.
перечитай очень внимательно мануальчик по termios.


Автор: xStream 12.2.2010, 16:27
Цитата(bilbobagginz @ 12.2.2010,  16:22)
там есть 2 "локальных" режима:
"канонический", устанвливается:
Код

tconf.c_lflag |=ICANON;

"неканонический":
Код

tconf.c_lflag ^= tconf.c_lflag;

функционал VTIME в каждом режиме свой.

перечитай очень внимательно мануальчик по termios.

Канонический режим у меня отключен. man tcsetattr перечитал 10 раз. В каноническом режиме таймаут вообще не работает.

Автор: bilbobagginz 12.2.2010, 16:39
xStream, 
a что сидит на другом конце последовательного порта?

Добавлено через 2 минуты и 37 секунд
может тот, кто сидит на др. конце - вырубается сам.

Автор: xStream 12.2.2010, 16:54
bilbobagginz, 
Фискальный регистратор.
На вряд ли. С select оно работает smile

Автор: bilbobagginz 12.2.2010, 17:03
а можешь показать что получаешь:
Код

if (tcsetattr(fd, TCSANOW, &tconf)){
   perror("skotinka: ");
}

?

Автор: xStream 12.2.2010, 17:11
bilbobagginz,  tcsetattr возвращает 0

Автор: bilbobagginz 12.2.2010, 17:18
все равно собака....  smile
А если устройство работает быстро, почему таймаут в 2.5 секунды - не подходит?

Добавлено @ 17:22
и еще момент, там есть еще каунтер байтов:
Код

term.c_cc[VMIN]

ты его трогал ?
там есть схема условий, когда read  возвращается, 4 случая (когда VMIN/VTIME по нулям)

и еще вопрос: почему асинхронный подход тебе не нравится?

Автор: xStream 12.2.2010, 17:28
Цитата(bilbobagginz @ 12.2.2010,  17:18)
все равно собака....  smile
А если устройство работает быстро, почему таймаут в 2.5 секунды - не подходит?

Добавлено @ 17:22
и еще момент, там есть еще каунтер байтов:
Код

term.c_cc[VMIN]

ты его трогал ?
там есть схема условий, когда read  возвращается, 4 случая (когда VMIN/VTIME по нулям)

и еще вопрос: почему асинхронный подход тебе не нравится?

Ожидать байт надо столько, сколько прописано в документации к устройству. И это время может колебаться от 500 мс, до 150000 мс. 
.c_cc[VMIN] выставлен в 0.

Автор: bilbobagginz 12.2.2010, 17:43
Цитата(xStream @  12.2.2010,  16:28 Найти цитируемый пост)
Ожидать байт

т.е. 1 байт ожидаешь ?

Добавлено через 12 минут и 37 секунд
и еще вопросик: когда read() возвращается позже чем надо, он какую ошибку возвращает, какой errno ?

Автор: xStream 15.2.2010, 11:07
Цитата(bilbobagginz @ 12.2.2010,  17:43)
т.е. 1 байт ожидаешь ?

и еще вопросик: когда read() возвращается позже чем надо, он какую ошибку возвращает, какой errno ?

да, по 1-му байту считываю

а read() возвращается без ошибки и с 1 прочитанным байтом (как и надо), даже если позже таймаута. но устройство, то уже потеряло логическую нить. оно считает, что комп не ответил в нужный промежуток времени и начинает "диалог" заново. 

Автор: kuzulis 15.2.2010, 16:45
ИМХО, select в помощь + все VMIN и VTIME по нулям + при открытии флагами ставить асинхронный режим + читать не по 1 байту - а по реальному их количеству в приемном буфере и потом просто проверять скока прочиталось и скока нужно еще дочитать и т.п. Всё просто.

Вопрос: нужно именно под *.nix или тебе можно и кроссплатформенное решение на Qt4 ? smile

Добавлено через 1 минуту и 57 секунд
И еще, какой протокол работы с устройством?

Добавлено через 4 минуты и 30 секунд
Цитата

Мне нужны таймауты до 120 с. Сейчас вместо tcsetattr() использую select(), но это костыль. 


Ну неправда... Это не костыль! smile

Автор: xStream 15.2.2010, 18:02
Цитата

ИМХО, select в помощь + все VMIN и VTIME по нулям + при открытии флагами ставить асинхронный режим + читать не по 1 байту - а по реальному их количеству в приемном буфере и потом просто проверять скока прочиталось и скока нужно еще дочитать и т.п. Всё просто.

Примерно так всё сейчас и работает.

Цитата

Вопрос: нужно именно под *.nix или тебе можно и кроссплатформенное решение на Qt4 ? smile

Не можно, а нужно. Использую QextSerialPort

Цитата

И еще, какой протокол работы с устройством?

АТОЛ Протокол работы ККМ.

Автор: kuzulis 15.2.2010, 18:24
Цитата

Не можно, а нужно. Использую QextSerialPort


а попробуйте ка  QSerialDevice. http://fireforge.net/snapshots.php?group_id=199

PS: мне нужны тестеры сего поделия smile

Добавлено через 45 секунд
Цитата

Примерно так всё сейчас и работает.


ИМХО - тогда и нечего заморачиваться

Автор: xStream 16.2.2010, 11:06
kuzulis, отписался тебе в личку. 

Цитата

ИМХО - тогда и нечего заморачиваться


приходится. с select тоже не все гладко.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)