如何同步接收串口数据?

时间:2016-02-20 08:17:26

标签: c linux serial-port

我有以下设置:运行Linux(TCL)的计算机和以固定频率(100 Hz)发送固定长度(10字节)数据包的设备。

在计算机上,我打开了串口,我正在尝试读取传入的数据。但是,不是一直以10字节块的形式接收它,而是读取的数据量较少,我不得不重新组装它们。

我的目标是在每个数据包到达后发送一个响应,尽可能保留数据包之间的间隔。

这是我打开串口的方式:

@PreAuthorize

另外,我使用fnctl:

在文件描述符上设置以下内容
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));

我正在循环中读取文件描述符,对int flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | FASYNC | O_DIRECT); 调用包含select()的文件描述符集,然后读取所有可用字节(请求的字节数大于10)。

我应该更改什么以确保及时处理传入数据?

1 个答案:

答案 0 :(得分:0)

如果你的程序只是等待字节和回答,那么你可以尝试使用阻塞文件操作。从O_NONBLOCK函数调用中删除open标记,设置端口后只需执行read(fd, buffer, 10)。该函数在准确读取10个字节(或发生错误或信号到达)后将返回。

但是,请记住,您读取操作可以在数据包传输过程中启动,因此例如,您可以获取第n个数据包的最后x个字节和第n个数据包n + 1的第一个数据。