1、Linux串口编程Linux串口编程1.串口操作需要的头文件#include /标准输入输出定义#include /标准函数库定义#include /Unix标准函数定义#include #include #include /文件控制定义#include /POSIX中断控制定义#include /错误号定义2.打开串口串口位于/dev中,可作为标准文件的形式打开,其中:串口1/dev/ttyS0串口2/dev/ttyS1代码如下:intfd;fd=open(“/dev/ttyS0”,O_RDWR);if(fd=-1)Perror(“串口1打开失败!”);/else/fcntl(fd,F_SE
2、TFL,FNDELAY);除了使用O_RDWR标志之外,通常还会使用O_NOCTTY和O_NDELAY这两个标志。O_NOCTTY:告诉Unix这个程序不想成为“控制终端”控制的程序,不说明这个标志的话,任何输入都会影响你的程序。O_NDELAY:告诉Unix这个程序不关心DCD信号线状态,即其他端口是否运行,不说明这个标志的话,该程序就会在DCD信号线为低电平时停止。3.设置波特率最基本的串口设置包括波特率、校验位和停止位设置,且串口设置主要使用termios.h头文件中定义的termios结构,如下:struct termiostcflag_tc_iflag;/输入模式标志tcflag_t
3、c_oflag;/输出模式标志tcflag_tc_cflag;/控制模式标志tcflag_tc_lflag; /本地模式标志cc_tc_line; /line disciplinecc_tc_ccNCC;/control characters代码如下: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
4、,1200,300,;voidSetSpeed(intfd,intspeed)inti;structtermiosOpt;/定义termios结构if(tcgetattr(fd,&Opt)!=0)perror(“tcgetattrfd”);return;for(i=0;isizeof(speed_arr)/sizeof(int);i+)if(speed=name_arri)tcflush(fd,TCIOFLUSH);cfsetispeed(&Opt,speed_arri);cfsetospeed(&Opt,speed_arri);if(tcsetattr(fd,TCSANOW,&Opt)!=0
5、)perror(“tcsetattrfd”);return;tcflush(fd,TCIOFLUSH);注意tcsetattr函数中使用的标志:TCSANOW:立即执行而不等待数据发送或者接受完成。TCSADRAIN:等待所有数据传递完成后执行。TCSAFLUSH:Flush input and output buffers and make the change4.设置数据位、停止位和校验位以下是几个数据位、停止位和校验位的设置方法:(以下均为1位停止位)8位数据位、无校验位:Opt.c_cflag &= PARENB;Opt.c_cflag &= CSTOPB;Opt.c_cflag &=
6、 CSIZE;Opt.c_cflag |= CS8;7位数据位、奇校验:Opt.c_cflag |= PARENB;Opt.c_cflag |= PARODD;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;7位数据位、偶校验:Opt.c_cflag |= PARENB;Opt.c_cflag &= PARODD;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;7位数据位、Space校验:Opt.c_cflag &= PARENB;Opt.c_
7、cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;代码如下:intSetParity(intfd,intdatabits,intstopbits,intparity)structtermiosOpt;if(tcgetattr(fd,&Opt)!=0)perror(tcgetattrfd);returnFALSE;Opt.c_cflag|=(CLOCAL|CREAD);/一般必设置的标志switch(databits)/设置数据位数case7:Opt.c_cflag&=CSIZE;Opt.c_cflag|=CS7;break;case
8、8:Opt.c_cflag&=CSIZE;Opt.c_cflag|=CS8;berak;default:fprintf(stderr,Unsupporteddatasize.n);returnFALSE;switch(parity)/设置校验位casen:caseN:Opt.c_cflag&=PARENB;/清除校验位Opt.c_iflag&=INPCK;/enableparitycheckingbreak;caseo:caseO:Opt.c_cflag|=PARENB;/enableparityOpt.c_cflag|=PARODD;/奇校验Opt.c_iflag|=INPCK/disabl
9、eparitycheckingbreak;casee:caseE:Opt.c_cflag|=PARENB;/enableparityOpt.c_cflag&=PARODD;/偶校验Opt.c_iflag|=INPCK;/disablepairtycheckingbreak;cases:caseS:Opt.c_cflag&=PARENB;/清除校验位Opt.c_cflag&=CSTOPB;/?Opt.c_iflag|=INPCK;/disablepairtycheckingbreak;default:fprintf(stderr,Unsupportedparity.n);returnFALSE;
10、switch(stopbits)/设置停止位case1:Opt.c_cflag&=CSTOPB;break;case2:Opt.c_cflag|=CSTOPB;break;default:fprintf(stderr,Unsupportedstopbits.n);returnFALSE;opt.c_cflag|=(CLOCAL|CREAD);opt.c_lflag&=(ICANON|ECHO|ECHOE|ISIG);opt.c_oflag&=OPOST;opt.c_oflag&=(ONLCR|OCRNL);/添加的opt.c_iflag&=(ICRNL|INLCR);opt.c_iflag&=
11、(IXON|IXOFF|IXANY);/添加的tcflush(fd,TCIFLUSH);Opt.c_ccVTIME=0;/设置超时为15secOpt.c_ccVMIN=0;/UpdatetheOptanddoitnowif(tcsetattr(fd,TCSANOW,&Opt)!=0)perror(tcsetattrfd);returnFALSE;returnTRUE;5.某些设置项在第四步中我们看到一些比较特殊的设置,下面简述一下他们的作用。c_cc数组的VSTART和VSTOP元素被设定成DC1和DC3,代表ASCII标准的XON和XOFF字符,如果在传输这两个字符的时候就传不过去,需要把软
12、件流控制屏蔽,即:Opt.c_iflag &= (IXON | IXOFF | IXANY);有时候,在用write发送数据时没有键入回车,信息就发送不出去,这主要是因为我们在输入输出时是按照规范模式接收到回车或换行才发送,而更多情况下我们是不必键入回车或换行的。此时应转换到行方式输入,不经处理直接发送,设置如下:Opt.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);还存在这样的情况:发送字符0X0d的时候,往往接收端得到的字符是0X0a,原因是因为在串口设置中c_iflag和c_oflag中存在从NL-CR和CR-NL的映射,即串口能把回车和换行当成同一
13、个字符,可以进行如下设置屏蔽之:Opt.c_iflag &= (INLCR | ICRNL | IGNCR);Opt.c_oflag &= (ONLCR | OCRNL);6.读写串口发送数据方式如下,write函数将返回写的位数或者当错误时为-1。char buffer1024;int length;int nByte;nByte = write(fd, buffer, length);读取数据方式如下,原始数据模式下每个read函数将返回实际串口收到的字符数,如果串口中没有字符可用,回叫将会阻塞直到以下几种情况:有字符进入;一个间隔计时器失效;错误发送。在打开串口成功后,使用fcntl(f
14、d, F_SETFL, FNDELAY)语句,可以使read函数立即返回而不阻塞。FNDELAY选项使read函数在串口无字符时立即返回且为0。char buffer1024;int length;int readByte;readByte = read(fd, buffer, len);注意:设置为原始模式传输数据的话,read函数返回的字符数是实际串口收到的字符数。Linux下直接用read读串口可能会造成堵塞,或者数据读出错误,此时可使用tcntl或者select等函数实现异步读取。用select先查询com口,再用read去读就可以避免上述错误。7.关闭串口串口作为文件来处理,所以一般
15、的关闭文件函数即可:close(fd);8.例子这个例子中,需要打开串口1,设置9600波特率、8位数据位、1位停止位以及空校验,之后利用while语句循环判断串口中是否可以读出数据,将串口中数据连续读出后重新写回到串口中。该程序可与minicom联合测试。#include#include#include#include#include#include#include#includemain()intfd;inti;intlen;intn=0;charread_buf256;charwrite_buf256;structtermiosopt;fd=open(/dev/ttyS0,O_RDWR|
16、O_NOCTTY);/默认为阻塞读方式if(fd=-1)perror(openserial0n);exit(0);tcgetattr(fd,&opt);cfsetispeed(&opt,B9600);cfsetospeed(&opt,B9600);if(tcsetattr(fd,TCSANOW,&opt)!=0)perror(tcsetattrerror);return-1;opt.c_cflag&=CSIZE;opt.c_cflag|=CS8;opt.c_cflag&=CSTOPB;opt.c_cflag&=PARENB;opt.c_cflag&=INPCK;opt.c_cflag|=(CL
17、OCAL|CREAD);opt.c_lflag&=(ICANON|ECHO|ECHOE|ISIG);opt.c_oflag&=OPOST;opt.c_oflag&=(ONLCR|OCRNL);/添加的opt.c_iflag&=(ICRNL|INLCR);opt.c_iflag&=(IXON|IXOFF|IXANY);/添加的opt.c_ccVTIME=0;opt.c_ccVMIN=0;tcflush(fd,TCIOFLUSH);printf(configurecompleten);if(tcsetattr(fd,TCSANOW,&opt)!=0)perror(serialerror);retu
18、rn-1;printf(startsendandreceivedatan);while(1)n=0;len=0;bzero(read_buf,sizeof(read_buf);/类似于memsetbzero(write_buf,sizeof(write_buf);while(n=read(fd,read_buf,sizeof(read_buf)0)for(i=len;i(len+n);i+)write_bufi=read_bufi-len;len+=n;write_buflen=0;printf(Len%dn,len);printf(%sn,write_buf);n=write(fd,writ
19、e_buf,len);printf(write%dcharsn,n);sleep(2);9.附录c_cflag用于设置控制参数,除了波特率外还包含以下内容: EXTAExternal rate clockEXTBExternal rate clockCSIZEBit mask for data bitsCS55个数据位CS66个数据位CS77个数据位CS88个数据位CSTOPB2个停止位(清除该标志表示1个停止位PARENB允许校验位PARODD使用奇校验(清除该标志表示使用偶校验)CREADEnable receiverHUPCLHangup (drop DTR) on last close
20、CLOCALLocal line do not change “owner” of portLOBLKBlock job control outpuc_cflag标志可以定义CLOCAL和CREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCAL和CREAD通常总是被是能的。c_lflag用于设置本地模式,决定串口驱动如何处理输入字符,设置内容如下:ISIGEnable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals ICANONEnable canonical input (else raw) XCASEM
21、ap uppercase lowercase (obsolete) ECHOEnable echoing of input characters ECHOEEcho erase character as BS-SP-BS ECHOKEcho NL after kill character ECHONLEcho NL NOFLSHDisable flushing of input buffers after interrupt or quit characters IEXTENEnable extended functions ECHOCTLEcho control characters as
22、char and delete as ? ECHOPRTEcho erased character as character erased ECHOKEBS-SP-BS entire line on line kill FLUSHOOutput being flushed PENDINRetype pending input at next read or input char TOSTOPSend SIGTTOU for background outputc_iflag用于设置如何处理串口上接收到的数据,包含如下内容:INPCKEnable parity check IGNPARIgnore parity errors PARMRKMark parity errors ISTRIPStrip parity bits IXONEnable software flow control (outgoing) IXOFFEnable software flow control (incoming) IXANYAllow any character
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1