串口讀函數(shù)read是阻塞函數(shù)爆土,多路串口接收不太好處理,如果每路串口使用單獨的線程接收浪費資源,使用select()函數(shù)監(jiān)聽多路串口數(shù)據(jù)可以把所有接收的數(shù)據(jù)在一個線程中處理缰犁,類似QT中的槽函數(shù)功能滑频。
1捡偏、函數(shù)原型介紹
int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)
入口參數(shù):
①:ndfs:select() 中監(jiān)視的文件句柄,一般設(shè)為要監(jiān)視的文件中的最大文件號加一峡迷。
②:rdfds:select()監(jiān)視的可讀文件句柄集合银伟,當rdfds映象的文件句柄狀態(tài)變成可讀時系統(tǒng)告訴select函數(shù)返回。這個集合中有一個文件可讀绘搞,select就會返回一個大于0的值彤避,表示有文件可讀,如果沒有可讀的文件夯辖,則根據(jù)timeout參數(shù)再判斷是否超時忠藤,若超出timeout的時間,select返回0楼雹,若發(fā)生錯誤返回負值模孩,可以傳入NULL值,表示不關(guān)心任何文件的讀變化贮缅;
③:wtfds: select()監(jiān)視的可寫文件句柄集合榨咐,當wtfds映象的文件句柄狀態(tài)變成可寫時系統(tǒng)告訴select函數(shù)返回。
如果這個集合中有一個文件可寫谴供,select就會返回一個大于0的值块茁,表示有文件可寫,
如果沒有可寫的文件桂肌,則根據(jù)timeout參數(shù)再判斷是否超時数焊,
若超出timeout的時間,select返回0崎场,若發(fā)生錯誤返回負值佩耳,
可以傳入NULL值,表示不關(guān)心任何文件的寫變化谭跨。
④:exfds:select()監(jiān)視的異常文件句柄集合干厚,當exfds映象的文件句柄上有特殊情況發(fā)生時系統(tǒng)會告訴select函數(shù)返回。
⑤:timeout:select()的超時結(jié)束時間
配置函數(shù):
FD_ZERO(fd_set *fdset):清空fdset與所有文件句柄的聯(lián)系螃宙。
FD_SET(int fd, fd_set *fdset):建立文件句柄fd與fdset的聯(lián)系蛮瞄。
FD_CLR(int fd, fd_set *fdset):清除文件句柄fd與fdset的聯(lián)系。
FD_ISSET(int fd, fdset *fdset):檢查fdset聯(lián)系的文件句柄fd是否可讀寫谆扎,>0表示可讀寫挂捅。
2、
int main(void)
{
int uart01_fd ,uart02_fd堂湖;
fd_set recv_fds; /* 定義接收fds 一個存放文件描述符(file descriptor)闲先,即文件句柄的聚合周瞎,實際上是一long類型的數(shù)組 */
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; //設(shè)定超時時間
tv.tv_usec = 0; //10000us = 10ms
if(uart01_fd > maxfd) /* maxfd 為最大值 */
{
maxfd = uart01_fd;
}
if(uart02_fd > maxfd)
{
maxfd = uart01_fd;
}
for(;;)
{
/* 注意每次都要重新設(shè)置 */
FD_ZERO(&recv_fds);
FD_SET(uart01_fd,&recv_fds); /* 分別把句柄加入讀監(jiān)視集合里去 */
FD_SET(uart02_fd,&recv_fds); /* 分別把句柄加入讀監(jiān)視集合里去 */
fd_result = select(maxfd + 1, &recv_fds, NULL, NULL, &tv); /* 注意是最大值加1 */
if(fd_result < 0)
{
printf("select err"); /* select函數(shù)出錯 */
usleep(10000);
continue;
}
else if(fd_result == 0)
{
// printf("select time out \n"); /* 在設(shè)定的tv時間內(nèi),socket的狀態(tài)沒有發(fā)生變化 */
usleep(10000);
continue;
}
else /* 開始讀數(shù)據(jù) */
{
if(FD_ISSET(uart01_fd, &recv_fds)) /* 先判斷一下是哪個句柄可讀 */
{
uiLen = read(uart01_fd,ucbuff,0xff); /* 讀取串口數(shù)據(jù) */
/*
** 數(shù)據(jù)解析
*/
}
if(FD_ISSET(uart02_fd, &recv_fds)) /* 先判斷一下是哪個句柄可讀 */
{
uiLen = read(uart02_fd,ucbuff,0xff); /* 讀取串口數(shù)據(jù) */
/*
** 數(shù)據(jù)解析
*/
}
}
}
}