C Epoll读取错误的字节

C Epoll读取错误的字节,c,linux,epoll,C,Linux,Epoll,我是linux系统编程的新手,所以请友好一点。 我必须在8N1模式下通过RS-422从波特率为921600的串行端口(/dev/ttyX)读取数据,无奇偶校验。 stty输出信号表明支持此波特率。 所以我决定给埃波尔打电话。 问题是epoll返回了错误的字节。 因为我已经指定了消息格式,所以我试图通过手动验证传入数据来进行调试。所以我画了这个: 所有消息的尾部都有2个字节的crc。 11 b5表示消息开始。消息长度应为36字节。 72 b5是另一个消息开始标记。112字节len。 73 b5也

我是linux系统编程的新手,所以请友好一点。 我必须在8N1模式下通过RS-422从波特率为921600的串行端口(/dev/ttyX)读取数据,无奇偶校验。 stty输出信号表明支持此波特率。 所以我决定给埃波尔打电话。 问题是epoll返回了错误的字节。 因为我已经指定了消息格式,所以我试图通过手动验证传入数据来进行调试。所以我画了这个:

所有消息的尾部都有2个字节的crc。 11 b5表示消息开始。消息长度应为36字节。 72 b5是另一个消息开始标记。112字节len。 73 b5也是消息标记。36字节。 请找到蓝色下划线:这是一条好消息。 小红+肥红是不好的。 它是37字节的len。我有一个额外的字节和crc不匹配。 下一个好的(绿色)。 下一个坏的。它是114字节而不是112字节,当然crc不匹配

这是我的密码:

... All necessary includes

#define SERIAL_BAUD 921600
#define MAXEVENTS 1024

int openSerial()
{
struct termios options;
int fd;

if ((fd = open("/dev/ttyUSB0", O_RDWR)) == -1)
{
    return -1;
}

if (tcgetattr(fd, &options) < 0)
{
    printf("Unable to get options with tcgetattr\n");
    return -1;
}

if (cfsetispeed(&options, SERIAL_BAUD) < 0)
{
    printf("Unable to set input speed with cfsetispeed\n");
    return -1;
}

if (cfsetospeed(&options, SERIAL_BAUD) < 0)
{
    printf("Unable to set output speed with cfsetispeed\n");
    return -1;
}

cfmakeraw(&options);

//options.c_cflag |= SERIAL_BAUD; // Set Baudrate first time
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CRTSCTS;

options.c_cflag &= ~ECHO; // Disable echoing of input characters
options.c_cflag &= ~ECHOE;

 // set to 8N1
options.c_cflag &= ~PARENB; // no parity
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CSIZE; // Mask the character size bits
options.c_cflag |= CS8; // 8 data bits

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

options.c_oflag = 0;

options.c_cc[VTIME] = 2; // inter-character timer
options.c_cc[VMIN] = 1; // blocking read until

if (tcflush(fd, TCIFLUSH) < 0)
{
    printf("Unable to flush fd with tcflush\n");
    return -1;
}

if (tcsetattr(fd, TCSANOW, &options) != 0)
{
    printf("Unable to set options with tcsetattr\n");
    return -1;
}

return fd;
}

int main(void)
{
int fd;
int efd;
struct epoll_event event;
struct epoll_event* events;
int length;
unsigned char buff[512];

if ((fd = openSerial()) < 0)
{
    printf("Exiting because of openSerial failure\n");
    return 1;
}

efd = epoll_create1(0);

event.data.fd = fd;
event.events = EPOLLIN;

if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event) < 0)
{
    printf("Epoll_ctl error occured\n");
    return 1;
}

events = (epoll_event*) calloc(MAXEVENTS, sizeof(event));

for(;;)
{
    int n = epoll_wait(efd, events, MAXEVENTS, 5000);

    if (n < 0)
    {
        // No ready descriptors, so wait a bit longer
        continue;
    }

    if(events[0].events & EPOLLIN)
    {
        length = read(events[0].data.fd, buff, sizeof(buff) / 2);

        if(length > 0)
        {
            printf("\n------MESSAGE START-------\n");
            for (int i = 0 ; i < length ; ++i)
            {
                if (i && i % 16 == 0)
                {
                    printf("\n");
                }
                printf("%02x ", buff[i]);
            }

            printf("\n------MESSAGE FINISH-------\n");
        }
    }
    else if(events[0].events & EPOLLOUT)
    {
        // TODO Write here to serial
    }
    else if(events[0].events & EPOLLHUP || events[0].events & EPOLLERR)
    {
        printf("Error occured on serial port\n");
    }
    else
    {
        printf("No data whthin 5 seconds.\n");
    }
}

