epoll 获取串口数据 亲测可用

本文介绍了一个使用Linux系统通过串口接收并打印数据的程序实例。该程序利用了epoll进行高效的事件监听,并通过多线程的方式实现了串口数据的接收与处理。文中详细展示了如何配置串口参数以及实现串口数据的正确读取。
串口助手发送八个字节,linux接收并打印。必须发送8个字节(这是bug。当然也可以在程序里改成必须发送9个字节)
#include     <stdio.h>  
#include     <stdlib.h>   
#include     <unistd.h>    
#include     <sys/types.h>  
#include     <sys/stat.h>  
#include     <fcntl.h>   
#include     <termios.h>  
#include     <errno.h>  
#include     <string.h>  
#include     <pthread.h>
#include     <sys/epoll.h>

#define MAXEVENTS 64
int fd; 
int efd;

void pthread_uartrecv(void)
{
  int n,i,nread,s;

  char buff[20];
  struct epoll_event event;
  struct epoll_event* events;
  events=calloc(MAXEVENTS,sizeof event);  
  efd=epoll_create(5);//epoll support number is 5 
  event.data.fd=fd;
  event.events=EPOLLIN|EPOLLET; //et mod,put in data
  s=epoll_ctl(efd,EPOLL_CTL_ADD,fd,&event);  
  
  while(1)
  {
	int len=0;
	bzero(buff,8);
	while(1)
	{
	    n=epoll_wait(efd,events,MAXEVENTS,-1);// -1 :wait until it happen
	    for(i=0;i<n;i++)
	    {
		if((events[i].events & EPOLLERR)||(events[i].events & EPOLLHUP)||(!(events[i].events & EPOLLIN)))
		{
			fprintf(stderr,"epoll error\n");  
		        close(events[i].data.fd);  
		        continue;  
		} 
		else 
		{
			nread = read(events[i].data.fd,buff+len,8);
			tcdrain(fd); 
			tcflush(fd,TCIOFLUSH); 
			len=len+nread;
			printf("nread=%d,len=%d\n",nread,len);
		}
	    }
	    if(len>=8)
		break;
	}
	printf("%s\n",buff); 
  }
}
    
int main()  
{  
    int flags;
    struct termios opt;   
    //fd = open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY); 
    fd = open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK); 
    //fcntl(fd, F_SETFL, 0); 
    //flags=fcntl(fd, F_GETFL, 0); 
    //flags|=O_NONBLOCK;
    //fcntl(fd, F_SETFL, flags); 

    tcgetattr(fd, &opt);        
    cfsetispeed(&opt, B9600);  
    cfsetospeed(&opt, B9600);  
    if(tcsetattr(fd, TCSANOW, &opt) != 0 )  
    {       
       perror("tcsetattr error1");  
       return -1;  
    }  
    opt.c_cflag &= ~CSIZE;    
    opt.c_cflag |= CS8;     
    opt.c_cflag &= ~CSTOPB;   
    opt.c_cflag &= ~PARENB;   
    opt.c_iflag &= ~INPCK;//opt.c_cflag &= ~INPCK;the last this is fetal set  
    opt.c_cflag |= (CLOCAL | CREAD);  
    opt.c_cflag &= ~CRTSCTS;
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
    opt.c_oflag &= ~OPOST;  
    opt.c_oflag &= ~(ONLCR | OCRNL);    //添加的  
    opt.c_iflag &= ~(ICRNL | INLCR);  
    opt.c_iflag &= ~(IXON | IXOFF | IXANY);    //添加的   
    opt.c_cc[VTIME] = 8;  
    opt.c_cc[VMIN] = 10;  
      
    tcflush(fd, TCIOFLUSH);  
   
    printf("configure complete\n");  
     
    if(tcsetattr(fd, TCSANOW, &opt) != 0)  
    {  
        perror("serial error");  
        return -1;  
    }   
    
    pthread_t id;
    pthread_create(&id,NULL,(void*)pthread_uartrecv,NULL);
  
    while(1)  
    {    
        sleep(2);
	printf("this is main function\n");
    }  
}
为了改善上述bug
 void pthread_uartrecv(void)
{
  int n,i,nread,s;
  char buff[20];
  struct epoll_event event;
  struct epoll_event* events;
  events=calloc(MAXEVENTS,sizeof event);  
  efd=epoll_create(5);//epoll support number is 5 
  event.data.fd=fd;
  event.events=EPOLLIN|EPOLLET; //et mod,put in data
  s=epoll_ctl(efd,EPOLL_CTL_ADD,fd,&event);  
  
  while(1)
  {
	int len=0;
	bzero(buff,20);
	while(1)
	{
	    //printf("here epoll_wait\n");
	    n=epoll_wait(efd,events,MAXEVENTS,20);// -1 :wait until it happen
	    for(i=0;i<n;i++)
	    {
		nread = read(events[i].data.fd,buff+len,20);
		if(nread>0)
		{
		    tcdrain(fd); 
		    tcflush(fd,TCIOFLUSH); 
		    len=len+nread;
		    printf("nread=%d,len=%d\n",nread,len);
		}
	    }
	    if(n==0)
	    {
		break;
	    }
	}
	if(len>0)
	    printf("%s\n",buff); 
  }
}

