王者荣耀all扁鹊:linux 串口通讯

来源:百度文库 编辑:中财网 时间:2024/04/30 02:08:21

linux 串口通讯  

2010-03-11 20:18:03|  分类: 转载 |  标签:termios  串口  属性  c_oflag  c_iflag  linux   |字号大中小 订阅

配置串口

POSIX终端接口

POSIX

POSIX是Portable Operating System Interface(可移植操作系统界面)的缩写,而X则表明其对Unix API的传承。WindowsNT和现代UNIX都支持POSIX接口。

很多系统都支持POSIX终端(串口)接口。程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等。要使用这个端口的话,你必须将头文件包含到你的程序中。这个头文件中定义了终端控制结构体和POSIX控制函数。

与串口操作相关的最重要的两个POSIX函数可能就是tcgetattr(3)和tcsetattr(3)。顾名思义,这两个函数分别用来取得设设置终端的属性。调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体:

termios结构体成员

成员 描述 c_cflag 控制选项 c_lflag 行选项 c_iflag 输入选项 c_oflag 输出选项 c_cc 控制字符 c_ispeed 输入波特率(NEW) c_ospeed 输出波特率(NEW)

控制选项

通过termios结构体的c_cflag成员可以控制波特率,数据的比特数,parity,停止位和硬件流控制。下面这张表列出了所有可以使用的常数。

c_cflag常数

常量 描述 CBAUD Bit mask for baud rate B0 0 baud (drop DTR) B50 50 baud B75 75 baud B110 110 baud B134 134.5 baud B150 150 baud B200 200 baud B300 300 baud B600 600 baud B1200 1200 baud B1800 1800 baud B2400 2400 baud B4800 4800 baud B9600 9600 baud B19200 19200 baud B38400 38400 baud B57600 57,600 baud B76800 76,800 baud B115200 115,200 baud EXTA External rate clock EXTB External rate clock CSIZE Bit mask for data bits CS5 5 data bits CS6 6 data bits CS7 7 data bits CS8 8 data bits CSTOPB 2 stop bits (1 otherwise) CREAD Enable receiver PARENB Enable parity bit PARODD Use odd parity instead of even HUPCL Hangup (drop DTR) on last close CLOCAL Local line - do not change "owner" of port LOBLK Block job control output CNEW_RTSCTS/CRTSCTS Enable hardware flow control (not supported on all platforms)

在传统的POSIX编程中,当连接一个本地的(不通过调制解调器)或者远程的终端(通过调制解调器)时,这里有两个选项应当一直打开,一个是CLOCAL,另一个是CREAD。这两个选项可以保证你的程序不会变成端口的所有者,而端口所有者必须去处理发散性作业控制和挂断信号,同时还保证了串行接口驱动会读取过来的数据字节。

发散性作业控制和信号

这个名词非常难以理解。但现在大多数的串口编程都已经脱离了终端本身,一般不会发生这里提到的情况,详细的说明请参看这里。

波特率常数(CBAUD,B9600等等)通常指用到那些不支持c_ispeed和c_ospeed成员的旧的接口上。后面文章将会提到如何使用其他POSIX函数来设置波特率。

千万不要直接用使用数字来初始化c_cflag(当然还有其他标志),最好的方法是使用位运算的与或非组合来设置或者清除这个标志。不同的操作系统版本会使用不同的位模式,使用常数定义和位运算组合来避免重复工作从而提高程序的可移植性。

设置波特率

不同的操作系统会将波特率存储在不同的位置。旧的编程接口将波特率存储在上表所示的c_cflag成员中,而新的接口实装则提供了c_ispeed和c_ospeed成员来保存实际波特率的值。

程序中可是使用cfsetospeed(3)和cfsetispeed(3)函数在termios结构体中设置波特率而不用去管底层操作系统接口。下面的代码是个非常典型的设置波特率的例子。

struct termios options;/* * Get the current options for the port... */tcgetattr(fd, &options);/* * Set the baud rates to 19200... */cfsetispeed(&options, B19200);cfsetospeed(&options, B19200);/* * Enable the receiver and set local mode... */options.c_cflag |= (CLOCAL | CREAD);/* * Set the new options for the port... */tcsetattr(fd, TCSANOW, &options);

函数tcgetattr(3)会将当前串口配置回填到termio结构体option中。然后,程序设置了输入输出的波特率并且将本地模式(CLOCAL)和串行数据接收(CREAD)设置为有效,接着将新的配置作为参数传递给函数tcsetattr(3)。常量TCSANOW标志所有改变必须立刻生效而不用等到数据传输结束。其他另一些常数可以保证等待数据结束或者刷新输入输出之后再生效。

tcsetattr常量

