2016-02-20 3 views
0

У меня есть следующая настройка: компьютер под управлением Linux (TCL) и устройство, которое отправляет пакеты фиксированной длины (10 байтов) с фиксированной частотой (100 Гц).Как получить данные на последовательном порту синхронно?

На компьютере у меня есть этот последовательный порт, и я пытаюсь читать входящие данные. Однако, вместо того, чтобы получать его в 10-байтовых фрагментах все время, считывается меньшее количество данных, и я вынужден их снова собрать.

Моя цель - отправить ответ для каждого пакета после его поступления, сохраняя интервалы между пакетами как можно больше.

Это, как я открыть последовательный порт:

int fd = open(device_name, O_RDWR | O_NOCTTY | O_NONBLOCK); 
if(fd == -1) 
{ 
    LOGPRINT("Failed to open terminal file.\nError #%d (%s)\n", 
      errno, strerror(errno)); 
     return fd; 
} 

LOGPRINT("Setting terminal attributes\n"); 
struct termios config; 
struct termios *pterm = &config; 
// set baud rate 

LOGPRINT("Setting baud rate to %d.\n", baud_rates[baud_rate_index]); 
// change to raw mode 
LOGPRINT("Setting terminal to raw mode\n"); 
pterm->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR 
        | IGNCR | ICRNL | IXON); 
pterm->c_oflag &= OPOST; 
pterm->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 
cfsetispeed(pterm, baud_bits[pconfig->baud_rate_index]); 
cfsetospeed(pterm, baud_bits[pconfig->baud_rate_index]); 
LOGPRINT("Set character size, parity and stop bit flags.\n"); 
// set character size 
pterm->c_cflag &= ~CSIZE; 
pterm->c_cflag |= csize_flag; 
// set parity 
pterm->c_cflag &= ~(PARENB | PARODD); 
pterm->c_cflag |= parity_flag; 
// set stopbits 
pterm->c_cflag &= ~CSTOPB; 
pterm->c_cflag |= stopbits_flag; 

// enable reading; ignore control lines 
pterm->c_cflag |= CREAD | CLOCAL; 
// disable flow control 

pterm->c_cc[VMIN] = 1; 
pterm->c_cc[VTIME] = 0; 
LOGPRINT("Flush terminal.\n"); 
// flush terminal 
tcflush(fd, TCIOFLUSH); 
LOGPRINT("Apply parameters.\n"); 
return WRAPSYSCALL(tcsetattr(fd, TCSANOW, pterm)); 

Кроме того я установить следующий дескриптор файла с fnctl:

int flags = fcntl(fd, F_GETFL); 
fcntl(fd, F_SETFL, flags | FASYNC | O_DIRECT); 

Я чтение из дескриптора файла в цикле с select() вызова в наборе дескрипторов файлов, содержащем fd, затем считывая все байты avaiable (запрашивая количество байтов намного больше 10).

Что я должен изменить для обеспечения того, чтобы входящие данные обрабатывались по мере их правильного ввода, своевременно?

+1

«считывается меньшее количество данных, и я вынужден их снова собрать» - да, это нормально с последовательными потоками байтов, а также использование подходящего протокола для установления границ сообщений. –

+0

Меня беспокоит причина. Если это происходит из-за того, что не все данные полученного пакета сразу попадают в буфер файлов, это означает, что я читаю остальную часть пакета только тогда, когда следующий на урнах, который побеждает цель ответа на пакеты по мере их поступления. – Srv19

+0

Большинство драйверов опубликует любой оставшиеся буферизованные данные, если больше не приходит в течение некоторого таймаута, обычно 3-5 символов. –

ответ

0

Если ваша программа ничего не делает, кроме ожидания байтов и ответа, вы можете попробовать использовать операции блокировки файлов. Удалите флаг O_NONBLOCK из вашего вызова функции open, а после установки порта выполните только read(fd, buffer, 10). Функция вернется после считывания ровно 10 байтов (или произойдет ошибка или придет сигнал).

Однако помните, что операция чтения может начинаться в середине передачи пакетов, поэтому, например, вы можете получить последние x байтов n-го пакета и первые 10-x пакета n + 1.

+0

OP должен использовать режим блокировки, так как код указывает на необработанный (неканонический) режим. Спецификации VMIN и VTIME игнорируются, когда порт настроен в неблокирующем режиме. BTW аргумент длины в ** read() ** указывает максимальную длину и может не возвращать * точно * длину, как вы писали. – sawdust

+0

хорошо, да, если я укажу десять, насколько я знаю, нет ничего предварительного чтения read() с 2 или 6 байтами. – Srv19

+0

@ Srv19: Если вы используете блокировку только для чтения, сигнал/ошибка может прекратить системный вызов. В других обстоятельствах он должен вернуть 10. – nsilent22

Смежные вопросы