zoukankan      html  css  js  c++  java
  • Linux中多路串口Select监听方式

    申明:本文转自链接:https://www.jianshu.com/p/a293869bbdb8

    串口读函数read是阻塞函数,多路串口接收不太好处理,如果每路串口使用单独的线程接收浪费资源,使用select()函数监听多路串口数据可以把所有接收的数据在一个线程中处理,类似QT中的槽函数功能。
    1、函数原型介绍:

      int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)

    入口参数:
    ①:ndfs:select() 中监视的文件句柄,一般设为要监视的文件中的最大文件号加一。
    ②:rdfds:select()监视的可读文件句柄集合,当rdfds映象的文件句柄状态变成可读时系统告诉select函数返回。这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值,可以传入NULL值,表示不关心任何文件的读变化;
    ③:wtfds: select()监视的可写文件句柄集合,当wtfds映象的文件句柄状态变成可写时系统告诉select函数返回。
    如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,
    如果没有可写的文件,则根据timeout参数再判断是否超时,
    若超出timeout的时间,select返回0,若发生错误返回负值,
    可以传入NULL值,表示不关心任何文件的写变化。
    ④:exfds:select()监视的异常文件句柄集合,当exfds映象的文件句柄上有特殊情况发生时系统会告诉select函数返回。
    ⑤:timeout:select()的超时结束时间
    配置函数:
    FD_ZERO(fd_set *fdset):清空fdset与所有文件句柄的联系。
    FD_SET(int fd, fd_set *fdset):建立文件句柄fd与fdset的联系。
    FD_CLR(int fd, fd_set *fdset):清除文件句柄fd与fdset的联系。
    FD_ISSET(int fd, fdset *fdset):检查fdset联系的文件句柄fd是否可读写,>0表示可读写。


    2、示例代码:
    int main(void)
    {
        int     uart01_fd ,uart02_fd;
        fd_set  recv_fds;  /* 定义接收fds  一个存放文件描述符(file descriptor),即文件句柄的聚合,实际上是一long类型的数组 */
        int     maxfd   = 0;    /* 定义最大句柄 */
        int     fd_result;
        struct  timeval tv;       /* 超时时间 */
    
        uart01_fd   =    open("/dev/ttyO1", O_RDWR | O_NOCTTY); /* 打开串口 */
        if(uart01_fd < 0) {
            printf("open /dev/ttyO1 error 
    ");
                   // return -1;
        }
        
        uart02_fd   =    open("/dev/ttyO2", O_RDWR | O_NOCTTY); /* 打开串口 */
        if(uart02_fd < 0) {
            printf("open /dev/ttyO2 error 
    ");
                   // return -1;
        }
        
        tv.tv_sec   = 10;       //设定超时时间 
        tv.tv_usec  = 0;          //10000us = 10ms
        if(uart01_fd > maxfd)                            /* maxfd 为最大值  */
        {
            maxfd = uart01_fd;
        }
        if(uart02_fd > maxfd)
        {
            maxfd = uart01_fd;
        }
        for(;;)
        {   
            /* 注意每次都要重新设置 */
            FD_ZERO(&recv_fds);
            FD_SET(uart01_fd,&recv_fds);                                /* 分别把句柄加入读监视集合里去   */
            FD_SET(uart02_fd,&recv_fds);                                /* 分别把句柄加入读监视集合里去   */
    
            fd_result = select(maxfd + 1, &recv_fds, NULL, NULL, &tv);  /* 注意是最大值加1                   */
            if(fd_result < 0)
            {
                    printf("select err");                               /* select函数出错                 */
                usleep(10000);
                continue;
            }
            else if(fd_result == 0)
            {
                // printf("select time out 
    "); /* 在设定的tv时间内,socket的状态没有发生变化 */
                usleep(10000);
                continue;
            }
            else                                                        /* 开始读数据 */
            {
                if(FD_ISSET(uart01_fd, &recv_fds))                      /* 先判断一下是哪个句柄可读 */
                    {
                    uiLen  = read(uart01_fd,ucbuff,0xff);               /*  读取串口数据  */
                                    /*
                                      ** 数据解析 
                                      */        
                }   
                if(FD_ISSET(uart02_fd, &recv_fds))                      /* 先判断一下是哪个句柄可读 */
                    {
                    uiLen  = read(uart02_fd,ucbuff,0xff);                /*  读取串口数据  */
                                    /*
                                      ** 数据解析 
                                      */        
                }
            }
        }
    }
  • 相关阅读:
    django文件上传
    django验证码
    auth模块---笔记
    css笔记
    django模板系统---2
    django模板系统
    Django中间件
    前端笔记---1
    我的django笔记---1
    DNS服务器的搭建
  • 原文地址:https://www.cnblogs.com/beyonne/p/11224730.html
Copyright © 2011-2022 走看看