使用poll处理多个fd的数据

使用poll处理多个串口数据

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/time.h>
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>


#define IMU_SERIAL "/dev/ttyCH9344USB0"
#define ENCODE_SERIAL "/dev/ttyTHS2"

#define IMU_DATA_FILE "/tmp/imu.bin"
#define ENCODE_DATA_FILE "/tmp/encode.bin"

#define POLL_FD_NUM_MAX 2
#define RECVBUF_LEN_MAX 1024*1024


void close_serial(int *fd) {
    close(*fd);
    *fd = -1;

    return;
}

void close_file(FILE **fd) {
    fclose(*fd);
    *fd = NULL;

    return;
}

void free_buf(void **buf) {
    free(*buf);
    *buf = NULL;

    return;
}

int ParseBaudRate(int baud)
{
    int value = -1;

    if (baud == B50 || baud == 50)
    {
        value = B50;
    }
    else if (baud == B75 || baud == 75)
    {
        value = B75;
    }
    else if (baud == B110 || baud == 110)
    {
        value = B110;
    }
    else if (baud == B134 || baud == 134)
    {
        value = B134;
    }
    else if (baud == B150 || baud == 150)
    {
        value = B150;
    }
    else if (baud == B200 || baud == 200)
    {
        value = B200;
    }
    else if (baud == B300 || baud == 300)
    {
        value = B300;
    }
    else if (baud == B600 || baud == 600)
    {
        value = B600;
    }
    else if (baud == B1200 || baud == 1200)
    {
        value = B1200;
    }
    else if (baud == B1800 || baud == 1800)
    {
        value = B1800;
    }
    else if (baud == B2400 || baud == 2400)
    {
        value = B2400;
    }
    else if (baud == B4800 || baud == 4800)
    {
        value = B4800;
    }
    else if (baud == B9600 || baud == 9600)
    {
        value = B9600;
    }
    else if (baud == B19200 || baud == 19200)
    {
        value = B19200;
    }
    else if (baud == B38400 || baud == 38400)
    {
        value = B38400;
    }
    else if (baud == B57600 || baud == 57600)
    {
        value = B57600;
    }
    else if (baud == B115200 || baud == 115200)
    {
        value = B115200;
    }
    else if (baud == B230400 || baud == 230400)
    {
        value = B230400;
    }
    else if (baud == B460800 || baud == 460800)
    {
        value = B460800;
    }
    else if (baud == B500000 || baud == 500000)
    {
        value = B500000;
    }
    else if (baud == B576000 || baud == 576000)
    {
        value = B576000;
    }
    else if (baud == B921600 || baud == 921600)
    {
        value = B921600;
    }
    else if (baud == B1000000 || baud == 1000000)
    {
        value = B1000000;
    }
    else if (baud == B1152000 || baud == 1152000)
    {
        value = B1152000;
    }
    else if (baud == B1500000 || baud == 1500000)
    {
        value = B1500000;
    }
    else if (baud == B2000000 || baud == 2000000)
    {
        value = B2000000;
    }
    else if (baud == B2500000 || baud == 2500000)
    {
        value = B2500000;
    }
    else if (baud == B3000000 || baud == 3000000)
    {
        value = B3000000;
    }
    else if (baud == B3500000 || baud == 3500000)
    {
        value = B3500000;
    }
    else if (baud == B4000000 || baud == 4000000)
    {
        value = B4000000;
    }

    return value;
}

int open_serial(char *tty_name, int baud) {
    int ret = -1;
    int fd = -1;
    struct termios options;

    memset(&options, 0, sizeof(options));

    fd = open(tty_name, O_RDWR | O_NOCTTY); //打开串口设备
    if (fd < 0)
    {
        printf("open tty failed:%s\n", strerror(errno));
        return fd;
    }

    ret = tcgetattr(fd, &options); //获取原有的串口属性的配置
    if (ret != 0)
    {
        printf("tcgetattr() failed:%s\n", strerror(errno));
        close_serial(&fd);
        return fd;
    }

    // 激活选项有CLOCAL和CREAD,用于本地连接和接收使能;
    options.c_cflag |= CLOCAL | CREAD;

    //设置波特率
    cfsetspeed(&options, ParseBaudRate(baud));

    // 设置数据位,需使用掩码设置
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    // 设置奇偶校验位-无校验
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~PARODD;

    // 设置停止位,通过激活c_cflag中的CSTOPB实现。若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB
    options.c_cflag &= ~CSTOPB;
    
    // 设置最少字符和等待时间,对于接收字符和等待时间没有特别要求时,可设为0
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;

    // 刷新输入输出队列
    tcflush(fd, TCIOFLUSH);

    if ((tcsetattr(fd, TCSAFLUSH, &options)) != 0)
    {
        printf("tcsetattr failed:%s\n", strerror(errno));
        close_serial(&fd);
        return fd;
    }

    printf("open tty[%s] success, buad[%d]\n", tty_name, baud);
    return fd;
}

