linux串口應用編程


linux串口應用編程



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

pthread_t pth1;
pthread_t pth2;
pthread_t pth3;

sem_t sem_r;//讀緩衝區res_buff[64]信號量
sem_t sem_w;//寫緩衝區res_buff[64]信號量

pthread_mutex_t event_lock;     //事件互斥鎖
pthread_mutex_t buf_lock; //緩衝區互斥鎖
pthread_cond_t event_ready; //事件條件變量
char res_buff[64];


/*******************************************************
//function :  打開串口設備函數
//parameter:  設備路徑
//return   :  文件描述符(fd)
********************************************************/
int Open_Uatr_Dev(const char *path)
{
	int fd;  //文件描述符

	//if((fd=open(path,O_RDWR|O_NDELAY|O_NOCTTY))<0)
	if((fd=open(path,O_RDWR|O_NOCTTY))<0)
	{
		perror("open serial failed!\n");
		return -1;
	}
	else
	{
		return fd;
	}

}


/*******************************************************
//function :  串口初始化函數
//parameter:  文件描述符,波特率,數據位,停止位,奇偶校驗位
//return   :  成功返回 0;失敗返回 -1
********************************************************/

int Set_Uart(int fd,int nSpeed,int nBits,char parity,int nStop )
{
	struct termios newtio,oldtio;
	if(tcgetattr(fd,&oldtio)!=0) //串口參數檢查
	{
		perror("tcgetattr error!\n");
		return -1;
	}
	bzero(&newtio,sizeof(newtio));

	/*設置控制模式*/
	newtio.c_cflag |= CLOCAL;//保證程序不佔用串口
	newtio.c_cflag |= CREAD; //保證程序可以從串口中讀取數據

	newtio.c_cflag &=  ~CSIZE;//屏蔽其它標誌位

	/*設置數據位*/	 
	switch(nBits)
	{
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
		default :
			perror("useless nBits!\n");
			return -1;
	}

	/*設置校驗位*/	 	 
	switch(parity) 
	{
		case 'o':
		case 'O':
			newtio.c_cflag |= PARENB; //產生奇偶位,執行奇偶校驗
			newtio.c_cflag |= PARODD; //若設置則爲奇校驗,否則爲偶校驗
			newtio.c_iflag |= INPCK;  //使奇偶校驗起作用
			break;
		case 'n':
		case 'N':    
			newtio.c_cflag &= ~PARENB;   /* Clear parity enable */
			newtio.c_iflag &= ~INPCK;    /* Enable parity checking */ 
			break; 
		case 'e':  
		case 'E':   
			newtio.c_cflag |= PARENB;    /* Enable parity */    
			newtio.c_cflag &= ~PARODD;   /* 轉換爲偶效驗*/     
			newtio.c_iflag |= INPCK;     /* Disnable parity checking */
			break;
		case 's': 
		case 'S':     
			newtio.c_cflag &= ~PARENB;
			newtio.c_cflag &= ~CSTOPB;
			break;  
		default:   
			perror("useless parity!\n");    
			return -1; 
	}

	/*設置波特率*/ 
	switch (nSpeed)
	{
		case 4800:
			cfsetispeed(&newtio,B4800);
			cfsetospeed(&newtio,B4800);
			break;
		case 9600:
			cfsetispeed(&newtio,B9600);
			cfsetospeed(&newtio,B9600);
			break;
		case 19200:
			cfsetispeed(&newtio,B19200);
			cfsetospeed(&newtio,B19200);
			break;
		case 38400:
			cfsetispeed(&newtio,B38400);
			cfsetospeed(&newtio,B38400);
			break;
		case 115200:
			cfsetispeed(&newtio,B115200);
			cfsetospeed(&newtio,B115200);
			break;
		default:
			perror("useless nSpeed!\n");
			return -1; 
	}

	/*設置停止位*/		 
	switch (nStop)
	{
		case 1:    
			newtio.c_cflag &= ~CSTOPB;  
			break;  
		case 2:    
			newtio.c_cflag |=  CSTOPB;  
			break;
		default:    
			perror("useless nStop!\n");  
			return -1; 
	}
	newtio.c_cc[VTIME] = 150; /* 設置超時15 seconds*/   
	newtio.c_cc[VMIN] = 0; /* Update the options and do it NOW */
	tcflush(fd,TCIFLUSH); //清空串口BUFF中的數據

	/*設置串口(將新配置的結構體newtio設置到串口中去) */
	if (tcsetattr(fd,TCSANOW,&newtio) != 0)   
	{ 
		perror("Setup Serial Failed!\n");   
		return -1;  
	}
	return 0;

}


/*******************************************************
//function : 串口發送函數
//parameter: const void *buf(待發送數據的內存地址) size (發送數據的大小)
//return   : -1(失敗)
********************************************************/

int  uart_send(int fd,const void *buf,int size)
{
	int  ret = 0;
	int  total = 0;
	assert(buf != NULL);//斷言,如果爲真,程序正常運行,爲假,程序退出,
	while (total != size) 
	{
		if ((ret = write(fd, buf + total, size - total))==-1)
		{
			perror("serial send failed\n");
			total = -1;
			break;
		} 
		else
			total += ret;
	}
	return total;	
}


