1. 程式人生 > >linux c poll 串列埠讀資料例程

linux c poll 串列埠讀資料例程

epoll機制讀取linux串列埠資料

https://blog.csdn.net/coding__madman/article/details/51657944

com.c

#include "com.h"
 
int openSerial(char *cSerialName)
{
    int iFd;
 
    struct termios opt; 
 
    iFd = open(cSerialName, O_RDWR | O_NOCTTY |O_NONBLOCK);
	//iFd = open(cSerialName, O_RDWR | O_NOCTTY | O_NDELAY);//阻塞 |O_RSYNC
    if(iFd < 0) {
        perror(cSerialName);
        return -1;
    }
 
    tcgetattr(iFd, &opt);      
 
    cfsetispeed(&opt, B9600);
    cfsetospeed(&opt, B9600);
 
    
    /*
     * raw mode
     */
    opt.c_lflag   &=   ~(ECHO   |   ICANON   |   IEXTEN   |   ISIG);
    opt.c_iflag   &=   ~(BRKINT   |   ICRNL   |   INPCK   |   ISTRIP   |   IXON);
    opt.c_oflag   &=   ~(OPOST);
    opt.c_cflag   &=   ~(CSIZE   |   PARENB);
    opt.c_cflag   |=   CS8;
 
    /*
     * 'DATA_LEN' bytes can be read by serial
     */
    opt.c_cc[VMIN]   =   DATA_LEN;                                      
    opt.c_cc[VTIME]  =   150;
 
    if (tcsetattr(iFd,   TCSANOW,   &opt)<0) {
        return   -1;
    }
 
 
    return iFd;
}
 
 
int EpollInit(int cfd)
{
	epid = epoll_create(6);//放在初始化
	
	event.events = EPOLLET | EPOLLIN;
	event.data.fd = cfd;
	if (epoll_ctl(epid, EPOLL_CTL_ADD, cfd, &event) != 0) {//將讀事件新增到epoll的事件佇列中
		printf("set epoll error!\n");
		return 0;
	}
	printf("set epoll ok!\n");
	
	return 1;
}
 
int ComRead(char * ReadBuff,const int ReadLen)
{
	
	int read_len = 0;
	int len = 0;
 
	//下面開始epoll等待
	int i =0,witeNum= 0;
	while (1) 
	{
		witeNum = epoll_wait(epid, events, 1, 50);
		printf("witeNum0 = %d\n   ", witeNum);
		if( witeNum == 0)
				return 0;
		//printf("witeNum = %d\n", witeNum);
		
		for (i = 0; i < witeNum; i++) 
		{
 
			if ((events[i].events & EPOLLERR)
					|| (events[i].events & EPOLLHUP)
					|| (!(events[i].events & EPOLLIN))) 
			{
				printf("no data!\n");
				break;
			} 
			else if (events[i].events & EPOLLIN) 
			{//有資料進入  接受資料
				len = read(events[i].data.fd, ReadBuff, ReadLen);
				tcdrain(fd);
			    tcflush(fd,TCIOFLUSH);
 
				if(len != ReadLen) //如何保證每次都讀到這些位元組又不阻塞! 
				{
					bzero(ReadBuff,15);
				}
				
				if( len == ReadLen)
				 return len;
		 
			}
		}
	}
 
	return len ;
}
 

com.h

#ifndef _COM_H_
#define _COM_H_
 
#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 <limits.h> 
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/epoll.h> 
#include <string.h>
 
//#define MAXLEN 15
 
#define DATA_LEN                0xFF         
 
int fd;//檔案描述符
int epid; //epoll識別符號
struct epoll_event event;
struct epoll_event events[6];//事件集合
//char RecvBuff[MAXLEN];//接受到的資料
 
int ComRead(char * ReadBuff,const int ReadLen);//com口讀資料
int EpollInit(int cfd);
 
int  openSerial(char *cSerialName);
 
 
#endif

main.c

#include <stdio.h>
#include "com.h"
 
int main(void)
{
	char tmp[15] = {0};
	int rl;
	int write_len;
	char* text = ".P\r\n" ;
	int i;
 
	fd = openSerial("/dev/ttySP2");
	
	if(fd < 0)
	{
		printf("open com fail!\n");
		return 0;
	}
	
	EpollInit(fd);
	
	while(1)
	{
		bzero(tmp,sizeof(tmp));
	    tcflush(fd,TCIOFLUSH);//清空串列埠輸入輸出快取
		
		write_len = write(fd, text, strlen(".P\r\n"));//向串列埠傳送指令
		
		if(write_len != 4)
		{
			printf("write fail!\n");
			return 0;
		}
		
		rl = ComRead(tmp,8);//讀取8個位元組放到快取
         
		//列印讀到的資料
		printf("write_len = %d,  read_len = %d\n", write_len, rl);
		tmp[rl] = '\0';
		printf("read: %s\n", tmp);	
		for(i = 0; i < rl; i++)
			printf(" %d", tmp[i]);
		printf("\n\n");
		
		if(rl != 8)
		{
			printf("read fail!\n");
		}
	
	}
	
	close(epid);
	close(fd);
	
	return 0;
}