或者 封装成函数

#include     <stdio.h>  
#include     <stdlib.h>   
#include     <unistd.h>    
#include     <sys/types.h>  
#include     <sys/stat.h>  
#include     <fcntl.h>   
#include     <termios.h>  
#include     <errno.h>  
#include     <string.h>  
#include     <pthread.h>
#include     <sys/epoll.h>

#define MAXEVENTS 64
int fd; 
int efd;

//
int epoll_read(char *buff,int datalen)
{
    
    int n,i,nread,len;
    struct epoll_event event;
    struct epoll_event* events;
    events=calloc(MAXEVENTS,sizeof event);  
    efd=epoll_create(5);//epoll support number is 5 
    event.data.fd=fd;
    event.events=EPOLLIN|EPOLLET; //et mod,put in data
    epoll_ctl(efd,EPOLL_CTL_ADD,fd,&event);  
    len=0;
    while(1)
    {
	n=epoll_wait(efd,events,MAXEVENTS,20);// -1 :wait until it happen
	for(i=0;i<n;i++)
	{
	    nread = read(events[i].data.fd,buff+len,datalen);
	    if(nread>0)
	    {
		tcdrain(fd); 
		tcflush(fd,TCIOFLUSH); 
		len=len+nread;
		printf("nread=%d,len=%d\n",nread,len);
	    }
	}
	if(n==0)
	{
	    break;
	}
    }
    free(events);
    close(efd); //please close efd after used epoll 这是易错点,否则会导致后面无法接收串口数据
    return len;
}
void pthread_uartrecv(void)
{
  

  char buff[20];
  while(1)
  {
	int len=0;
	bzero(buff,20);
	len=epoll_read(buff,20);
	if(len>0)
	    printf("len=%d,buff=%s\n",len,buff); 
  }
}
    
int main()  
{  
    int flags;
    struct termios opt;   
    //fd = open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY); 
    fd = open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK); 
    //fcntl(fd, F_SETFL, 0); 
    //flags=fcntl(fd, F_GETFL, 0); 
    //flags|=O_NONBLOCK;
    //fcntl(fd, F_SETFL, flags); 

    tcgetattr(fd, &opt);        
    cfsetispeed(&opt, B9600);  
    cfsetospeed(&opt, B9600);  
    if(tcsetattr(fd, TCSANOW, &opt) != 0 )  
    {       
       perror("tcsetattr error1");  
       return -1;  
    }  
    opt.c_cflag &= ~CSIZE;    
    opt.c_cflag |= CS8;     
    opt.c_cflag &= ~CSTOPB;   
    opt.c_cflag &= ~PARENB;   
    opt.c_iflag &= ~INPCK;//opt.c_cflag &= ~INPCK;the last this is fetal set  
    opt.c_cflag |= (CLOCAL | CREAD);  
    opt.c_cflag &= ~CRTSCTS;
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
    opt.c_oflag &= ~OPOST;  
    opt.c_oflag &= ~(ONLCR | OCRNL);    //添加的  
    opt.c_iflag &= ~(ICRNL | INLCR);  
    opt.c_iflag &= ~(IXON | IXOFF | IXANY);    //添加的   
    opt.c_cc[VTIME] = 8;  
    opt.c_cc[VMIN] = 10;  
      
    tcflush(fd, TCIOFLUSH);  
   
    printf("configure complete\n");  
     
    if(tcsetattr(fd, TCSANOW, &opt) != 0)  
    {  
        perror("serial error");  
        return -1;  
    }   
    
    pthread_t id;
    pthread_create(&id,NULL,(void*)pthread_uartrecv,NULL);
  
    while(1)  
    {    
        sleep(2);
	printf("this is main function\n");
    }  
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值