男生小便闪小机相片:linux 串口通讯
来源:百度文库 编辑:偶看新闻 时间:2024/04/29 14:44:18
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函数可能就是tcgetattr(3)和tcsetattr(3)。顾名思义,这两个函数分别用来取得设设置终端的属性。调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体:
termios结构体成员
控制选项
通过termios结构体的c_cflag成员可以控制波特率,数据的比特数,parity,停止位和硬件流控制。下面这张表列出了所有可以使用的常数。
c_cflag常数
在传统的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常量
不同的系统上可能支持不同的输入输出速度,所以,通过串口连接两台机器或者设备的时候,应该将波特率设置成两者中较小的那个,即MIN(speed1, speed2)。
设置字符大小
设置字符大小的时候,这里却没有像设置波特率那么方便的函数。所以,程序中需要一些位掩码运算来把事情搞定。字符大小以比特为单位指定:
options.c_flag &= ~CSIZE; /* Mask the character size bits */options.c_flag |= CS8; /* Select 8 da
设置奇偶校验
与设置字符大小的方式差不多,这里仍然需要组合一些位掩码来将奇偶校验设为有效和奇偶校验的类型。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 da
输出选项
成员变量c_oflag之中包括了输出过滤选项。和输入模式相似,程序可以选择使用经过加工的或者原始的数据输出。
c_oflag成员的常量
选择加工过的输出
通过在c_oflag成员变量中设置OPOST选项的方法程序可以选择加工过的输入。
options.c_oflag |= OPOST;
在所有选项当中,你可能只需要使用ON
选择原始输出
原始输出方式可以通过在c_oflag中重置OPOST选项来选择:
options.c_oflag &= ~OPOST;
如果OPOST选项被设置成无效的话,其他c_oflag中的选项都会失效。
控制字符
字符数组c_cc里面包括了控制字符的定义和超时参数。这个数组的每个元素都是以常量定义的。
成员变量c_cc中的控制字符
设置软件流控制字符
用来做软件流控制的字符包含在数组c_cc的VSTART和VSTOP元素里面。通常情况下,它们应该被设置成DC1(八进制021)和DC3(八进制023),它们在ASCII标准中代表着XON和XOFF字符。
设置读取超