/*******************************************************
//function : 串口接收函數
//parameter: const void *buf(待接收數據的內存地址)  size (接收數據的大小)
//return   : -1(失敗)
********************************************************/

int  uart_receive(int fd,void *buf,int size)
{
	int  ret = 0;
	int  total = 0;
	assert(buf != NULL);//斷言,如果爲真,程序正常運行,爲假,程序退出,
	while (1) 
	{
		
		if ((ret = read(fd, buf, size))==-1)
		{
			perror("serial read failed\n");
			return -1;
		} 
		else{
			if(!strlen(buf))
			{
				//printf("coming\n");
			}else{
				printf("buf = %s\n",buf);
				break;		
			}		
		}		
	}

}

/*******************************************************
//function :  串口讀線程處理函數(收到數據去填充緩衝區)
//parameter:  void * args
//return   :  void *
********************************************************/
void * receive_handle(void * args)
{
	int fd = *(int *)args; 

	while(1)
	{
	 sem_wait(&sem_w);
	 uart_receive(fd,(void *)res_buff,sizeof(res_buff));
	 sem_post(&sem_r);

	}
	pthread_exit(NULL);
}


/*******************************************************
//function :  緩衝區線程處理函數(當緩衝區填寫完畢,可以去讀緩衝區)
//parameter:  void * args
//return   :  void *
********************************************************/
void * read_buf_handle(void * args)
{
	while(1)
	{
		sem_wait(&sem_r);
	 	printf("res_buff = %s\n",res_buff);
		switch(res_buff[0])
		{
			case 0x11:
				pthread_mutex_lock(&buf_lock);
				pthread_cond_signal(&event_ready);
				pthread_mutex_unlock(&buf_lock);	
				break;
			default :
				break;
		}
		memset(res_buff, 0, sizeof(res_buff));	
		sem_post(&sem_w);
	}
	pthread_exit(NULL);	
}


/*******************************************************
//function :  事件線程處理函數(等待條件滿足纔會執行)
//parameter:  void * args
//return   :  void *
********************************************************/
void * event_handle(void * args)
{
		while(1)
		{
	
			pthread_mutex_lock(&event_lock);
			pthread_cond_wait(&event_ready,&event_lock);	
			printf("event_handle coming\n");	
			pthread_mutex_unlock(&event_lock);
		}
		pthread_exit(NULL); 
}

/*******************************************************
//function :  線程創建函數,
//parameter:  void 
//return   :  void 
********************************************************/
 void pthrea_prgress(void *args)
 {
	pthread_create(&pth2,NULL,read_buf_handle,NULL);
	sleep(1);
	pthread_create(&pth1,NULL,receive_handle,args);
	sleep(1);	
	pthread_create(&pth3,NULL,event_handle,NULL);
	sleep(1);	
 }

 /*******************************************************
//function :  信號量初始化函數,
//parameter:  int r_value,int w_value
//return   :  -1(失敗) 
********************************************************/
int semt_init(int r_value,int w_value)
{   
	int ret;
	ret = sem_init(&sem_w,0,w_value);
	if(ret < 0)
	{
		perror("sem_init_w");
		return -1;
	}
	ret = sem_init(&sem_r,0,r_value);
	if(ret < 0)
	{
		perror("sem_init_r");
		return -1;
	}
	return 0;
}

/*******************************************************
//function :  主函數,
//parameter:  int argc,char *argv[]
//return   :  0
********************************************************/

int main(int argc,char *argv[])
{   
	int uart_fd,ret;
	char buf[4]={0x11,0x22,0x33,0x44};
	char *psr="/dev/ttymxc1";
	uart_fd=Open_Uatr_Dev(psr); //打開串口設備
	if(Set_Uart(uart_fd,115200,8,'N',1)==-1)
	{
		perror("uart init failed\n");
		exit(1);
	}
	else{
		printf("uart init success\n");
	}
//互斥鎖初始化
	ret = pthread_mutex_init(&event_lock,NULL);
	if(ret != 0)
	{
		printf("pthread_mutex_init failed\n");
		exit(1);
	}

	ret = pthread_mutex_init(&buf_lock,NULL);
	if(ret != 0)
	{
		printf("pthread_mutex_init failed\n");
		exit(1);
	}
	
	
//條件變量初始化
	pthread_cond_init(&event_ready,NULL);
//信號量初始化
	
	ret = semt_init(0,1);
	if(ret < 0)
	{
		printf("semt_init_err\n");
		exit(1);
	}

	pthrea_prgress((void *)&uart_fd);
	
	while(1){
		pthread_join(pth2,NULL);
		pthread_join(pth1,NULL);
		pthread_mutex_destroy(&event_lock);
		pthread_mutex_destroy(&buf_lock);
        pthread_cond_destroy(&event_ready);
		break;
	}

	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章