親測可用,移植時根據需求修改即可,轉載自:http://blog.csdn.net/w282529350/article/details/7378388
//串口相關的頭文件 #include<stdio.h> /*標準輸入輸出定義*/ #include<stdlib.h> /*標準函數庫定義*/ #include<unistd.h> /*Unix 標準函數定義*/ #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> /*文件控制定義*/ #include<termios.h> /*PPSIX 終端控制定義*/ #include<errno.h> /*錯誤號定義*/ #include<string.h> //宏定義 #define FALSE -1 #define TRUE 0 /******************************************************************* * 名稱: UART0_Open * 功能: 打開串口并返回串口設備文件描述 * 入口參數: fd :文件描述符 port :串口號(ttyS0,ttyS1,ttyS2) * 出口參數: 正確返回為1,錯誤返回為0 *******************************************************************/ int UART0_Open(int fd,char* port) { fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY); if (FALSE == fd) { perror("Can't Open Serial Port"); return(FALSE); } //恢復串口為阻塞狀態 if(fcntl(fd, F_SETFL, 0) < 0) { PRintf("fcntl failed!/n"); return(FALSE); } else { printf("fcntl=%d/n",fcntl(fd, F_SETFL,0)); } //測試是否為終端設備 if(0 == isatty(STDIN_FILENO)) { printf("standard input is not a terminal device/n"); return(FALSE); } else { printf("isatty success!/n"); } printf("fd->open=%d/n",fd); return fd; } /******************************************************************* * 名稱: UART0_Close * 功能: 關閉串口并返回串口設備文件描述 * 入口參數: fd :文件描述符 port :串口號(ttyS0,ttyS1,ttyS2) * 出口參數: void *******************************************************************/ void UART0_Close(int fd) { close(fd); } /******************************************************************* * 名稱: UART0_Set * 功能: 設置串口數據位,停止位和效驗位 * 入口參數: fd 串口文件描述符 * speed 串口速度 * flow_ctrl 數據流控制 * databits 數據位 取值為 7 或者8 * stopbits 停止位 取值為 1 或者2 * parity 效驗類型 取值為N,E,O,,S *出口參數: 正確返回為1,錯誤返回為0 *******************************************************************/ int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) { int i; int status; int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300}; int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300}; struct termios options; /*tcgetattr(fd,&options)得到與fd指向對象的相關參數,并將它們保存于options,該函數還可以測試配置是否正確,該串口是否可用等。若調用成功,函數返回值為0,若調用失敗,函數返回值為1. */ if( tcgetattr( fd,&options) != 0) { perror("SetupSerial 1"); return(FALSE); } //設置串口輸入波特率和輸出波特率 for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { cfsetispeed(&options, speed_arr[i]); cfsetospeed(&options, speed_arr[i]); } } //修改控制模式,保證程序不會占用串口 options.c_cflag |= CLOCAL; //修改控制模式,使得能夠從串口中讀取輸入數據 options.c_cflag |= CREAD; //設置數據流控制 switch(flow_ctrl) { case 0 ://不使用流控制 options.c_cflag &= ~CRTSCTS; break; case 1 ://使用硬件流控制 options.c_cflag |= CRTSCTS; break; case 2 ://使用軟件流控制 options.c_cflag |= IXON | IXOFF | IXANY; break; } //設置數據位 //屏蔽其他標志位 options.c_cflag &= ~CSIZE; switch (databits) { case 5 : options.c_cflag |= CS5; break; case 6 : options.c_cflag |= CS6; break; case 7 : options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size/n"); return (FALSE); } //設置校驗位 switch (parity) { case 'n': case 'N': //無奇偶校驗位。 options.c_cflag &= ~PARENB; options.c_iflag &= ~INPCK; break; case 'o': case 'O'://設置為奇校驗 options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; break; case 'e': case 'E'://設置為偶校驗 options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; break; case 's': case 'S': //設置為空格 options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity/n"); return (FALSE); } // 設置停止位 switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits/n"); return (FALSE); } //修改輸出模式,原始數據輸出 options.c_oflag &= ~OPOST; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //options.c_lflag &= ~(ISIG | ICANON); //設置等待時間和最小接收字符 options.c_cc[VTIME] = 1; /* 讀取一個字符等待1*(1/10)s */ options.c_cc[VMIN] = 1; /* 讀取字符的最少個數為1 */ //如果發生數據溢出,接收數據,但是不再讀取 刷新收到的數據但是不讀 tcflush(fd,TCIFLUSH); //激活配置 (將修改后的termios數據設置到串口中) if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("com set error!/n"); return (FALSE); } return (TRUE); } /******************************************************************* * 名稱: UART0_Init() * 功能: 串口初始化 * 入口參數: fd : 文件描述符 * speed : 串口速度 * flow_ctrl 數據流控制 * databits 數據位 取值為 7 或者8 * stopbits 停止位 取值為 1 或者2 * parity 效驗類型 取值為N,E,O,,S * * 出口參數: 正確返回為1,錯誤返回為0 *******************************************************************/ int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity) { int err; //設置串口數據幀格式 if (UART0_Set(fd,19200,0,8,1,'N') == FALSE) { return FALSE; } else { return TRUE; } } /******************************************************************* * 名稱: UART0_Recv * 功能: 接收串口數據 * 入口參數: fd :文件描述符 * rcv_buf :接收串口中數據存入rcv_buf緩沖區中 * data_len :一幀數據的長度 * 出口參數: 正確返回為1,錯誤返回為0 *******************************************************************/ int UART0_Recv(int fd, char *rcv_buf,int data_len) { int len,fs_sel; fd_set fs_read; struct timeval time; FD_ZERO(&fs_read); FD_SET(fd,&fs_read); time.tv_sec = 10; time.tv_usec = 0; //使用select實現串口的多路通信 fs_sel = select(fd+1,&fs_read,NULL,NULL,&time); printf("fs_sel = %d/n",fs_sel); if(fs_sel) { len = read(fd,rcv_buf,data_len); printf("I am right!(version1.2) len = %d fs_sel = %d/n",len,fs_sel); return len; } else { printf("Sorry,I am wrong!"); return FALSE; } } /******************************************************************** * 名稱: UART0_Send * 功能: 發送數據 * 入口參數: fd :文件描述符 * send_buf :存放串口發送數據 * data_len :一幀數據的個數 * 出口參數: 正確返回為1,錯誤返回為0 *******************************************************************/ int UART0_Send(int fd, char *send_buf,int data_len) { int len = 0; len = write(fd,send_buf,data_len); if (len == data_len ) { printf("send data is %s/n",send_buf); return len; } else { tcflush(fd,TCOFLUSH); return FALSE; } } int main(int argc, char **argv) { int fd; //文件描述符 int err; //返回調用函數的狀態 int len; int i; char rcv_buf[100]; //char send_buf[20]="tiger john"; char send_buf[20]="tiger john"; if(argc != 3) { printf("Usage: %s /dev/ttySn 0(send data)/1 (receive data) /n",argv[0]); return FALSE; } fd = UART0_Open(fd,argv[1]); //打開串口,返回文件描述符 do { err = UART0_Init(fd,19200,0,8,1,'N'); printf("Set Port Exactly!/n"); }while(FALSE == err || FALSE == fd); if(0 == strcmp(argv[2],"0")) { for(i = 0;i < 10;i++) { len = UART0_Send(fd,send_buf,10); if(len > 0) printf(" %d time send %d data successful/n",i,len); else printf("send data failed!/n"); sleep(2); } UART0_Close(fd); } else { while (1) //循環讀取數據 { len = UART0_Recv(fd, rcv_buf,99); if(len > 0) { rcv_buf[len] = '/0'; printf("receive data is %s/n",rcv_buf); printf("len = %d/n",len); } else { printf("cannot receive data/n"); } sleep(2); } UART0_Close(fd); } }
新聞熱點
疑難解答