接收缓存区:
/* 接收长度 */
int recv_len;
/* 接收缓存区 */
char recv_buf[1024];
串口接收函数:
void Uart1::RecvSerial(int fd)
{
fd_set fds;
struct timeval timeout={1,0}; //select等待1秒,1秒轮询,要非阻塞就置0
int select_ret=-1;
while(true)
{
FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(fd,&fds); //添加描述符
select_ret = select(fd+1,&fds,NULL,NULL,&timeout);
switch(select_ret) //select使用
{
case -1:
exit(-1);
break; //select错误,退出程序
case 0:
break; //再次轮询
default:
if(FD_ISSET(fd,&fds)) //测试fd是否可读。即是否有串口数据
{
recv_len=read(fd, recv_buf, sizeof(recv_buf));
recv_buf[recv_len] = '\0';
printf("recv_buf : %s \n", recv_buf);
}
}
}
}
其中fd为打开串口的文件描述符。使用open函数打开串口,是否阻塞和select无关。
/* 以阻塞的方式打开 */
int fd = open(dev_name_buf, O_RDWR|O_NOCTTY);
/* 以非阻塞的方式打开 */
/* int fd = open(dev_name_buf, O_RDWR); */
上述两种打开,在接收函数中都是可以正常使用的。open传入的阻塞参数只是对read函数起作用。
关于selecet函数:
函数原型:
int select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);
参数nfds:select监视的文件句柄数。
视进程中打开的文件数而定,一般设为你要监视各文件中的最大文件号加一。
(注:nfds并非一定表示监视的文件句柄数。官方文档仅指出nfds is the highest-numbered file descriptor in any of the three sets, plus 1. (可在linux环境中通过man select命令查得))
参数readfds、writefds和exceptfds 称为描述词组,是用来回传该描述词的读,写或例外的状况。
readfds:select监视的可读文件句柄集合。
writefds: select监视的可写文件句柄集合。
exceptfds: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, fd_set *fdset):检查fdset联系的文件句柄fd是否可读写,当>0表示可读写。
(关于fd_set及相关宏的定义见/usr/include/sys/types.h)
struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。
struct timeval
{
time_t tv_sec;
time_t tv_usec;
};
上述接收函数中,select函数中第三个参数传入NULL,表示不关心任何文件的写变化。
参考链接:
https://www.cnblogs.com/zhengAloha/p/8661762.html
https://blog.csdn.net/zimiao815/article/details/52806133
20190709补充:
Linux man中提供的函数:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}