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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值