int main()
{
    int i = 0;
    int ret = -1;
    int recvlen = -1;
    int writelen = -1;
    int tty_imufd = -1;
    int tty_encodefd = -1;
    int fionread_byte = -1;

    FILE *imu_fd = NULL;
    FILE *encode_fd = NULL;
    struct pollfd poll_fd[POLL_FD_NUM_MAX];

    imu_fd = fopen(IMU_DATA_FILE, "ab");
    if (NULL == imu_fd)
    {
        printf("open file[%s] failed\n", IMU_DATA_FILE);
        return 1;
    }

    encode_fd = fopen(ENCODE_DATA_FILE, "ab");
    if (NULL == encode_fd)
    {
        printf("open file[%s] failed\n", ENCODE_DATA_FILE);
        close_file(&imu_fd);
        return 1;
    }

    char *recv_buf = malloc(RECVBUF_LEN_MAX);
    if (recv_buf == NULL)
    {
        printf("malloc %d failed\n", RECVBUF_LEN_MAX);

        close_file(&imu_fd);
        close_file(&encode_fd);
        return 1;
    }

    tty_imufd = open_serial(IMU_SERIAL, 460800);
    if (tty_imufd < 0)
    {
        printf("open [%s] failed\n", IMU_SERIAL);
        free_buf((void **)&recv_buf);
        close_file(&imu_fd);
        close_file(&encode_fd);
        return 1;
    }

    tty_encodefd = open_serial(ENCODE_SERIAL, 460800);
    if (tty_encodefd < 0)
    {
        printf("open [%s] failed\n", ENCODE_SERIAL);

        free_buf((void **)&recv_buf);
        close_file(&imu_fd);
        close_file(&encode_fd);
        close_serial(&tty_imufd);
        return 1;
    }

    poll_fd[0].fd = tty_imufd;
    poll_fd[0].events = POLLIN;
    poll_fd[1].fd = tty_encodefd;
    poll_fd[1].events = POLLIN;

    while(1)
    {
        ret = poll(poll_fd, POLL_FD_NUM_MAX, 500);
        if (ret < 0)
        {
            printf("poll error[%s]\n", strerror(errno));
            continue;
        }
        
        for (i = 0; i < POLL_FD_NUM_MAX; i++)
        {
            if (!(poll_fd[i].events & POLLIN))
            {
                continue;
            }
            
            ioctl(poll_fd[i].fd, FIONREAD, &fionread_byte);
            if (fionread_byte <= 0)
            {
                continue;
            }

            recvlen = read(poll_fd[i].fd, recv_buf, RECVBUF_LEN_MAX);
            if (recvlen < 0)
            {
                printf("read() error:%s\n", strerror(errno));
                memset(recv_buf, 0, RECVBUF_LEN_MAX);
                continue;
            }

            if (poll_fd[i].fd == tty_imufd)
            {
                writelen = fwrite(recv_buf, sizeof(char), recvlen, imu_fd);
                if (writelen != recvlen)
                {
                    printf("writing file falied, writelen_expect: %d, writelen_real: %d\n", recvlen, writelen);
                }
            }
            else if (poll_fd[i].fd == tty_encodefd)
            {
                writelen = fwrite(recv_buf, sizeof(char), recvlen, encode_fd);
                if (writelen != recvlen)
                {
                    printf("writing file falied, writelen_expect: %d, writelen_real: %d\n", recvlen, writelen);
                }
            }
        }

        usleep(1000);
    }
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用 `poll` 函数连续监测多个文件描述符的简单示例: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h> #define MAX_EVENTS 2 int main() { struct pollfd fds[MAX_EVENTS]; int timeout = 5000; // 超时时间,单位为毫秒 // 打开两个文件描述符 int fd1 = open("file1.txt", O_RDONLY); int fd2 = open("file2.txt", O_RDONLY); // 设置文件描述符和事件 fds[0].fd = fd1; fds[0].events = POLLIN; fds[1].fd = fd2; fds[1].events = POLLIN; while (1) { int ret = poll(fds, MAX_EVENTS, timeout); if (ret == -1) { perror("poll"); exit(EXIT_FAILURE); } else if (ret == 0) { printf("Timeout occurred.\n"); } else { for (int i = 0; i < MAX_EVENTS; i++) { if (fds[i].revents & POLLIN) { printf("File descriptor %d has data to read.\n", fds[i].fd); char buffer[1024]; ssize_t bytesRead = read(fds[i].fd, buffer, sizeof(buffer)); if (bytesRead == -1) { perror("read"); exit(EXIT_FAILURE); } printf("Read %zd bytes: %s\n", bytesRead, buffer); } } } } // 关闭文件描述符 close(fd1); close(fd2); return 0; } ``` 在上面的示例中,我们使用 `poll` 函数来监测两个文件描述符 `fd1` 和 `fd2` 是否有数据可读。首先,我们打开了两个文件描述符并设置对应的事件为 `POLLIN`,然后进入一个无限循环。在循环中,调用 `poll` 函数来等待事件发生,如果有事件发生,则通过检查 `revents` 域来确定是哪个文件描述符上有数据可读。然后,我们使用 `read` 函数从文件中读取数据并进行处理。 这个示例展示了如何使用 `poll` 函数来连续监测多个文件描述符的状态,并在有数据可读时进行相应的处理。需要注意的是,示例中的超时时间设置为 5 秒,可以根据需要进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值