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