常量 描述 TCSANOW Make changes now without waiting for data to complete TCSADRAIN Wait until everything has been transmitted TCSAFLUSH Flush input and output buffers and make the change

不同的系统上可能支持不同的输入输出速度,所以,通过串口连接两台机器或者设备的时候,应该将波特率设置成两者中较小的那个,即MIN(speed1, speed2)。

设置字符大小

设置字符大小的时候,这里却没有像设置波特率那么方便的函数。所以,程序中需要一些位掩码运算来把事情搞定。字符大小以比特为单位指定:

options.c_flag &= ~CSIZE; /* Mask the character size bits */options.c_flag |= CS8; /* Select 8 data bits */

设置奇偶校验

与设置字符大小的方式差不多,这里仍然需要组合一些位掩码来将奇偶校验设为有效和奇偶校验的类型。UNIX串口驱动可以生成even,odd和no parity位码。设置space奇偶校验需要耍点小手段。

  • No parity (8N1)

options.c_cflag &= ~PARENBoptions.c_cflag &= ~CSTOPBoptions.c_cflag &= ~CSIZE;options.c_cflag |= CS8;

  • Even parity (7E1)

options.c_cflag |= PARENBoptions.c_cflag &= ~PARODDoptions.c_cflag &= ~CSTOPBoptions.c_cflag &= ~CSIZE;options.c_cflag |= CS7;

  • Odd parity (7O1)

options.c_cflag |= PARENBoptions.c_cflag |= PARODDoptions.c_cflag &= ~CSTOPBoptions.c_cflag &= ~CSIZE;options.c_cflag |= CS7;

  • Space parity is setup the same as no parity (7S1)

options.c_cflag &= ~PARENBoptions.c_cflag &= ~CSTOPBoptions.c_cflag &= ~CSIZE;options.c_cflag |= CS8;

设置硬件流控制

某些版本的UNIX系统支持通过CTS(Clear To Send)和RTS(Request To Send)信号线来设置硬件流控制。如果系统上定义了CNEW_RTSCTS和CRTSCTS常量,那么很可能它会支持硬件流控制。使用下面的方法将硬件流控制设置成有效:

