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 \r\n"); // return -1; } uart02_fd = open("/dev/ttyO2", O_RDWR | O_NOCTTY); /* 打開串口 */ if(uart02_fd < 0) { printf("open /dev/ttyO2 error \r\n"); // 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 \n"); /* 在設定的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); /* 讀取串口數據 */ /* ** 數據解析 */ } } } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM