浅谈linux下的串口通讯开发
<p>串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。串口通讯指的是计算机依次以位(bit)为单位来传送数据,串行通讯使用的范围很广,在嵌入式系统开发过程中串口通讯也经常用到通讯方式之一。</p><p>Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口设备。在linux系统下面,每一个串口设备都有设备文件与其关联,设备文件位于系统的/dev目录下面。如linux下的/ttyS0,/ttyS1分别表示的是串口1和串口2。下面来详细介绍linux下是如何使用串口的:</p>
<p><span><strong>1. 串口操作需要用到的头文件</strong></span></p>
<p>#include /*标准输入输出定义*/</p>
<p>#include /*标准函数库定义*/</p>
<p>#include /*Unix 标准函数定义*/</p>
<p>#include</p>
<p>#include</p>
<p>#include /*文件控制定义*/</p>
<p>#include /*POSIX 终端控制定义*/</p>
<p>#include /*错误号定义*/</p>
<p>#include /*字符串功能函数*/</p>
<p><span><strong>2. 串口通讯波特率设置</strong></span></p>
<p>波特率的设置定义在,其包含在头文件里。</p>
<p>常用的波特率常数如下:</p>
<p>B0-------à0 B1800-------à1800</p>
<p>B50-----à50 B2400------à2400</p>
<p>B75-----à75 B4800------à4800</p>
<p>B110----à110 B9600------à9600</p>
<p>B134----à134.5 B19200-----à19200</p>
<p>B200----à200 B38400------à38400</p>
<p>B300----à300 B57600------à57600</p>
<p>B600----à600 B76800------à76800</p>
<p>B1200---à1200 B115200-----à115200</p>
<p>假定程序中想要设置通讯的波特率,使用cfsetispeed( )和cfsetospeed( )函数来操作,获取波特率信息是通过cfgetispeed()和cfgetospeed()函数来完成的。比如可以这样来指定串口通讯的波特率:</p>
<div class="jb51code">
<div><div id="highlighter_885976" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include //头文件定义</code></div>
<div class="line number2 index1 alt1"> </div>
<div class="line number3 index2 alt2"><code class="xhtml plain">........</code></div>
<div class="line number4 index3 alt1"> </div>
<div class="line number5 index4 alt2"><code class="xhtml plain">........</code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">.......</code></div>
<div class="line number8 index7 alt1"> </div>
<div class="line number9 index8 alt2"><code class="xhtml plain">struct termios opt; /*定义指向termios 结构类型的指针opt*/</code></div>
<div class="line number10 index9 alt1"> </div>
<div class="line number11 index10 alt2"><code class="xhtml plain">/***************以下设置通讯波特率****************/</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">cfsetispeed(&opt,B9600 ); /*指定输入波特率,9600bps*/</code></div>
<div class="line number14 index13 alt1"> </div>
<div class="line number15 index14 alt2"><code class="xhtml plain">cfsetospeed(&opt,B9600);/*指定输出波特率,9600bps*/</code></div>
<div class="line number16 index15 alt1"> </div>
<div class="line number17 index16 alt2"><code class="xhtml plain">/************************************************/</code></div>
<div class="line number18 index17 alt1"> </div>
<div class="line number19 index18 alt2"><code class="xhtml plain">.........</code></div>
<div class="line number20 index19 alt1"> </div>
<div class="line number21 index20 alt2"><code class="xhtml plain">..........</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p></p>
<p>一般来说,输入、输出的波特率应该是一致的。</p>
<p><span><strong>3. 串口属性配置</strong></span></p>
<p>在程序中,很容易配置串口的属性,这些属性定义在结构体struct termios中。为在程序中使用该结构体,需要包含文件,该头文件定义了结构体struct termios。</p>
<p>该结构体定义如下:</p>
<div class="jb51code">
<div><div id="highlighter_985561" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#define NCCS 19</code></div>
<div class="line number2 index1 alt1"> </div>
<div class="line number3 index2 alt2"><code class="xhtml plain">struct termios {</code></div>
<div class="line number4 index3 alt1"> </div>
<div class="line number5 index4 alt2"><code class="xhtml plain">tcflag_t c_iflag; /* 输入参数 */</code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">tcflag_t c_oflag; /* 输出参数 */</code></div>
<div class="line number8 index7 alt1"> </div>
<div class="line number9 index8 alt2"><code class="xhtml plain">tcflag_t c_cflag; /* 控制参数*/</code></div>
<div class="line number10 index9 alt1"> </div>
<div class="line number11 index10 alt2"><code class="xhtml plain">tcflag_t c_ispeed; /* 输入波特率 */</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">tcflag_t c_ospeed; /* 输出波特率 */</code></div>
<div class="line number14 index13 alt1"> </div>
<div class="line number15 index14 alt2"><code class="xhtml plain">cc_t c_line; /* 线控制 */</code></div>
<div class="line number16 index15 alt1"> </div>
<div class="line number17 index16 alt2"><code class="xhtml plain">cc_t c_cc; /* 控制字符*/</code></div>
<div class="line number18 index17 alt1"> </div>
<div class="line number19 index18 alt2"><code class="xhtml plain">};</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p></p>
<p>其中成员c_line在POSIX(Portable Operating System Interface for UNIX)系统中不使用。对于支持POSIX终端接口的系统中,对于端口属性的设置和获取要用到两个重要的函数是:</p>
<p><span><strong>(1).int tcsetattr(int fd,int opt_DE,*ptr)</strong></span></p>
<p>该函数用来设置终端控制属性,其参数说明如下:</p>
<p>l fd:待操作的文件描述符</p>
<p>l opt_DE:选项值,有三个选项以供选择:</p>
<p>TCSANOW: 不等数据传输完毕就立即改变属性</p>
<p>TCSADRAIN:等待所有数据传输结束才改变属性</p>
<p>TCSAFLUSH:清空输入输出缓冲区才改变属性</p>
<p>l *ptr:指向termios结构的指针</p>
<p>函数返回值:成功返回0,失败返回-1。</p>
<p><span><strong>(2).int tcgetattr(int fd,*ptr)</strong></span></p>
<p>该函数用来获取终端控制属性,它把串口的默认设置赋给了termios数据数据结构,其参数说明如下:</p>
<p>l fd:待操作的文件描述符</p>
<p>l *ptr:指向termios结构的指针</p>
<p>函数返回值:成功返回0,失败返回-1。</p>
<p><span><strong>4. 打开串口</strong></span></p>
<p>在前面已经提到linux下的串口访问是以设备文件形式进行的,所以打开串口也即是打开文件的操作。函数原型可以如下所示:</p>
<p>int open(“DE_name”,int open_Status)</p>
<p>参数说明:</p>
<p><span><strong>(1).DE_name:要打开的设备文件名</strong></span></p>
<p>比如要打开串口1,即为/dev/ttyS0。</p>
<p><span><strong>(2).open_Status:文件打开方式,可采用下面的文件打开模式:</strong></span></p>
<p>l O_RDONLY:以只读方式打开文件</p>
<p>l O_WRONLY:以只写方式打开文件</p>
<p>l O_RDWR:以读写方式打开文件</p>
<p>l O_APPEND:写入数据时添加到文件末尾</p>
<p>l O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t</p>
<p>l O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误</p>
<p>l O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0</p>
<p>l O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。</p>
<p>l O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。</p>
<p>函数返回值:</p>
<p>成功返回文件描述符,如果失败返回-1</p>
<p>例如假定以可读写方式打开/dev/ttyS0设备,就可以这样操作:</p>
<div class="jb51code">
<div><div id="highlighter_639043" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include //头文件包含</code></div>
<div class="line number2 index1 alt1"> </div>
<div class="line number3 index2 alt2"><code class="xhtml plain">......</code></div>
<div class="line number4 index3 alt1"> </div>
<div class="line number5 index4 alt2"><code class="xhtml plain">......</code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">int fd; /* 文件描述符 */</code></div>
<div class="line number8 index7 alt1"> </div>
<div class="line number9 index8 alt2"><code class="xhtml plain">fd = open("/dev/ttyS0", O_RDWR | 0_NOCTTY); /*以读写方式打开设备*/</code></div>
<div class="line number10 index9 alt1"> </div>
<div class="line number11 index10 alt2"><code class="xhtml plain">if(fd == -1)</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">perror("Can not open Serial_Port 1/n!");/*打开失败时的错误提示*/</code></div>
<div class="line number14 index13 alt1"> </div>
<div class="line number15 index14 alt2"><code class="xhtml plain">........</code></div>
<div class="line number16 index15 alt1"> </div>
<div class="line number17 index16 alt2"><code class="xhtml plain">........</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p></p>
<p><span><strong>5. 串口读操作(接收端)</strong></span></p>
<p>用open函数打开设备文件,函数返回一个文件描述符(file descriptors,fd),通过文件描述符来访问文件。读串口操作是通过read函数来完成的。函数原型如下:</p>
<p>int read(int fd, *buffer,length);</p>
<p>参数说明:</p>
<p>(1).int fd:文件描述符</p>
<p>(2).*buffer:数据缓冲区</p>
<p>(3).length:要读取的字节数</p>
<p>函数返回值:</p>
<p>读操作成功读取返回读取的字节数,失败则返回-1。</p>
<p><span><strong>6. 串口写操作(发送端)</strong></span></p>
<p>写串口操作是通过write函数来完成的。函数原型如下:</p>
<p>write(int fd, *buffer,length);</p>
<p>参数说明:</p>
<p>(1).fd:文件描述符</p>
<p>(2).*buffer:存储写入数据的数据缓冲区</p>
<p>(3).length:写入缓冲去的数据字节数</p>
<p>函数返回值:</p>
<p>成功返回写入数据的字节数,该值通常等于length,如果写入失败返回-1。</p>
<p>例如:向终端设备发送初始化命令</p>
<div class="jb51code">
<div><div id="highlighter_824126" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include //头文件包含</code></div>
<div class="line number2 index1 alt1"> </div>
<div class="line number3 index2 alt2"><code class="xhtml plain">......</code></div>
<div class="line number4 index3 alt1"> </div>
<div class="line number5 index4 alt2"><code class="xhtml plain">......</code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">int n</code></div>
<div class="line number8 index7 alt1"> </div>
<div class="line number9 index8 alt2"><code class="xhtml plain">sbuf[]={Hello,this is a Serial_Port test!/n };//待发送数据</code></div>
<div class="line number10 index9 alt1"> </div>
<div class="line number11 index10 alt2"><code class="xhtml plain">int len_send="sizeof"(sbuf);//发送缓冲区字节数定义</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">n = write(fd,sbuf,len_send); //写缓冲区</code></div>
<div class="line number14 index13 alt1"> </div>
<div class="line number15 index14 alt2"><code class="xhtml plain">if(n == -1)</code></div>
<div class="line number16 index15 alt1"> </div>
<div class="line number17 index16 alt2"><code class="xhtml plain">{</code></div>
<div class="line number18 index17 alt1"> </div>
<div class="line number19 index18 alt2"><code class="xhtml plain">printf("Wirte sbuf error./n");</code></div>
<div class="line number20 index19 alt1"> </div>
<div class="line number21 index20 alt2"><code class="xhtml plain">}</code></div>
<div class="line number22 index21 alt1"> </div>
<div class="line number23 index22 alt2"><code class="xhtml plain">......</code></div>
<div class="line number24 index23 alt1"> </div>
<div class="line number25 index24 alt2"><code class="xhtml plain">......</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p></p>
<p><span><strong>7. 关闭串口</strong></span></p>
<p>对设备文件的操作与对普通文件的操作一样,打开操作之后还需要关闭,关闭串口用函数close( )来操作,函数原型为:</p>
<p>int close(int fd);</p>
<p>参数说明:</p>
<p>fd:文件描述符</p>
<p>函数返回值:</p>
<p>成功返回0,失败返回-1。</p>
<p>NAME</p>
<p>termios, tcgetattr, tcsetattr, tcsendbreak, tcdrain, tcflush, tcflow, cfmakeraw, cfgetospeed, cfgetispeed, cfsetispeed, cfsetospeed - 获取和设置终端属性,行控制,获取和设置波特率</p>
<p><span><strong>SYNOPSIS 总览</strong></span></p>
<p>#include <termios.h> <br>
#include <unistd.h></p>
<p>int tcgetattr(int fd, struct termios *termios_p);</p>
<p>int tcsetattr(int fd, int optional_actions, struct termios *termios_p);</p>
<p>int tcsendbreak(int fd, int duration);</p>
<p>int tcdrain(int fd);</p>
<p>int tcflush(int fd, int queue_selector);</p>
<p>int tcflow(int fd, int action);</p>
<p>int cfmakeraw(struct termios *termios_p);</p>
<p>speed_t cfgetispeed(struct termios *termios_p);</p>
<p>speed_t cfgetospeed(struct termios *termios_p);</p>
<p>int cfsetispeed(struct termios *termios_p, speed_t speed);</p>
<p>int cfsetospeed(struct termios *termios_p, speed_t speed);</p>
<p><span><strong>DESCRIPTION 描述</strong></span></p>
<p>termios 函数族提供了一个常规的终端接口,用于控制非同步通信端口。</p>
<p>这里描述的大部分属性有一个 termios_p 类型的参数,它是指向一个 termios 结构的指针。这个结构包含了至少下列成员:</p>
<p>tcflag_t c_iflag; /* 输入模式 */<br>
tcflag_t c_oflag; /* 输出模式 */<br>
tcflag_t c_cflag; /* 控制模式 */<br>
tcflag_t c_lflag; /* 本地模式 */<br>
cc_t c_cc; /* 控制字符 */</p>
<p><span><strong>c_iflag 标志常量:</strong></span></p>
<p><strong>IGNBRK</strong><br>
忽略输入中的 BREAK 状态。<br><strong>BRKINT</strong><br>
如果设置了 IGNBRK,将忽略 BREAK。如果没有设置,但是设置了 BRKINT,那么 BREAK 将使得输入和输出队列被刷新,如果终端是一个前台进程组的控制终端,这个进程组中所有进程将收到SIGINT 信号。如果既未设置 IGNBRK 也未设置 BRKINT,BREAK 将视为与 NUL 字符同义,除非设置了 PARMRK,这种情况下它被视为序列 /377 /0 /0。<br><strong>IGNPAR</strong><br>
忽略桢错误和奇偶校验错。<br><strong>PARMRK</strong><br>
如果没有设置 IGNPAR,在有奇偶校验错或桢错误的字符前插入 /377 /0。如果既没有设置 IGNPAR 也没有设置 PARMRK,将有奇偶校验错或桢错误的字符视为 /0。<br><strong>INPCK</strong><br>
启用输入奇偶检测。<br><strong>ISTRIP</strong><br>
去掉第八位。<br><strong>INLCR</strong><br>
将输入中的 NL 翻译为 CR。<br><strong>IGNCR</strong><br>
忽略输入中的回车。<br><strong>ICRNL</strong><br>
将输入中的回车翻译为新行 (除非设置了 IGNCR)。<br><strong>IUCLC</strong><br>
(不属于 POSIX) 将输入中的大写字母映射为小写字母。<br><strong>IXON</strong><br>
启用输出的 XON/XOFF 流控制。<br><strong>IXANY</strong><br>
(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出。(?)<br><strong>IXOFF</strong><br>
启用输入的 XON/XOFF 流控制。<br><strong>IMAXBEL</strong><br>
(不属于 POSIX) 当输入队列满时响零。Linux 没有实现这一位,总是将它视为已设置。<br>
POSIX.1 中定义的 c_oflag 标志常量:</p>
<p><strong>OPOST</strong><br>
启用具体实现自行定义的输出处理。<br>
其余 c_oflag 标志常量定义在 POSIX 1003.1-2001 中,除非另外说明。</p>
<p><strong>OLCUC</strong><br>
(不属于 POSIX) 将输出中的小写字母映射为大写字母。<br><strong>ONLCR</strong><br>
(XSI) 将输出中的新行符映射为回车-换行。<br><strong>OCRNL<br></strong>将输出中的回车映射为新行符<br><strong>ONOCR</strong><br>
不在第 0 列输出回车。<br><strong>ONLRET</strong><br>
不输出回车。<br><strong>OFILL</strong><br>
发送填充字符作为延时,而不是使用定时来延时。<br><strong>OFDEL</strong><br>
(不属于 POSIX) 填充字符是 ASCII DEL (0177)。如果不设置,填充字符则是 ASCII NUL。<br><strong>NLDLY</strong><br>
新行延时掩码。取值为 NL0 和 NL1。<br><strong>CRDLY</strong><br>
回车延时掩码。取值为 CR0, CR1, CR2, 或 CR3。<br><strong>TABDLY</strong><br>
水平跳格延时掩码。取值为 TAB0, TAB1, TAB2, TAB3 (或 XTABS)。取值为 TAB3,即 XTABS,将扩展跳格为空格 (每个跳格符填充 8 个空格)。(?)<br><strong>BSDLY</strong><br>
回退延时掩码。取值为 BS0 或 BS1。(从来没有被实现过)<br><strong>VTDLY</strong><br>
竖直跳格延时掩码。取值为 VT0 或 VT1。<br><strong>FFDLY</strong><br>
进表延时掩码。取值为 FF0 或 FF1。<br></p>
<p><span><strong>c_cflag 标志常量:</strong></span></p>
<p><strong>CBAUD</strong><br>
(不属于 POSIX) 波特率掩码 (4+1 位)。<br><strong>CBAUDEX</strong><br>
(不属于 POSIX) 扩展的波特率掩码 (1 位),包含在 CBAUD 中。<br>
(POSIX 规定波特率存储在 termios 结构中,并未精确指定它的位置,而是提供了函数 cfgetispeed() 和 cfsetispeed() 来存取它。一些系统使用 c_cflag 中 CBAUD 选择的位,其他系统使用单独的变量,例如 sg_ispeed 和 sg_ospeed 。)</p>
<p><strong>CSIZE</strong><br>
字符长度掩码。取值为 CS5, CS6, CS7, 或 CS8。<br><strong>CSTOPB</strong><br>
设置两个停止位,而不是一个。<br><strong>CREAD</strong><br>
打开接受者。<br><strong>PARENB</strong><br>
允许输出产生奇偶信息以及输入的奇偶校验。<br><strong>PARODD</strong><br>
输入和输出是奇校验。<br><strong>HUPCL</strong><br>
在最后一个进程关闭设备后,降低 modem 控制线 (挂断)。(?)<br><strong>CLOCAL</strong><br>
忽略 modem 控制线。<br><strong>LOBLK</strong><br>
(不属于 POSIX) 从非当前 shell 层阻塞输出(用于 shl )。(?)<br><strong>CIBAUD</strong><br>
(不属于 POSIX) 输入速度的掩码。CIBAUD 各位的值与 CBAUD 各位相同,左移了 IBSHIFT 位。<br><strong>CRTSCTS</strong><br>
(不属于 POSIX) 启用 RTS/CTS (硬件) 流控制。<br></p>
<p><span><strong>c_lflag 标志常量:</strong></span></p>
<p><strong>ISIG</strong><br>
当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号。<br><strong>ICANON</strong><br>
启用标准模式 (canonical mode)。允许使用特殊字符 EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, 和 WERASE,以及按行的缓冲。<br><strong>XCASE</strong><br>
(不属于 POSIX; Linux 下不被支持) 如果同时设置了 ICANON,终端只有大写。输入被转换为小写,除了以 / 前缀的字符。输出时,大写字符被前缀 /,小写字符被转换成大写。<br><strong>ECHO</strong><br>
回显输入字符。<br><strong>ECHOE</strong><br>
如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词。<br><strong>ECHOK</strong><br>
如果同时设置了 ICANON,字符 KILL 删除当前行。<br><strong>ECHONL</strong><br>
如果同时设置了 ICANON,回显字符 NL,即使没有设置 ECHO。<br><strong>ECHOCTL</strong><br>
(不属于 POSIX) 如果同时设置了 ECHO,除了 TAB, NL, START, 和 STOP 之外的 ASCII 控制信号被回显为 ^X, 这里 X 是比控制信号大 0x40 的 ASCII 码。例如,字符 0x08 (BS) 被回显为 ^H。<br><strong>ECHOPRT</strong><br>
(不属于 POSIX) 如果同时设置了 ICANON 和 IECHO,字符在删除的同时被打印。<br><strong>ECHOKE</strong><br>
(不属于 POSIX) 如果同时设置了 ICANON,回显 KILL 时将删除一行中的每个字符,如同指定了 ECHOE 和 ECHOPRT 一样。<br><strong>DEFECHO</strong><br>
(不属于 POSIX) 只在一个进程读的时候回显。<br><strong>FLUSHO</strong><br>
(不属于 POSIX; Linux 下不被支持) 输出被刷新。这个标志可以通过键入字符 DISCARD 来开关。<br><strong>NOFLSH</strong><br>
禁止在产生 SIGINT, SIGQUIT 和 SIGSUSP 信号时刷新输入和输出队列。<br><strong>TOSTOP</strong><br>
向试图写控制终端的后台进程组发送 SIGTTOU 信号。<br><strong>PENDIN</strong><br>
(不属于 POSIX; Linux 下不被支持) 在读入下一个字符时,输入队列中所有字符被重新输出。(bash 用它来处理 typeahead)<br><strong>IEXTEN</strong><br>
启用实现自定义的输入处理。这个标志必须与 ICANON 同时使用,才能解释特殊字符 EOL2,LNEXT,REPRINT 和 WERASE,IUCLC 标志才有效。<br></p>
<p><span><strong>c_cc 数组定义了特殊的控制字符。符号下标 (初始值) 和意义为:</strong></span></p>
<p><strong><span id="1482889946536E"> </span>VINTR</strong><br>
(003, ETX, Ctrl-C, or also 0177, DEL, rubout) 中断字符。发出 SIGINT 信号。当设置 ISIG 时可被识别,不再作为输入传递。<br><strong>VQUIT</strong><br>
(034, FS, Ctrl-/) 退出字符。发出 SIGQUIT 信号。当设置 ISIG 时可被识别,不再作为输入传递。<br><strong>VERASE</strong><br>
(0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) 删除字符。删除上一个还没有删掉的字符,但不删除上一个 EOF 或行首。当设置 ICANON 时可被识别,不再作为输入传递。<br><strong>VKILL</strong><br>
(025, NAK, Ctrl-U, or Ctrl-X, or also @) 终止字符。删除自上一个 EOF 或行首以来的输入。当设置 ICANON 时可被识别,不再作为输入传递。<br><strong>VEOF</strong><br>
(004, EOT, Ctrl-D) 文件尾字符。更精确地说,这个字符使得 tty 缓冲中的内容被送到等待输入的用户程序中,而不必等到 EOL。如果它是一行的第一个字符,那么用户程序的 read() 将返回 0,指示读到了 EOF。当设置 ICANON 时可被识别,不再作为输入传递。<br><strong>VMIN</strong><br>
非 canonical 模式读的最小字符数。<br><strong>VEOL</strong><br>
(0, NUL) 附加的行尾字符。当设置 ICANON 时可被识别。<br><strong>VTIME</strong><br>
非 canonical 模式读时的延时,以十分之一秒为单位。<br><strong>VEOL2</strong><br>
(not in POSIX; 0, NUL) 另一个行尾字符。当设置 ICANON 时可被识别。<br><strong>VSWTCH</strong><br>
(not in POSIX; not supported under Linux; 0, NUL) 开关字符。(只为 shl 所用。)<br><strong>VSTART</strong><br>
(021, DC1, Ctrl-Q) 开始字符。重新开始被 Stop 字符中止的输出。当设置 IXON 时可被识别,不再作为输入传递。<br><strong>VSTOP</strong><br>
(023, DC3, Ctrl-S) 停止字符。停止输出,直到键入 Start 字符。当设置 IXON 时可被识别,不再作为输入传递。<br><strong>VSUSP</strong><br>
(032, SUB, Ctrl-Z) 挂起字符。发送 SIGTSTP 信号。当设置 ISIG 时可被识别,不再作为输入传递。<br><strong>VDSUSP</strong><br>
(not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) 延时挂起信号。当用户程序读到这个字符时,发送 SIGTSTP 信号。当设置 IEXTEN 和 ISIG,并且系统支持作业管理时可被识别,不再作为输入传递。<br><strong>VLNEXT</strong><br>
(not in POSIX; 026, SYN, Ctrl-V) 字面上的下一个。引用下一个输入字符,取消它的任何特殊含义。当设置 IEXTEN 时可被识别,不再作为输入传递。<br><strong>VWERASE</strong><br>
(not in POSIX; 027, ETB, Ctrl-W) 删除词。当设置 ICANON 和 IEXTEN 时可被识别,不再作为输入传递。<br><strong>VREPRINT</strong><br>
(not in POSIX; 022, DC2, Ctrl-R) 重新输出未读的字符。当设置 ICANON 和 IEXTEN 时可被识别,不再作为输入传递。<br><strong>VDISCARD</strong><br>
(not in POSIX; not supported under Linux; 017, SI, Ctrl-O) 开关:开始/结束丢弃未完成的输出。当设置 IEXTEN 时可被识别,不再作为输入传递。<br><strong>VSTATUS</strong><br>
(not in POSIX; not supported under Linux; status request: 024, DC4, Ctrl-T).<br></p>
<p>这些符号下标值是互不相同的,除了 VTIME,VMIN 的值可能分别与 VEOL,VEOF 相同。 (在 non-canonical 模式下,特殊字符的含义更改为延时含义。MIN 表示应当被读入的最小字符数。TIME 是以十分之一秒为单位的计时器。如果同时设置了它们,read 将等待直到至少读入一个字符,一旦读入 MIN 个字符或者从上次读入字符开始经过了 TIME 时间就立即返回。如果只设置了 MIN,read 在读入 MIN 个字符之前不会返回。如果只设置了 TIME,read 将在至少读入一个字符,或者计时器超时的时候立即返回。如果都没有设置,read 将立即返回,只给出当前准备好的字符。) (?)</p>
<p>tcgetattr() 得到与 fd 指向的对象相关的参数,将它们保存于 termios_p 引用的 termios 结构中。函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。</p>
<p>tcsetattr() 设置与终端相关的参数 (除非需要底层支持却无法满足),使用 termios_p 引用的 termios 结构。optional_actions 指定了什么时候改变会起作用:</p>
<p><strong>TCSANOW</strong><br>
改变立即发生<br><strong>TCSADRAIN</strong><br>
改变在所有写入 fd 的输出都被传输后生效。这个函数应当用于修改影响输出的参数时使用。<br><strong>TCSAFLUSH</strong><br>
改变在所有写入 fd 引用的对象的输出都被传输后生效,所有已接受但未读入的输入都在改变发生前丢弃。<br>
tcsendbreak() 传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义。</p>
<p>如果终端并非使用异步串行数据传输,tcsendbreak() 什么都不做。</p>
<p>tcdrain() 等待直到所有写入 fd 引用的对象的输出都被传输。</p>
<p>tcflush() 丢弃要写入 引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据,取决于 queue_selector 的值:</p>
<p><strong>TCIFLUSH</strong><br>
刷新收到的数据但是不读<br><strong>TCOFLUSH</strong><br>
刷新写入的数据但是不传送<br><strong>TCIOFLUSH</strong><br>
同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送<br>
tcflow() 挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值:</p>
<p><strong>TCOOFF</strong><br>
挂起输出<br><strong>TCOON</strong><br>
重新开始被挂起的输出<br><strong>TCIOFF</strong><br>
发送一个 STOP 字符,停止终端设备向系统传送数据<br><strong>TCION</strong><br>
发送一个 START 字符,使终端设备向系统传输数据<br>
打开一个终端设备时的默认设置是输入和输出都没有挂起。</p>
<p>波特率函数被用来获取和设置 termios 结构中,输入和输出波特率的值。新值不会马上生效,直到成功调用了 tcsetattr() 函数。</p>
<p>设置速度为 B0 使得 modem "挂机"。与 B38400 相应的实际比特率可以用 setserial(8) 调整。</p>
<p>输入和输出波特率被保存于 termios 结构中。</p>
<p><strong>cfmakeraw 设置终端属性如下:</strong></p>
<p> termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP<br>
|INLCR|IGNCR|ICRNL|IXON);<br>
termios_p->c_oflag &= ~OPOST;<br>
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);<br>
termios_p->c_cflag &= ~(CSIZE|PARENB);<br>
termios_p->c_cflag |= CS8;<br></p>
<p>cfgetospeed() 返回 termios_p 指向的 termios 结构中存储的输出波特率</p>
<p>cfsetospeed() 设置 termios_p 指向的 termios 结构中存储的输出波特率为 speed。取值必须是以下常量之一:</p>
<p> B0<br>
B50<br>
B75<br>
B110<br>
B134<br>
B150<br>
B200<br>
B300<br>
B600<br>
B1200<br>
B1800<br>
B2400<br>
B4800<br>
B9600<br>
B19200<br>
B38400<br>
B57600<br>
B115200<br>
B230400</p>
<p>零值 B0 用来中断连接。如果指定了 B0,不应当再假定存在连接。通常,这样将断开连接。CBAUDEX 是一个掩码,指示高于 POSIX.1 定义的速度的那一些 (57600 及以上)。因此,B57600 &CBAUDEX 为非零。</p>
<p>cfgetispeed() 返回 termios 结构中存储的输入波特率。</p>
<p>cfsetispeed() 设置 termios 结构中存储的输入波特率为 speed。如果输入波特率被设为0,实际输入波特率将等于输出波特率。</p>
<p><strong>RETURN VALUE 返回值</strong></p>
<p>cfgetispeed() 返回 termios 结构中存储的输入波特率。</p>
<p>cfgetospeed() 返回 termios 结构中存储的输出波特率。</p>
<p>其他函数返回:</p>
<p>0<br>
成功<br>
-1<br>
失败,并且为 errno 置值来指示错误。<br>
注意 tcsetattr() 返回成功,如果任何所要求的修改可以实现的话。因此,当进行多重修改时,应当在这个函数之后再次调用 tcgetattr() 来检测是否所有修改都成功实现。</p>
<p><br><span><strong>NOTES 注意</strong></span></p>
<p>Unix V7 以及很多后来的系统有一个波特率的列表,在十四个值 B0, ..., B9600 之后可以看到两个常数 EXTA, EXTB ("External A" and "External B")。很多系统将这个列表扩展为更高的波特率。</p>
<p>tcsendbreak 中非零的 duration 有不同的效果。SunOS 指定中断 duration*N 秒,其中 N 至少为 0.25,不高于 0.5 。Linux, AIX, DU, Tru64 发送 duration 微秒的 break 。FreeBSD, NetBSD, HP-UX 以及 MacOS 忽略 duration 的值。在 Solaris 和 Unixware 中, tcsendbreak 搭配非零的 duration 效果类似于 tcdrain。 </p>
<p></p>
<p>所有的范例来源自 miniterm.c. The type ahead 暂存器被限制在 255 个字元, 就跟标准输入程序的最大字串长度相同 ( 或 ).</p>
<p>参考程序码中的注解它会解释不同输入模式的使用. 我希望这些程序码都能被了解. 标准输入程序的程序范例的注解写得最好, 其它的范例都只在不同于其它范例的地方做注解.</p>
<p>叙述不是很完整, 但可以激励你对这范例做实验, 以延生出合于你所需应用程序的最佳解.</p>
<p>别忘记要把序列埠的权限设定正确 (也就是: chmod a+rw /dev/ttyS1)!</p>
<p><span><strong>3.1 标准输入程序</strong></span></p>
<div class="jb51code">
<div><div id="highlighter_83498" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div>
<div class="line number33 index32 alt2">33</div>
<div class="line number34 index33 alt1">34</div>
<div class="line number35 index34 alt2">35</div>
<div class="line number36 index35 alt1">36</div>
<div class="line number37 index36 alt2">37</div>
<div class="line number38 index37 alt1">38</div>
<div class="line number39 index38 alt2">39</div>
<div class="line number40 index39 alt1">40</div>
<div class="line number41 index40 alt2">41</div>
<div class="line number42 index41 alt1">42</div>
<div class="line number43 index42 alt2">43</div>
<div class="line number44 index43 alt1">44</div>
<div class="line number45 index44 alt2">45</div>
<div class="line number46 index45 alt1">46</div>
<div class="line number47 index46 alt2">47</div>
<div class="line number48 index47 alt1">48</div>
<div class="line number49 index48 alt2">49</div>
<div class="line number50 index49 alt1">50</div>
<div class="line number51 index50 alt2">51</div>
<div class="line number52 index51 alt1">52</div>
<div class="line number53 index52 alt2">53</div>
<div class="line number54 index53 alt1">54</div>
<div class="line number55 index54 alt2">55</div>
<div class="line number56 index55 alt1">56</div>
<div class="line number57 index56 alt2">57</div>
<div class="line number58 index57 alt1">58</div>
<div class="line number59 index58 alt2">59</div>
<div class="line number60 index59 alt1">60</div>
<div class="line number61 index60 alt2">61</div>
<div class="line number62 index61 alt1">62</div>
<div class="line number63 index62 alt2">63</div>
<div class="line number64 index63 alt1">64</div>
<div class="line number65 index64 alt2">65</div>
<div class="line number66 index65 alt1">66</div>
<div class="line number67 index66 alt2">67</div>
<div class="line number68 index67 alt1">68</div>
<div class="line number69 index68 alt2">69</div>
<div class="line number70 index69 alt1">70</div>
<div class="line number71 index70 alt2">71</div>
<div class="line number72 index71 alt1">72</div>
<div class="line number73 index72 alt2">73</div>
<div class="line number74 index73 alt1">74</div>
<div class="line number75 index74 alt2">75</div>
<div class="line number76 index75 alt1">76</div>
<div class="line number77 index76 alt2">77</div>
<div class="line number78 index77 alt1">78</div>
<div class="line number79 index78 alt2">79</div>
<div class="line number80 index79 alt1">80</div>
<div class="line number81 index80 alt2">81</div>
<div class="line number82 index81 alt1">82</div>
<div class="line number83 index82 alt2">83</div>
<div class="line number84 index83 alt1">84</div>
<div class="line number85 index84 alt2">85</div>
<div class="line number86 index85 alt1">86</div>
<div class="line number87 index86 alt2">87</div>
<div class="line number88 index87 alt1">88</div>
<div class="line number89 index88 alt2">89</div>
<div class="line number90 index89 alt1">90</div>
<div class="line number91 index90 alt2">91</div>
<div class="line number92 index91 alt1">92</div>
<div class="line number93 index92 alt2">93</div>
<div class="line number94 index93 alt1">94</div>
<div class="line number95 index94 alt2">95</div>
<div class="line number96 index95 alt1">96</div>
<div class="line number97 index96 alt2">97</div>
<div class="line number98 index97 alt1">98</div>
<div class="line number99 index98 alt2">99</div>
<div class="line number100 index99 alt1">100</div>
<div class="line number101 index100 alt2">101</div>
<div class="line number102 index101 alt1">102</div>
<div class="line number103 index102 alt2">103</div>
<div class="line number104 index103 alt1">104</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number3 index2 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number4 index3 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number5 index4 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">/* 鲍率设定被定义在 , 这在 被引入 */</code></div>
<div class="line number8 index7 alt1"><code class="xhtml plain">#define BAUDRATE B38400 </code></div>
<div class="line number9 index8 alt2"><code class="xhtml plain">/* 定义正确的序列埠 */</code></div>
<div class="line number10 index9 alt1"><code class="xhtml plain">#define MODEMDEVICE "/dev/ttyS1"</code></div>
<div class="line number11 index10 alt2"><code class="xhtml plain">#define _POSIX_SOURCE 1 /* POSIX 系统兼容 */</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">#define FALSE 0</code></div>
<div class="line number14 index13 alt1"><code class="xhtml plain">#define TRUE 1</code></div>
<div class="line number15 index14 alt2"> </div>
<div class="line number16 index15 alt1"><code class="xhtml plain">volatile int STOP=FALSE; </code></div>
<div class="line number17 index16 alt2"> </div>
<div class="line number18 index17 alt1"><code class="xhtml plain">main()</code></div>
<div class="line number19 index18 alt2"><code class="xhtml plain">{</code></div>
<div class="line number20 index19 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">int fd,c, res;</code>
</div>
<div class="line number21 index20 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">struct termios oldtio,newtio;</code>
</div>
<div class="line number22 index21 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">char buf;</code>
</div>
<div class="line number23 index22 alt2"><code class="xhtml plain">/* </code></div>
<div class="line number24 index23 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">开启数据机装置以读取并写入而不以控制 tty 的模式</code>
</div>
<div class="line number25 index24 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">因为我们不想程序在送出 CTRL-C 后就被杀掉.</code>
</div>
<div class="line number26 index25 alt1"><code class="xhtml plain">*/</code></div>
<div class="line number27 index26 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); </code>
</div>
<div class="line number28 index27 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd <0) {perror(MODEMDEVICE); exit(-1); }</code>
</div>
<div class="line number29 index28 alt2"> </div>
<div class="line number30 index29 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */</code>
</div>
<div class="line number31 index30 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">bzero(&newtio, sizeof(newtio)); /* 清除结构体以放入新的序列埠设定值 */</code>
</div>
<div class="line number32 index31 alt1"> </div>
<div class="line number33 index32 alt2"><code class="xhtml plain">/* </code></div>
<div class="line number34 index33 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">BAUDRATE: 设定 bps 的速度. 你也可以用 cfsetispeed 及 cfsetospeed 来设定.</code>
</div>
<div class="line number35 index34 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">CRTSCTS : 输出资料的硬件流量控制 (只能在具完整线路的缆线下工作</code>
</div>
<div class="line number36 index35 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">参考 Serial-HOWTO 第七节)</code>
</div>
<div class="line number37 index36 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">CS8 : 8n1 (8 位元, 不做同位元检查,1 个终止位元)</code>
</div>
<div class="line number38 index37 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">CLOCAL : 本地连线, 不具数据机控制功能</code>
</div>
<div class="line number39 index38 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">CREAD : 致能接收字元</code>
</div>
<div class="line number40 index39 alt1"><code class="xhtml plain">*/</code></div>
<div class="line number41 index40 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;</code>
</div>
<div class="line number42 index41 alt1">
<code class="xhtml spaces"> </code> </div>
<div class="line number43 index42 alt2"><code class="xhtml plain">/*</code></div>
<div class="line number44 index43 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">IGNPAR : 忽略经同位元检查后, 错误的位元组</code>
</div>
<div class="line number45 index44 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">ICRNL : 比 CR 对应成 NL (否则当输入信号有 CR 时不会终止输入)</code>
</div>
<div class="line number46 index45 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">在不然把装置设定成 raw 模式(没有其它的输入处理)</code>
</div>
<div class="line number47 index46 alt2"><code class="xhtml plain">*/</code></div>
<div class="line number48 index47 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_iflag = IGNPAR | ICRNL;</code>
</div>
<div class="line number49 index48 alt2">
<code class="xhtml spaces"> </code> </div>
<div class="line number50 index49 alt1"><code class="xhtml plain">/*</code></div>
<div class="line number51 index50 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">Raw 模式输出.</code>
</div>
<div class="line number52 index51 alt1"><code class="xhtml plain">*/</code></div>
<div class="line number53 index52 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_oflag = 0;</code>
</div>
<div class="line number54 index53 alt1">
<code class="xhtml spaces"> </code> </div>
<div class="line number55 index54 alt2"><code class="xhtml plain">/*</code></div>
<div class="line number56 index55 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">ICANON : 致能标准输入, 使所有回应机能停用, 并不送出信号以叫用程序</code>
</div>
<div class="line number57 index56 alt2"><code class="xhtml plain">*/</code></div>
<div class="line number58 index57 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_lflag = ICANON;</code>
</div>
<div class="line number59 index58 alt2">
<code class="xhtml spaces"> </code> </div>
<div class="line number60 index59 alt1"><code class="xhtml plain">/* </code></div>
<div class="line number61 index60 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">初始化所有的控制特性</code>
</div>
<div class="line number62 index61 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">预设值可以在 /usr/include/termios.h 找到, 在注解中也有,</code>
</div>
<div class="line number63 index62 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">但我们在这不需要看它们</code>
</div>
<div class="line number64 index63 alt1"><code class="xhtml plain">*/</code></div>
<div class="line number65 index64 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-c */ </code>
</div>
<div class="line number66 index65 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-/ */</code>
</div>
<div class="line number67 index66 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* del */</code>
</div>
<div class="line number68 index67 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* @ */</code>
</div>
<div class="line number69 index68 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 4; /* Ctrl-d */</code>
</div>
<div class="line number70 index69 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* 不使用分割字元组的计时器 */</code>
</div>
<div class="line number71 index70 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 1; /* 在读取到 1 个字元前先停止 */</code>
</div>
<div class="line number72 index71 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* '/0' */</code>
</div>
<div class="line number73 index72 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-q */ </code>
</div>
<div class="line number74 index73 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-s */</code>
</div>
<div class="line number75 index74 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-z */</code>
</div>
<div class="line number76 index75 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* '/0' */</code>
</div>
<div class="line number77 index76 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-r */</code>
</div>
<div class="line number78 index77 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-u */</code>
</div>
<div class="line number79 index78 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-w */</code>
</div>
<div class="line number80 index79 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* Ctrl-v */</code>
</div>
<div class="line number81 index80 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* '/0' */</code>
</div>
<div class="line number82 index81 alt1"> </div>
<div class="line number83 index82 alt2"><code class="xhtml plain">/* </code></div>
<div class="line number84 index83 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">现在清除数据机线并启动序列埠的设定</code>
</div>
<div class="line number85 index84 alt2"><code class="xhtml plain">*/</code></div>
<div class="line number86 index85 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcflush(fd, TCIFLUSH);</code>
</div>
<div class="line number87 index86 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&newtio);</code>
</div>
<div class="line number88 index87 alt1"> </div>
<div class="line number89 index88 alt2"><code class="xhtml plain">/*</code></div>
<div class="line number90 index89 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">终端机设定完成, 现在处理输入信号</code>
</div>
<div class="line number91 index90 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">在这个范例, 在一行的开始处输入 'z' 会退出此程序.</code>
</div>
<div class="line number92 index91 alt1"><code class="xhtml plain">*/</code></div>
<div class="line number93 index92 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">while (STOP==FALSE) { /* 回圈会在我们发出终止的信号后跳出 */</code>
</div>
<div class="line number94 index93 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 即使输入超过 255 个字元, 读取的程序段还是会一直等到行终结符出现才停止.</code>
</div>
<div class="line number95 index94 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">如果读到的字元组低于正确存在的字元组, 则所剩的字元会在下一次读取时取得.</code>
</div>
<div class="line number96 index95 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">res 用来存放真正读到的字元组个数 */</code>
</div>
<div class="line number97 index96 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">res = read(fd,buf,255); </code>
</div>
<div class="line number98 index97 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">buf=0; /* 设定字串终止字元, 所以我们能用 printf */</code>
</div>
<div class="line number99 index98 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">printf(":%s:%d/n", buf, res);</code>
</div>
<div class="line number100 index99 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (buf=='z') STOP=TRUE;</code>
</div>
<div class="line number101 index100 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">}</code>
</div>
<div class="line number102 index101 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 回存旧的序列埠设定值 */</code>
</div>
<div class="line number103 index102 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&oldtio);</code>
</div>
<div class="line number104 index103 alt1"><code class="xhtml plain">}</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p><span><strong>3.2 非标准输入程序</strong></span></p>
<p>在非标准的输入程序模式下, 输入的资料不会被组合成一行而输入后的处理功能 (清除, 杀掉, 删除, 等等.) 都不能使用. 这个模式有两个功能控制参数: c_cc 设定字元输入时间计时器, 及c_cc 设定满足读取功能的最低字元接收个数.</p>
<p>如果 MIN > 0 且 TIME = 0, MIN 设定为满足读取功能的最低字元接收个数. 由于 TIME 是 零, 所以计时器将不被使用.</p>
<p>如果 MIN = 0 且 TIME > 0, TIME 将被当做逾时设定值. 满足读取功能的情况为读取到单一字元, 或者超过 TIME 所定义的时间 (t = TIME *0.1 s). 如果超过 TIME 所定义的时间, 则不会传回任何字元.</p>
<p>如果 MIN > 0 且 TIME > 0, TIME 将被当做一个分割字元组的计时器. 满足读取功能的条件为接收到 MIN 个数的字元, 或两个字元的间隔时间超过 TIME 所定义的值. 计时器会在每读到一个字元后重新计时, 且只会在第一个字元收到后才会启动.</p>
<p>如果 MIN = 0 且 TIME = 0, 读取功能就马上被满足. 目前所存在的字元组个数, 或者 将回传的字元组个数. 根据 Antonino (参考 贡献) 所说, 你可以用 fcntl(fd, F_SETFL, FNDELAY); 在读取前得到相同的结果.</p>
<p>藉由修改 newtio.c_cc 及 newtio.c_cc 上述的模式就可以测试了.</p>
<div class="jb51code">
<div><div id="highlighter_265525" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div>
<div class="line number33 index32 alt2">33</div>
<div class="line number34 index33 alt1">34</div>
<div class="line number35 index34 alt2">35</div>
<div class="line number36 index35 alt1">36</div>
<div class="line number37 index36 alt2">37</div>
<div class="line number38 index37 alt1">38</div>
<div class="line number39 index38 alt2">39</div>
<div class="line number40 index39 alt1">40</div>
<div class="line number41 index40 alt2">41</div>
<div class="line number42 index41 alt1">42</div>
<div class="line number43 index42 alt2">43</div>
<div class="line number44 index43 alt1">44</div>
<div class="line number45 index44 alt2">45</div>
<div class="line number46 index45 alt1">46</div>
<div class="line number47 index46 alt2">47</div>
<div class="line number48 index47 alt1">48</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number3 index2 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number4 index3 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number5 index4 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number6 index5 alt1"> </div>
<div class="line number7 index6 alt2"><code class="xhtml plain">#define BAUDRATE B38400</code></div>
<div class="line number8 index7 alt1"><code class="xhtml plain">#define MODEMDEVICE "/dev/ttyS1"</code></div>
<div class="line number9 index8 alt2"><code class="xhtml plain">#define _POSIX_SOURCE 1 /* POSIX 系统兼容 */</code></div>
<div class="line number10 index9 alt1"><code class="xhtml plain">#define FALSE 0</code></div>
<div class="line number11 index10 alt2"><code class="xhtml plain">#define TRUE 1</code></div>
<div class="line number12 index11 alt1"> </div>
<div class="line number13 index12 alt2"><code class="xhtml plain">volatile int STOP=FALSE; </code></div>
<div class="line number14 index13 alt1"> </div>
<div class="line number15 index14 alt2"><code class="xhtml plain">main()</code></div>
<div class="line number16 index15 alt1"><code class="xhtml plain">{</code></div>
<div class="line number17 index16 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">int fd,c, res;</code>
</div>
<div class="line number18 index17 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">struct termios oldtio,newtio;</code>
</div>
<div class="line number19 index18 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">char buf;</code>
</div>
<div class="line number20 index19 alt1"> </div>
<div class="line number21 index20 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); </code>
</div>
<div class="line number22 index21 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd <0) {perror(MODEMDEVICE); exit(-1); }</code>
</div>
<div class="line number23 index22 alt2"> </div>
<div class="line number24 index23 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */</code>
</div>
<div class="line number25 index24 alt2"> </div>
<div class="line number26 index25 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">bzero(&newtio, sizeof(newtio));</code>
</div>
<div class="line number27 index26 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;</code>
</div>
<div class="line number28 index27 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_iflag = IGNPAR;</code>
</div>
<div class="line number29 index28 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_oflag = 0;</code>
</div>
<div class="line number30 index29 alt1"> </div>
<div class="line number31 index30 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 设定输入模式 (非标准型, 不回应,...) */</code>
</div>
<div class="line number32 index31 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_lflag = 0;</code>
</div>
<div class="line number33 index32 alt2">
<code class="xhtml spaces"> </code> </div>
<div class="line number34 index33 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 0; /* 不使用分割字元组计时器 */</code>
</div>
<div class="line number35 index34 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc = 5; /* 在读取到 5 个字元前先停止 */</code>
</div>
<div class="line number36 index35 alt1"> </div>
<div class="line number37 index36 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcflush(fd, TCIFLUSH);</code>
</div>
<div class="line number38 index37 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&newtio);</code>
</div>
<div class="line number39 index38 alt2"> </div>
<div class="line number40 index39 alt1"> </div>
<div class="line number41 index40 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">while (STOP==FALSE) { /* 输入回圈 */</code>
</div>
<div class="line number42 index41 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">res = read(fd,buf,255); /* 在输入 5 个字元后即返回 */</code>
</div>
<div class="line number43 index42 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">buf=0; /* 所以我们能用 printf... */</code>
</div>
<div class="line number44 index43 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">printf(":%s:%d/n", buf, res);</code>
</div>
<div class="line number45 index44 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (buf=='z') STOP=TRUE;</code>
</div>
<div class="line number46 index45 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">}</code>
</div>
<div class="line number47 index46 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&oldtio);</code>
</div>
<div class="line number48 index47 alt1"><code class="xhtml plain">}</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p><span><strong>3.3 非同步式输入</strong></span></p>
<div class="jb51code">
<div><div id="highlighter_151466" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div>
<div class="line number33 index32 alt2">33</div>
<div class="line number34 index33 alt1">34</div>
<div class="line number35 index34 alt2">35</div>
<div class="line number36 index35 alt1">36</div>
<div class="line number37 index36 alt2">37</div>
<div class="line number38 index37 alt1">38</div>
<div class="line number39 index38 alt2">39</div>
<div class="line number40 index39 alt1">40</div>
<div class="line number41 index40 alt2">41</div>
<div class="line number42 index41 alt1">42</div>
<div class="line number43 index42 alt2">43</div>
<div class="line number44 index43 alt1">44</div>
<div class="line number45 index44 alt2">45</div>
<div class="line number46 index45 alt1">46</div>
<div class="line number47 index46 alt2">47</div>
<div class="line number48 index47 alt1">48</div>
<div class="line number49 index48 alt2">49</div>
<div class="line number50 index49 alt1">50</div>
<div class="line number51 index50 alt2">51</div>
<div class="line number52 index51 alt1">52</div>
<div class="line number53 index52 alt2">53</div>
<div class="line number54 index53 alt1">54</div>
<div class="line number55 index54 alt2">55</div>
<div class="line number56 index55 alt1">56</div>
<div class="line number57 index56 alt2">57</div>
<div class="line number58 index57 alt1">58</div>
<div class="line number59 index58 alt2">59</div>
<div class="line number60 index59 alt1">60</div>
<div class="line number61 index60 alt2">61</div>
<div class="line number62 index61 alt1">62</div>
<div class="line number63 index62 alt2">63</div>
<div class="line number64 index63 alt1">64</div>
<div class="line number65 index64 alt2">65</div>
<div class="line number66 index65 alt1">66</div>
<div class="line number67 index66 alt2">67</div>
<div class="line number68 index67 alt1">68</div>
<div class="line number69 index68 alt2">69</div>
<div class="line number70 index69 alt1">70</div>
<div class="line number71 index70 alt2">71</div>
<div class="line number72 index71 alt1">72</div>
<div class="line number73 index72 alt2">73</div>
<div class="line number74 index73 alt1">74</div>
<div class="line number75 index74 alt2">75</div>
<div class="line number76 index75 alt1">76</div>
<div class="line number77 index76 alt2">77</div>
<div class="line number78 index77 alt1">78</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number3 index2 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number4 index3 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number5 index4 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number6 index5 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number7 index6 alt2"> </div>
<div class="line number8 index7 alt1"><code class="xhtml plain">#define BAUDRATE B38400</code></div>
<div class="line number9 index8 alt2"><code class="xhtml plain">#define MODEMDEVICE "/dev/ttyS1"</code></div>
<div class="line number10 index9 alt1"><code class="xhtml plain">#define _POSIX_SOURCE 1 /* POSIX 系统兼容 */</code></div>
<div class="line number11 index10 alt2"><code class="xhtml plain">#define FALSE 0</code></div>
<div class="line number12 index11 alt1"><code class="xhtml plain">#define TRUE 1</code></div>
<div class="line number13 index12 alt2"> </div>
<div class="line number14 index13 alt1"><code class="xhtml plain">volatile int STOP=FALSE; </code></div>
<div class="line number15 index14 alt2"> </div>
<div class="line number16 index15 alt1"><code class="xhtml plain">void signal_handler_IO (int status); /* 定义信号处理程序 */</code></div>
<div class="line number17 index16 alt2"><code class="xhtml plain">int wait_flag=TRUE; /* 没收到信号的话就会是 TRUE */</code></div>
<div class="line number18 index17 alt1"> </div>
<div class="line number19 index18 alt2"><code class="xhtml plain">main()</code></div>
<div class="line number20 index19 alt1"><code class="xhtml plain">{</code></div>
<div class="line number21 index20 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">int fd,c, res;</code>
</div>
<div class="line number22 index21 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">struct termios oldtio,newtio;</code>
</div>
<div class="line number23 index22 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">struct sigaction saio; /* definition of signal action */</code>
</div>
<div class="line number24 index23 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">char buf;</code>
</div>
<div class="line number25 index24 alt2"> </div>
<div class="line number26 index25 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 开启装置为 non-blocking (读取功能会马上结束返回) */</code>
</div>
<div class="line number27 index26 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);</code>
</div>
<div class="line number28 index27 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd <0) {perror(MODEMDEVICE); exit(-1); }</code>
</div>
<div class="line number29 index28 alt2"> </div>
<div class="line number30 index29 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 在使装置非同步化前, 安装信号处理程序 */</code>
</div>
<div class="line number31 index30 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">saio.sa_handler = signal_handler_IO;</code>
</div>
<div class="line number32 index31 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">saio.sa_mask = 0;</code>
</div>
<div class="line number33 index32 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">saio.sa_flags = 0;</code>
</div>
<div class="line number34 index33 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">saio.sa_restorer = NULL;</code>
</div>
<div class="line number35 index34 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">sigaction(SIGIO,&saio,NULL);</code>
</div>
<div class="line number36 index35 alt1">
<code class="xhtml spaces"> </code> </div>
<div class="line number37 index36 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 允许行程去接收 SIGIO 信号*/</code>
</div>
<div class="line number38 index37 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">fcntl(fd, F_SETOWN, getpid());</code>
</div>
<div class="line number39 index38 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 使文档ake the file descriptor 非同步 (使用手册上说只有 O_APPEND 及</code>
</div>
<div class="line number40 index39 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">O_NONBLOCK, 而 F_SETFL 也可以用...) */</code>
</div>
<div class="line number41 index40 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fcntl(fd, F_SETFL, FASYNC);</code>
</div>
<div class="line number42 index41 alt1"> </div>
<div class="line number43 index42 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定值 */</code>
</div>
<div class="line number44 index43 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 设定新的序列埠为标准输入程序 */</code>
</div>
<div class="line number45 index44 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;</code>
</div>
<div class="line number46 index45 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_iflag = IGNPAR | ICRNL;</code>
</div>
<div class="line number47 index46 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_oflag = 0;</code>
</div>
<div class="line number48 index47 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_lflag = ICANON;</code>
</div>
<div class="line number49 index48 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc=1;</code>
</div>
<div class="line number50 index49 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">newtio.c_cc=0;</code>
</div>
<div class="line number51 index50 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcflush(fd, TCIFLUSH);</code>
</div>
<div class="line number52 index51 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&newtio);</code>
</div>
<div class="line number53 index52 alt2">
<code class="xhtml spaces"> </code> </div>
<div class="line number54 index53 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 等待输入信号的回圈. 很多有用的事我们将在这做 */ </code>
</div>
<div class="line number55 index54 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">while (STOP==FALSE) {</code>
</div>
<div class="line number56 index55 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">printf("./n");usleep(100000);</code>
</div>
<div class="line number57 index56 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 在收到 SIGIO 后, wait_flag = FALSE, 输入信号存在则可以被读取 */</code>
</div>
<div class="line number58 index57 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (wait_flag==FALSE) { </code>
</div>
<div class="line number59 index58 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">res = read(fd,buf,255);</code>
</div>
<div class="line number60 index59 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">buf=0;</code>
</div>
<div class="line number61 index60 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">printf(":%s:%d/n", buf, res);</code>
</div>
<div class="line number62 index61 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (res==1) STOP=TRUE; /* 如果只输入 CR 则停止回圈 */</code>
</div>
<div class="line number63 index62 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">wait_flag = TRUE; /* 等待新的输入信号 */</code>
</div>
<div class="line number64 index63 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">}</code>
</div>
<div class="line number65 index64 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">}</code>
</div>
<div class="line number66 index65 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 回存旧的序列埠设定值 */</code>
</div>
<div class="line number67 index66 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">tcsetattr(fd,TCSANOW,&oldtio);</code>
</div>
<div class="line number68 index67 alt1"><code class="xhtml plain">}</code></div>
<div class="line number69 index68 alt2"> </div>
<div class="line number70 index69 alt1"><code class="xhtml plain">/***************************************************************************</code></div>
<div class="line number71 index70 alt2"><code class="xhtml plain">* 信号处理程序. 设定 wait_flag 为 FALSE, 以使上述的回圈能接收字元 *</code></div>
<div class="line number72 index71 alt1"><code class="xhtml plain">***************************************************************************/</code></div>
<div class="line number73 index72 alt2"> </div>
<div class="line number74 index73 alt1"><code class="xhtml plain">void signal_handler_IO (int status)</code></div>
<div class="line number75 index74 alt2"><code class="xhtml plain">{</code></div>
<div class="line number76 index75 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">printf("received SIGIO signal./n");</code>
</div>
<div class="line number77 index76 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">wait_flag = FALSE;</code>
</div>
<div class="line number78 index77 alt1"><code class="xhtml plain">}</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p><span><strong>3.4 等待来自多个信号来源的输入</strong></span></p>
<p>这一段很短. 它只能被拿来当成写程序时的提示, 故范例程序也很简短. 但这个范例不只能用在序列埠上, 还可以用在被当成文档来使用的装置上.</p>
<p>select 呼叫及伴随它所引发的巨集共用 fd_set. fd_set 则是一个位元阵列, 而其中每一个位元代表一个有效的文档叙述结构. select 呼叫接受一个有效的文档叙述结构并传回 fd_set 位元阵列, 而该位元阵列中若有某一个位元为 1, 就表示相对映的文档叙述结构的文档发生了输入, 输出或有例外事件. 而这些巨集提供了所有处理 fd_set 的功能. 亦可参考手册 select(2).</p>
<div class="jb51code">
<div><div id="highlighter_431324" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number3 index2 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number4 index3 alt1"> </div>
<div class="line number5 index4 alt2"><code class="xhtml plain">main()</code></div>
<div class="line number6 index5 alt1"><code class="xhtml plain">{</code></div>
<div class="line number7 index6 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">int fd1, fd2; /* 输入源 1 及 2 */</code>
</div>
<div class="line number8 index7 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd_set readfs; /* 文档叙述结构设定 */</code>
</div>
<div class="line number9 index8 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">int maxfd; /* 最大可用的文档叙述结构 */</code>
</div>
<div class="line number10 index9 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">int loop=1; /* 回圈在 TRUE 时成立 */ </code>
</div>
<div class="line number11 index10 alt2"> </div>
<div class="line number12 index11 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* open_input_source 开启一个装置, 正确的设定好序列埠,</code>
</div>
<div class="line number13 index12 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">并回传回此文档叙述结构体 */</code>
</div>
<div class="line number14 index13 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd1 = open_input_source("/dev/ttyS1"); /* COM2 */</code>
</div>
<div class="line number15 index14 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd1<0) exit(0);</code>
</div>
<div class="line number16 index15 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd2 = open_input_source("/dev/ttyS2"); /* COM3 */</code>
</div>
<div class="line number17 index16 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd2<0) exit(0);</code>
</div>
<div class="line number18 index17 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">maxfd = MAX (fd1, fd2)+1; /* 测试最大位元输入 (fd) */</code>
</div>
<div class="line number19 index18 alt2"> </div>
<div class="line number20 index19 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* 输入回圈 */</code>
</div>
<div class="line number21 index20 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">while (loop) {</code>
</div>
<div class="line number22 index21 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">FD_SET(fd1, &readfs); /* 测试输入源 1 */</code>
</div>
<div class="line number23 index22 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">FD_SET(fd2, &readfs); /* 测试输入源 2 */</code>
</div>
<div class="line number24 index23 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/* block until input becomes available */</code>
</div>
<div class="line number25 index24 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">select(maxfd, &readfs, NULL, NULL, NULL);</code>
</div>
<div class="line number26 index25 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (FD_ISSET(fd1)) /* 如果输入源 1 有信号 */</code>
</div>
<div class="line number27 index26 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">handle_input_from_source1();</code>
</div>
<div class="line number28 index27 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (FD_ISSET(fd2)) /* 如果输入源 2 有信号 */</code>
</div>
<div class="line number29 index28 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">handle_input_from_source2();</code>
</div>
<div class="line number30 index29 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">}</code>
</div>
<div class="line number31 index30 alt2"> </div>
<div class="line number32 index31 alt1"><code class="xhtml plain">}</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p>这个范例程序在等待输入信号出现前, 不能确定它会停顿下来. 如果你需要在输入时加入逾时功能, 只需把 select 呼叫换成:<br></p>
<div class="jb51code">
<div><div id="highlighter_258629" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">int res;</code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">struct timeval Timeout;</code></div>
<div class="line number3 index2 alt2"> </div>
<div class="line number4 index3 alt1"><code class="xhtml plain">/* 设定输入回圈的逾时值 */</code></div>
<div class="line number5 index4 alt2"><code class="xhtml plain">Timeout.tv_usec = 0; /* 毫秒 */</code></div>
<div class="line number6 index5 alt1"><code class="xhtml plain">Timeout.tv_sec = 1; /* 秒 */</code></div>
<div class="line number7 index6 alt2"><code class="xhtml plain">res = select(maxfd, &readfs, NULL, NULL, &Timeout);</code></div>
<div class="line number8 index7 alt1"><code class="xhtml plain">if (res==0)</code></div>
<div class="line number9 index8 alt2"><code class="xhtml plain">/* 文档叙述结构数在 input = 0 时, 会发生输入逾时. */</code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p>这个程序会在 1 秒钟后逾时. 如果超过时间, select 会传回 0, 但是应该留意 Timeout 的时间递减是由 select 所等待输入信号的时间为基准. 如果逾时的值是 0, select 会马上结束返回.</p>
<p>Linux 环境下使用RS-232接口 <br>
RS是英文 "推荐标准"的缩写 <br>
232为标识号 <br>
RS-485 <br>
串口通信表示计算机一次传送一个位的数据, <br>
当使用串行通信时,每个字的数据是一个位一个位的传输或接收的, <br>
每个位不是高电平,就是低电平. <br>
串行通信的速率通常是使用"位/每秒"的方式来表示的,即波特率。 <br>
全双工--计算机可以同时收发数据, <br>
它有两个独立的数据通道,一个输入,一个输出, <br>
半双工意味着计算机不能同时收发信息, <br>
只能有一人通道进行通信.</p>
<p>流控: <br>
<br>
通常,当数据在两个串行接口之间进行传输时需要对其进行控制. <br>
这通常依赖于串行通信连接的各种规定, <br>
对异步数据传输的控制有两种方法. <br>
一种叫:“软件”流控 。 <br>
一种叫: “硬件"流控 。</p>
<p>串口设备:</p>
<p>打开一个串行口</p>
<div class="jb51code">
<div><div id="highlighter_326118" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number2 index1 alt1"><code class="xhtml plain">#include </code></div>
<div class="line number3 index2 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number4 index3 alt1"><code class="xhtml plain">#include // 文件控制定义 </code></div>
<div class="line number5 index4 alt2"><code class="xhtml plain">#include </code></div>
<div class="line number6 index5 alt1"><code class="xhtml plain">#include //POSIX终端控制定义 </code></div>
<div class="line number7 index6 alt2"><code class="xhtml plain">/* </code></div>
<div class="line number8 index7 alt1"><code class="xhtml plain">* open_port() --打开串行口 </code></div>
<div class="line number9 index8 alt2"><code class="xhtml plain">* </code></div>
<div class="line number10 index9 alt1"><code class="xhtml plain">* 成功的话,返回文件描述符,错误则返回 -1. </code></div>
<div class="line number11 index10 alt2"><code class="xhtml plain">*/ </code></div>
<div class="line number12 index11 alt1"><code class="xhtml plain">int open_port(void) </code></div>
<div class="line number13 index12 alt2"><code class="xhtml plain">{ </code></div>
<div class="line number14 index13 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">int fd; </code>
</div>
<div class="line number15 index14 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY); </code>
</div>
<div class="line number16 index15 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (fd == -1) </code>
</div>
<div class="line number17 index16 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">{ </code>
</div>
<div class="line number18 index17 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">/*无法打开串口*/ </code>
</div>
<div class="line number19 index18 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">perror("open_port : Unable to open /dev/ttyS0"); </code>
</div>
<div class="line number20 index19 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">} </code>
</div>
<div class="line number21 index20 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">else </code>
</div>
<div class="line number22 index21 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">fcntl(fd,F_SETFL,0); </code>
</div>
<div class="line number23 index22 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">return (fd); </code>
</div>
<div class="line number24 index23 alt1"><code class="xhtml plain">} </code></div>
<div class="line number25 index24 alt2"><code class="xhtml plain">//O_NOCTTY 标志 ,该程序不想成为此端口的“控制终端"。 如果没有强调这一点, </code></div>
<div class="line number26 index25 alt1"><code class="xhtml plain">//O_NDELAY标志 , 标志告诉Linux ,该程序并不关注DCD信叼线所处的状态, 即不管另外一端的设备是在运行还是被挂起。如果没有指定该标志,那么程序就会被设置睡 眠状态, </code></div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p><span><strong>(2)向端口写数据 </strong></span></p>
<p>向端口写数据是很容易的,只要使用write()系统调用就可以了。</p>
<p>例如:</p>
<div class="jb51code">
<div><div id="highlighter_252910" class="syntaxhighlighterxhtml">
<div class="toolbar"><span>?</span></div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
</td>
<td class="code"><div class="container">
<div class="line number1 index0 alt2"><code class="xhtml plain">n=write(fd,"ATZ/r",4); </code></div>
<div class="line number2 index1 alt1">
<code class="xhtml spaces"> </code><code class="xhtml plain">if (n<0) </code>
</div>
<div class="line number3 index2 alt2">
<code class="xhtml spaces"> </code><code class="xhtml plain">fputs("write() of 4 bytes failed!/n",stderr); </code>
</div>
</div></td>
</tr></tbody></table>
</div></div>
<div class="codetool" id="codetool"><div class="code_n"><textarea></textarea></div></div>
</div>
<p> <br></p>
<p>write函数返回发送数据的个数,如果出现错误,则返回 -1。</p>
<p><span><strong>(3) 读端口数据 </strong></span></p>
<p>从端口读数据则需要些技巧。如果在原始数据的模式下对端口进行操作, read()系统调用将返回串行口输入缓冲区中所有的字符数据,不管有多少,如果没有数据,那么该调用将被阻塞.处于等待状态,直到有字符输入,</p>
<p>或者到了规定的时限和出现错误为止,通过以下方法,能使read函数立即返回。</p>
<p>fcntl(fd,F_SETFL,FNDELAY); <br>
FNDELAY 函数使read函数在端口没月字符存在的情况下,立刻返回0,</p>
<p>如果要恢复正常(阻塞)状态,可以调用fcntl()函数,不要FNDELAY参数,</p>
<p>如下所示: <br></p>
<p>fcntl(Fd,F_SETFL,0);</p>
<p>在使用O_NDELAY参数打开串行口后,同样与使用了该函数调用。</p>
<p>fcntl(fd,F_SETFL,0);</p>
<p>POSIX终端接口 串口,波特率,字符大小等, POSIX函数是 tcgetattr()和tcsetattr() 获取和设置终端的属性, 可以提供 structrure termios的指针</p>
<p>以上就是小编为大家带来的浅谈linux下的串口通讯开发全部内容了,希望大家多多支持~</p>
頁:
[1]