Перейти к содержанию

Задержка при чтении COM-порта под Linux


Рекомендуемые сообщения

Добрый день! Есть девайс,подключенный к COM-порту. Протокол обмена таков: посылаем 2 байта вопроса и читаем 3 байта ответа. Осциллографом четко видны посылки к устройству и практически сразу же ответ, все вместе занимает приблизительно 0,5 мс, однако функция чтения read возвращает значение только через 10 мс! Подскажите, как ускорить этот процесс до 1мс?

Пример программы:

char dev[] = "/dev/ttyS0";

port=open(dev,O_RDWR | O_NDELAY | O_NOCTTY);

if (port==-1) {

printf("err: failed to open ""%s""!",dev);

return 1;

}

//если поставить этот кусок, то задержка уменьшается до 4 мс, но этого мало

struct serial_struct ser;

ioctl(port, TIOCGSERIAL, &ser);

ser.flags |= ASYNC_LOW_LATENCY;

ioctl(port, TIOCSSERIAL, &ser);

//настройки порта таковы

termios tinfo;

fcntl(port,F_SETFL, 0); //ждать запрошенных данных

tcgetattr(port,&tinfo);

tinfo.c_cflag&=~(CSIZE | CRTSCTS | CSTOPB);

tinfo.c_cflag|=(CLOCAL | CREAD | CS8 | PARENB | CBAUD);

tinfo.c_iflag&=~(ISTRIP | IXON | IXOFF | IXANY | IGNBRK | BRKINT | PARMRK | INLCR | IGNCR | ICRNL);

tinfo.c_iflag|=(INPCK);

tinfo.c_oflag&=~OPOST;

tinfo.c_lflag&=~(ICANON | ECHO | ECHONL | ECHOE | ISIG | IEXTEN);

cfsetospeed(&tinfo,B115200);

cfsetispeed(&tinfo,B115200);

tcflush(port,TCIFLUSH);

tcsetattr(port,TCSANOW,&tinfo);

//собственно главный цикл, который выполняется 10 мс

char bufO[2]={10,10};

char buf[20];

while(1)

{ write(port,bufO,2);

read(port,buf,3);

}

Если поставить чтение без задержки fcntl(port,F_SETFL, FNDELAY), а использовать другие механизмы (через select, либо читать в цикле пока не наберется 3 байта) - результат один и тот же: цикл выполняется недопустимо медленно. Хотя под Windows XP аналогичная программа опрашивает данное устройство около 1 мс!

Ссылка на комментарий
Поделиться на другие сайты

Здравствуйте !

Знаете, этот код оставляет странное впечатление... Типа, что он перенесен по копи/паст из ... Даже не знаю - откуда ! В частности, используются BSD и устаревшие опции...

Может быть оставить все настройки СОМ-порта (кроме скорости) по умолчанию ? А самое главное замечание, Вы используете RAW режим работы с СОМ-портом :

tinfo.c_lflag&=~(ICANON

Но не уточняете параметры работы в НЕканоническом режиме. Т.е., раз

Вы задаете НЕканонический режим, то должны и задать параметры :

buf.c_cc[VMIN] = <<Минимальное количество байт>>;

buf.c_cc[VTIME] = <<Время тайм-аута>>;

Попробуйте поварьировать эти параметры, может быть - в них дело ?

Ссылка на комментарий
Поделиться на другие сайты

	ioctl(comfd,TCGETA,&oldtty); // Узнаем текущие параметры порта
	tty = oldtty;
	tty.c_lflag    = 0;
	tty.c_iflag    = BRKINT;
	tty.c_oflag    = 0;
	tty.c_cflag    = B9600|CS8|CREAD|CLOCAL|PARENB;
	tty.c_cflag &= ~PARODD; // это, смотря какую вам надо четность
	tty.c_cc[VMIN] = 0;
	tty.c_cc[VTIME] = 1;
	ioctl(comfd,TCSETA,&tty);
Ссылка на комментарий
Поделиться на другие сайты

Пробовали, не помогает. Единственный способ, которым удалось быстро считывать данные - это прямой доступ к портам (inb\outb).

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...