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