最近使用了linux的串口,整理了一下应用程序调用的API,希望将来有用。
主要有两个文件SerDrive.h盒SerDrive.c
//=======================================================
SerDrive.h
#ifndef SERDRIVE_H #define SERDRIVE_H //======================= //串口名字 #define TTY0_NAME "/dev/ttySAC0" #define TTY1_NAME "/dev/ttySAC1" #define TTY2_NAME "/dev/ttySAC2" //串口 #define TTYS0 1 #define TTYS1 2 #define TTYS2 3 //波特率 #define BAUD_2400 2400 #define BAUD_4800 4800 #define BAUD_9600 9600 #define BAUD_115200 115200 #define BAUD_460800 460800 //奇偶校验位 #define PARITY_ODD 'O' //奇数 #define PARITY_EVEN 'E' //偶数 #define PARITY_NONE 'N' //无奇偶校验位 //停止位 #define STOP_BIT_1 1 #define STOP_BIT_2 2 //数据位 #define DATA_BIT_7 7 #define DATA_BIT_8 8 //======================================== //串口API /*打开串口函数*/ int open_port(int fd,int comport); //串口配置的函数 int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop); //从串口中读取数据 int read_datas_tty(int fd,char *rcv_buf,int TimeOut,int Len); //向串口传数据 int send_data_tty(int fd, char *send_buf,int Len); //============== #endif // SERDRIVE_H
//*****************************************************
SerDrive.c
#include "SerDrive.h" //=========================================== #include <stdio.h> /*标准输入输出定义*/ #include <stdlib.h> /*标准函数库定义*/ #include <unistd.h> /*Unix 标准函数定义*/ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /*文件控制定义*/ #include <termios.h> /*POSIX 终端控制定义*/ #include <errno.h> /*错误号定义*/ //============================================= #define DEVICE_TTYS 1 //============================================= /*打开串口函数*/ int open_port(int fd,int comport) { if (comport==1)//串口 1 { fd = open( TTY0_NAME, O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd){ perror("Can't Open Serial Port"); return(-1); } } else if(comport==2)//串口 2 { fd = open( TTY1_NAME, O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd){ perror("Can't Open Serial Port"); return(-1); } } else if (comport==3)//串口 3 { fd = open( TTY2_NAME, O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd){ perror("Can't Open Serial Port"); return(-1); } } /*恢复串口为阻塞状态*/ if(fcntl(fd, F_SETFL, 0)<0) printf("fcntl failed!\n"); else printf("fcntl=%d\n",fcntl(fd, F_SETFL,0)); /*测试是否为终端设备*/ if(isatty(STDIN_FILENO)==0) printf("standard input is not a terminal device\n"); else printf("isatty success!\n"); printf("fd-open=%d\n",fd); return fd; } //串口配置的函数 int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio,oldtio; /*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/ if ( tcgetattr( fd,&oldtio) != 0) { perror("SetupSerial 1"); return -1; } bzero( &newtio, sizeof( newtio ) ); /*步骤一,设置字符大小*/ newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; /*设置停止位*/ switch( nBits ) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } /*设置奇偶校验位*/ switch( nEvent ) { case 'O': //奇数 newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'E': //偶数 newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'N': //无奇偶校验位 newtio.c_cflag &= ~PARENB; break; } /*设置波特率*/ switch( nSpeed ) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; case 460800: cfsetispeed(&newtio, B460800); cfsetospeed(&newtio, B460800); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; } /*设置停止位*/ if( nStop == 1 ) newtio.c_cflag &= ~CSTOPB; else if ( nStop == 2 ) newtio.c_cflag |= CSTOPB; /*设置等待时间和最小接收字符*/ newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; /*处理未接收字符*/ tcflush(fd,TCIFLUSH); /*激活新配置*/ if((tcsetattr(fd,TCSANOW,&newtio))!=0) { perror("com set error"); return -1; } printf("set done!\n"); return 0; } //====================================================== //从串口中读取数据 int read_datas_tty(int fd,char *rcv_buf,int TimeOut,int Len) { int retval; fd_set rfds; struct timeval tv; int ret,pos; tv.tv_sec = TimeOut/1000;//set the rcv wait time tv.tv_usec = TimeOut%1000*1000;//100000us = 0.1s pos = 0; while(1){ FD_ZERO(&rfds); FD_SET(fd,&rfds); retval = select(fd+1,&rfds,NULL,NULL,&tv); if(retval ==-1) { perror("select()"); break; } else if(retval) { ret= read(fd,rcv_buf+pos,1); if(-1 == ret){ break; } pos++; if(Len <= pos){ break; } } else { break; } } return pos; } //向串口传数据 int send_data_tty(int fd, char *send_buf,int Len) { ssize_t ret; ret = write(fd,send_buf,Len); if (ret == -1) { printf ("write device %s error\n", DEVICE_TTYS); return -1; } return 1; }
//**********************************************************************
//调用例子
#include "SerDrive.h" //====================================== int SerFd = -1; void ProcessInit(int argc, char *argv[]) { /*打开串口函数*/ SerFd = open_port(SerFd,TTYS1); if(0 < SerFd){ set_opt(SerFd,BAUD_2400, DATA_BIT_8, PARITY_NONE, STOP_BIT_1); }else{ printf("open_port ERROR !\n"); } } int main ( int argc, char *argv[]) { int nTmp = 0; char Buf[1024]; ProcessInit(argc,argv); while(1){ //从串口中读取数据 nTmp = read_datas_tty(SerFd, Buf,100,1024); if(0<nTmp){ //printf("rcv len=%d,data:%s\n",nTmp,Buf); //向串口传数据 send_data_tty(SerFd, Buf,nTmp); } } }
参考:
Linux串口编程
http://www.cnblogs.com/feisky/archive/2010/05/21/1740893.html
linux 串口特别是接收
http://blog.csdn.net/xyyangkun/article/details/7333288
Linux 串口编程
http://archive.cnblogs.com/a/1864327/
linux read() 函数
http://blog.csdn.net/bnxf00000/article/details/6235071
linux串口的select读,Linux下用select查询串口数据
http://www.justwinit.cn/post/3446/