options.c_cflag |= CNEW_RTSCTS; /* Also called CRTSCTS

将它设置成为无效的方法与此类似:

options.c_cflag &= ~CNEW_RTSCTS;

本地设置

经典输入

经典输入是终端中最常用的输入方式。但它同样适用于其他以行为单位的通讯方式,也就是说这种方式中另一端的“读取”只会返回一整行的输入。默认情况下,一行总是以NL(ASCII LF),EOF(End of File)或者EOL(End Of Line)结尾。默认设置中,CR(DOS/Windows默认的EOL)字符不能用来结束一行。经典输入处理过程一般情况也可以处理擦写,删除字和重新打印字符,将CR翻译成NL等任务。

本地模式成员变量c_lflag可以控制串口驱动怎样控制输入字符。通常,你可能需要通过c_lflag成员来设置经典输入和原始输入模式。

成员变量c_lflag可以使用的常量

ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals ICANON Enable canonical input (else raw) XCASE Map uppercase \lowercase (obsolete) ECHO Enable echoing of input characters ECHOE Echo erase character as BS-SP-BS ECHOK Echo NL after kill character ECHONL Echo NL NOFLSH Disable flushing of input buffers after interrupt or quit characters IEXTEN Enable extended functions ECHOCTL Echo control characters as ^char and delete as ~? ECHOPRT Echo erased character as character erased ECHOKE BS-SP-BS entire line on line kill FLUSHO Output being flushed PENDIN Retype pending input at next read or input char TOSTOP Send SIGTTOU for background output

选择经典输入

不要使用ECHO

当通过串口给一个调制解调器或者计算机发送命令的时候,永远不要使用回声选项(ECHO,ECHOE),这样的话程序会产生发送方和接收方相互反馈循环!

经典输入是以面向行设计的。在经典输入模式中输入字符会被放入一个缓冲之中,这样可以以与用户交互的方式编辑缓冲的内容,直到收到CR(carriage return)或者LF(line feed)字符。

选择使用经典输入模式的时候,你通常需要选择ICANON,ECHO和ECHOE选项:

options.c_lflag |= (ICANON | ECHO | ECHOE);

选择原始输入

原始输入根本不会被处理。输入字符只是被原封不动的接收。一般情况中,如果要使用原始输入模式,程序中需要去掉ICANON,ECHO,ECHOE和ISIG选项:

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

输入选项

可以通过输入模式成员c_iflag来控制从端口上收到的字符的输入过程。与c_cflag一样,c_iflag的最终值是想要使用的所有状态的位运算OR的组合。

c_iflag成员可以使用的常量

常量 描述 INPCK Enable parity check IGNPAR Ignore parity errors PARMRK Mark parity errors ISTRIP Strip parity bits IXON Enable software flow control (outgoing) IXOFF Enable software flow control (incoming) IXANY Allow any character to start flow again IGNBRK Ignore break condition BRKINT Send a SIGINT when a break condition is detected INLCR Map NL to CR IGNCR Ignore CR ICRNL Map CR to NL IUCLC Map uppercase to lowercase IMAXBEL Echo BEL on input line too long

设置输入奇偶校验选项

当程序在c_cflag中设置了奇偶校验成员(PARENB)的时候,程序就需要将输入奇偶校验设置成为有效。与奇偶校验相关的常量有INPCK,IGNPAR,PARMRK和ISTRIP。一般情况下,你可能需要选择INPCK和ISTRIP将奇偶校验设置为有效同时从接收字串中脱去奇偶校验位:

options.c_iflag |= (INPCK | ISTRIP);

IGNPAR是一个比较危险选项,即便有错误发生时,它也会告诉串口驱动直接忽略奇偶校验错误给数据放行。这个选项在测试链接的通讯质量时比较有用而通常不会被用在实际程序中。

PARMRK会导致奇偶校验错误被标志成特殊字符加入到输入流之中。如果IGNPAR选项也是有效的,那么一个NUL(八进制000)字符会被加入到发生奇偶校验错误的字符前面。否则,DEL(八进制177)和NUL字符会和出错的字符一起送出。

设置软件流控制

软件流控制可以通过IXON,IXOFF和IXANY常量设置成有效:

options.c_iflag |= (IXON | IXOFF | IXANY);

将其设置为无效的时候,很简单,只需要对这些位取反:

options.c_iflag &= ~(IXON | IXOFF | IXANY);

XON(start data)和XOFF(stop data)字符却是在c_cc数组中定义的,下面会详细描述这个数组。

输出选项

成员变量c_oflag之中包括了输出过滤选项。和输入模式相似,程序可以选择使用经过加工的或者原始的数据输出。

c_oflag成员的常量

常量 描述 OPOST Postprocess output (not set = raw output) OLCUC Map lowercase to uppercase ONLCR Map NL to CR-NL OCRNL Map CR to NL NOCR No CR output at column 0 ONLRET NL performs CR function OFILL Use fill characters for delay OFDEL Fill character is DEL NLDLY Mask for delay time needed between lines NL0 No delay for NLs NL1 Delay further output after newline for 100 milliseconds CRDLY Mask for delay time needed to return carriage to left column CR0 No delay for CRs CR1 Delay after CRs depending on current column position CR2 Delay 100 milliseconds after sending CRs CR3 Delay 150 milliseconds after sending CRs TABDLY Mask for delay time needed after TABs TAB0 No delay for TABs TAB1 Delay after TABs depending on current column position TAB2 Delay 100 milliseconds after sending TABs TAB3 Expand TAB characters to spaces BSDLY Mask for delay time needed after BSs BS0 No delay for BSs BS1 Delay 50 milliseconds after sending BSs VTDLY Mask for delay time needed after VTs VT0 No delay for VTs VT1 Delay 2 seconds after sending VTs FFDLY Mask for delay time needed after FFs FF0 No delay for FFs FF1 Delay 2 seconds after sending FFs

选择加工过的输出

通过在c_oflag成员变量中设置OPOST选项的方法程序可以选择加工过的输入。

options.c_oflag |= OPOST;

在所有选项当中,你可能只需要使用ONLCR选项来将行分隔符映射到CR-LF组合对上。其他选项主要是历史遗留,仅仅与行打印机和终端跟不上串行数据的年代有关。

选择原始输出

原始输出方式可以通过在c_oflag中重置OPOST选项来选择:

options.c_oflag &= ~OPOST;

如果OPOST选项被设置成无效的话,其他c_oflag中的选项都会失效。

控制字符

字符数组c_cc里面包括了控制字符的定义和超时参数。这个数组的每个元素都是以常量定义的。

成员变量c_cc中的控制字符

常量 描述 键 VINTR Interrupt CTRL-C VQUIT Quit CTRL-Z VERASE Erase Backspace (BS) VKILL Kill-line CTRL-U VEOF End-of-file CTRL-D VEOL End-of-line Carriage return (CR) VEOL2 Second end-of-line Line feed (LF) VMIN Minimum number of characters to read - VSTART Start flow CTRL-Q (XON) VSTOP Stop flow CTRL-S (XOFF) VTIME Time to wait for data (tenths of seconds) -

设置软件流控制字符

用来做软件流控制的字符包含在数组c_cc的VSTART和VSTOP元素里面。通常情况下,它们应该被设置成DC1(八进制021)和DC3(八进制023),它们在ASCII标准中代表着XON和XOFF字符。

设置读取超