您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > Linux串口select编程
Linux下串口程序开发串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是RS-232-C接口(又称EIARS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准该标准规定采用一个25个脚的DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于4%的情况下,传输电缆长度应为50英尺。在linux文件中,所有的设备文件一般都位于/dev下,其中串口一、串口二分别对应的设备名依次为“/dev/ttyS0”、“/dev/ttyS1”,可以查看在/dev下的文件以确认。在linux下面对于串口的读写就可以通过简单的read、write函数来完成,所不同的是只是需要对串口的其他参数另坐配置。1.串口编程需要用到的头文件#includestdio.h//标准输入输出定义#includestdlib.h#includefcntl.h//文件控制定义,主要完成串口通信中对文件的读写操作#includeunistd.h//linux标准函数定义#includesys/ioctl.h#includetermios.h//POSIX终端控制定义#includesys/time.h#includesys/types.h2.串口终端函数2.1打开串口设备intfd;char*device=/dev/tts/0;//设备路径,初始使用UART0for(t=1;targc;t++)//获取程序入口时输入的参数{if(!strcmp(argv[t],-d)&&(argc(t+1))){device=argv[t+1];}}if(!strcmp(device,/dev/tts/1))//不允许使用UART1,因为它已和PC相连。{printf(cannotuse/dev/tts/1\n);return-1;}fd=open(device,O_RDWR);//打开设备if(fd0)//设备打开失败{printf(opendeviceerror\n);return-1;}2.2设置串口最基本的串口设置包括波特率设置,校验位和停止位设置。实际上串口的设置只要是设置Structtermios()结构体中各成员的值。structtermio{unsignedshortc_iflag;/*输入模式标志*/unsignedshortc_oflag;/*输出模式标志*/unsignedshortc_cflag;/*控制模式标志*/unsignedshortc_lflag;/*localmodeflags*/unsignedcharc_line;/*linediscipline*/unsignedcharc_cc[NCC];/*controlcharacters*/};2.2.1波特率设置structtermiosOpt;tcgetattr(fd,&Opt);//得到当前串口的参数cfsetispeed(&Opt,B19200);/*设置为19200Bps*/cfsetospeed(&Opt,B19200);tcsetattr(fd,TCANOW,&Opt);//激活新配置设置波特率的例子函数:/***@brief设置串口通信速率*@paramfd类型int打开串口的文件句柄*@paramspeed类型int串口速度*@returnvoid*/intspeed_arr[]={B38400,B19200,B9600,B4800,B2400,B1200,B300,B38400,B19200,B9600,B4800,B2400,B1200,B300,};intname_arr[]={38400,19200,9600,4800,2400,1200,300,38400,19200,9600,4800,2400,1200,300,};voidset_speed(intfd,intspeed){inti;intstatus;structtermiosOpt;tcgetattr(fd,&Opt);for(i=0;isizeof(speed_arr)/sizeof(int);i++){if(speed==name_arr[i]){tcflush(fd,TCIOFLUSH);cfsetispeed(&Opt,speed_arr[i]);cfsetospeed(&Opt,speed_arr[i]);status=tcsetattr(fd1,TCSANOW,&Opt);if(status!=0){perror(tcsetattrfd1);return;}tcflush(fd,TCIOFLUSH);}}}2.2.2校验位和停止位设置/***@brief设置串口数据位,停止位和效验位*@paramfd类型int打开的串口文件句柄*@paramdatabits类型int数据位取值为7或者8*@paramstopbits类型int停止位取值为1或者2*@paramparity类型int效验类型取值为N,E,O,,S*/intset_Parity(intfd,intdatabits,intstopbits,intparity){structtermiosoptions;if(tcgetattr(fd,&options)!=0){//得到当前串口的参数perror(SetupSerial1);return(FALSE);}//设置字符大小options.c_cflag&=~CSIZE;switch(databits)/*设置数据位数*/{case7:options.c_cflag|=CS7;break;case8:options.c_cflag|=CS8;break;default:fprintf(stderr,Unsupporteddatasize\n);return(FALSE);}//设置奇偶校验位switch(parity){case'n'://无奇偶校验位case'N':options.c_cflag&=~PARENB;/*Clearparityenable*/break;case'o':case'O':options.c_cflag|=(PARODD|PARENB);/*设置为奇效验*/options.c_iflag|=INPCK;//INPCK:奇偶校验使能break;case'e':case'E':options.c_cflag|=PARENB;/*Enableparity*/options.c_cflag&=~PARODD;/*转换为偶效验*/options.c_iflag|=INPCK;/*Disnableparitychecking*/break;case'S'://Space校验case's':/*asnoparity*/options.c_cflag&=~PARENB;options.c_cflag&=~CSTOPB;options.c_iflag|=INPCK;break;default:fprintf(stderr,Unsupportedparity\n);return(FALSE);}//设置停止位switch(stopbits){case1:options.c_cflag&=~CSTOPB;//1个停止位break;case2:options.c_cflag|=CSTOPB;//2个停止位break;default:fprintf(stderr,Unsupportedstopbits\n);return(FALSE);}//处理未接收的字符tcflush(fd,TCIFLUSH);//设置等待时间和最小接收字符options.c_cc[VTIME]=150;/*设置超时15seconds*/options.c_cc[VMIN]=0;/*UpdatetheoptionsanddoitNOW*///激活新配置if(tcsetattr(fd,TCSANOW,&options)!=0){perror(SetupSerial3);return(FALSE);}return(TRUE);}2.2.3模式设置需要注意的是,如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(RawMode)方式来通信。newtio.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);//原始数据输入newtio.c_oflag&=~(OPOST);//原始数据输出2.2.4串口配置实例voidinit_ttyS(intfd){structtermiosnewtio;bzero(&newtio,sizeof(newtio));//得到当前串口的参数tcgetattr(fd,&newtio);//将输入波特率设为19200//将输出波特率设为19200cfsetispeed(&newtio,B19200);cfsetospeed(&newtio,B19200);//使能接收并使能本地状态newtio.c_cflag|=(CLOCAL|CREAD);//无校验8位数据位1位停止位newtio.c_cflag&=~PARENB;newtio.c_cflag&=~CSTOPB;newtio.c_cflag&=~CSIZE;//8个数据位newtio.c_cflag|=CS8;//原始数据输入newtio.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);newtio.c_oflag&=~(OPOST);//设置等待时间和最小接收字符数newtio.c_cc[VTIME]=0;newtio.c_cc[VMIN]=0;//处理未接收的字符tcflush(fd,TCIFLUSH);//激活新配置tcsetattr(fd,TCSANOW,&newtio);}2.1读串口读取串口数据使用文件操作read函数读取,如果设置为原始模式(RawMode)传输数据,那么read函数返回的字符数是实际串口收到的字符数。charbuff[1024];intLen;intreadByte=read(fd,buff,Len);可以使用操作文件的函数来实现异步读取,如fcntl,或者select等来操作。voidSERIAL_RX(void){//read(fd,RXBUF,RX_len);#if1intret,n,pos,retval;fd_setrfds;structtimevaltv;pos=0;//指向接收缓冲for(n=0;nRX_len;n++){RXBUF[n]=0xFF;}FD_ZERO(&rfds);//清空串口接收端口集FD_SET(fd,&rfds);//设置串口接收端口集tv.tv_sec=2;tv.tv_usec=0;while(FD_ISSET(fd,&rfds))//检测串口是否有读写动作{//每次循环都要清空,否则不会检测到有变化FD_ZERO(&rfds);//清空串口接收端口集FD_SET(fd,&rfds);//设置串口接收端口集retval=select(fd+1,&rfds,NULL,NULL,&tv);if(retval==-1){perror(select());break;}elseif(retval){//判断是否还有数据//sleep(2);ret=read(fd,RXBUF,RX_len);pos+=ret;//printf(ret=%d\n,ret);if((RXBUF[pos-2]=='\r')&(RXBUF[pos-1]=='\n'))//确实接收到了数据,并打印出来{FD_ZERO(&rfds);FD_SET(fd,&rfds);retval=select(fd+1,&rfds,NULL,NULL,&tv);if
本文标题:Linux串口select编程
链接地址:https://www.777doc.com/doc-2884740 .html