free(events);
close(fd);

return 0;
}
。。。所有必要的包括
#定义串行波特率921600
#定义MAXEVENTS 1024
int openSerial()
{
结构termios选项;
int-fd;
如果((fd=open(“/dev/ttyUSB0”,O_RDWR))=-1)
{
返回-1;
}
如果(tcgetattr(fd和选项)<0)
{
printf(“无法使用tcgetattr获取选项\n”);
返回-1;
}
if(cfsetispeed(&options,串行_波特)<0)
{
printf(“无法使用cfsetispeed设置输入速度\n”);
返回-1;
}
if(cfsetospeed(&options,串行_波特)<0)
{
printf(“无法使用cfsetispeed设置输出速度\n”);
返回-1;
}
cfmakeraw(和选项);
//options.c_cflag |=串行_波特率;//第一次设置波特率
选项c|u cflag |=(CLOCAL | CREAD);
options.c_cflag&=~CRTSCTS;
options.c_cflag&=~ECHO;//禁用输入字符的回显
options.c_cflag&=~回声;
//设置为8N1
options.c_cflag&=~PARENB;//无奇偶校验
options.c_cflag&=~CSTOPB;//1停止位
options.c_cflag&=~CSIZE;//屏蔽字符大小位
options.c_cflag |=CS8;//8个数据位
options.c|u iflag&=~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
options.c_of lag=0;
options.c_cc[VTIME]=2;//字符间计时器
options.c_cc[VMIN]=1;//阻止读取直到
如果(tcflush(fd,TCIFLUSH)<0)
{
printf(“无法用tcflush刷新fd\n”);
返回-1;
}
如果(tcsetattr(fd、TCSANOW和选项)!=0)
{
printf(“无法使用tcsetattr\n设置选项”);
返回-1;
}
返回fd;
}
内部主(空)
{
int-fd;
int efd;
结构epoll_事件;
结构epoll_事件*事件;
整数长度;
无符号字符buff[512];
如果((fd=openSerial())<0)
{
printf(“由于openSerial失败而退出\n”);
返回1;
}
efd=epoll_create1(0);
event.data.fd=fd;
event.events=EPOLLIN;
if(epoll\u ctl(efd、epoll\u ctl\u ADD、fd和event)<0)
{
printf(“发生Epoll\u ctl错误\n”);
返回1;
}
events=(epoll_event*)calloc(MAXEVENTS,sizeof(event));
对于(;;)
{
int n=epoll_wait(efd,events,MAXEVENTS,5000);
if(n<0)
{
//没有现成的描述符,请稍等
继续;
}
if(事件[0]。事件和EPOLLIN)
{
长度=读取(事件[0].data.fd、buff、sizeof(buff)/2);
如果(长度>0)
{
printf(“\n------消息开始-------\n”);
对于(int i=0;i
您的问题是
read()
返回的字节无法满足您的期望。我认为没有理由相信埃波尔与此有关


我也看不出有任何理由假设
read()
提供的字节数与系统从设备
/dev/ttyUSB0
接收的字节数不同。如果这些与您预期的不同,那么我倾向于认为要么设备出现故障,要么您的预期不正确(或至少不完整)。

您提供的
openSerial()
函数不接受任何参数,但您使用参数调用它。结果行为未定义。不测试函数调用的返回值是否存在错误条件。如果发生错误,您肯定会从继续操作中得到令人惊讶的结果,就好像一切都如预期一样。这是一个简化的列表,以便更好地查看,但当您指出我应该检查返回值时,我决定再次检查是否测试了funcs的所有返回值。发现cfsetispeed失败。我会设法解决这个问题。此外,我还刷新了代码清单。简化很好,但前提是它生成了一个正确的程序,可以(原则上)重现问题。