目录
序言
第一章 基本的串口通讯
什么是串口通讯
什么是RS-232
信号定义
异步通讯
什么是双工和单工
流量控制
什么是断开/break
同步通讯
访问串行端口
串行端口文件
打开串行端口
写入端口
读出端口
关闭端口
第二章 配置串行端口
POSIX终端接口
控制选项
本地选项
输入选项
输出选项
控制字符
第三章 Modem通讯
什么是Modem
与Modem通讯
标准Modem命令
常见的Modem通讯问题
第四章 高级串行端口编程
串行端口IOCTLs
获得控制信号
设置控制信号
获得有效字节数
从一个串行端口中选择输入
select系统调用
使用select系统调用
使用X Intrinsics库的Select接口
附录A.引出线
RS-232 引出线
RS-422 引出线
RS-574 (IBM PC/AT)引出线
SGI 引出线
附录B.控制符的ASCII编码
控制编码
序言
POSIX操作系统的串口编程指南将告诉你如何正确,有效,可移植地对PC上的Unix工作站的串行端口进行编程.每一章提供了 使用POSIX终端控制函数的程序范例,应该只需要进行少量的更动就可以在IRIX,HP-UX,SunOS,Solaris,DigitalUnix,Linux 和其它的Unix上运行.你将会发现,各个操作系统之间的最大区别仅仅是用于标志串口设备和锁文件的文件名不同.
该指南被组织成如下的章节和附录.
第一章 基本的串口通讯
第二章 配置串行端口
第三章 Modem通讯
第四章 高级串行端口编程
附录A.引出线
附录B.控制符的ASCII编码
第一章 基本的串口通讯
这一章介绍了串行通讯,RS-232和其它用于大多数计算机上的标准,同时引入了一个用于访问串口的C程序.
1.1 什么是串口通讯 ?
计算机在某一时间内会传送一个或多个位,而串口是一次一位地传送.串口通讯包括大多数网络设备,键盘,鼠标, 调制解调器和终端设备.
当使用串口通讯时,你发送或收到的每一个字,(比如一个字节或者一个字符),实际上都是一次一位地传送的.每一 位或者为on或者为off.之后你将听到的术语中,mark表示on,space表示off.
串行数据的速度经常用每秒位数(bps)或者波特率(baud)来表示.用来表示一秒中有多少1或者0被传送.在计算机 发明的初期,300baud被认为是很快的,而今天计算机的RS232可以达到430,800baud的速度!当波特率超过1,000时, 你通常会发现速率用千波特率,或kps(例如9,6k,19,2k).对于超过1,000,000的速率用兆波特率,或Mbps(例如1.5Mbps).
当提到串口设备或者端口时,它们或者被标记为数据通信设备("DCE")或者数据终端设备("DTE").两者的不同非常简单, 每一个信号对,比如发送和接收,被交换.当将两个DTE或者两个DCE接口连在一起,一个串行的用来交换信号对的 NULL-Modem电缆或适配器可以使用了.
1.2 什么是RS-232
RS-232是一种标准的用于EIA定义的串口通讯的电气接口.RS-232实际上由三个不同特点组成.每一个定义了不同 电压范围的on和off级别.常见的是RS-232C,定义mark位(on)指-3V到-12V之间的电压,space位指+3V到+12V之间的电压. RS-232C规范中指出这些信号可以发送到25英尺(约8米)远.如果波特率足够低的话,这些信号可以发送的更远些.
除了用于传输的线路,还要提供定时,状态和握手:
另外还有用于串口的两个标准,RS-422和RS-574.RS-422使用更低的电压和微分信号以电缆通讯长度达到将近1000英尺 (约300米).RS-574定义了9针的PC串口连接器和电压.
1.3 信号定义
RS-232标准定义了18个不同的用于串口通讯的信号.其中,仅有6个在Unix环境中是普遍适用的.
GND-逻辑地
严格地来说,逻辑地并不是信号,但是没有它其它的信号无法工作.逻辑地作为一个参照电压以致电器知道哪个电压是正哪些是负.
TXD-数据被发送
TXD信号承载从你的工作站发送到其它的机器或设备上的数据.mark电压表示1,space电压表示0.
RXD-被接收的数据
RXD信号承载从其它机器或设备上向你的工作站发送数据.类似TXD,mark和space电压分别表示1和0.
DCD-数据载波探测
DCD信号从串口电缆的另一端的机器或设备发送出来.串行线上的space电压表示机器或设备处于连线状态. DCD并不总是被用.
DTR-数据终端就绪
DTR信号是从你的工作站发送出来,告诉另一端的机器或设备你已经就绪或者尚未就绪,分别用space电压和mark电压表示.自从你的工作站打开串行接口之后DTR一直处于自动激活状态.
CTS-设备接收就绪,等待新的数据被发送 Clear to Send
CTS信号来自串行电缆的另一端.space电压表示你可以从你的工作站上发送更多数据了.(以前接收的已经处理完毕)
CTS常用来调节工作站与串行线另一端的数据传送流量.
RTS-请求发送
RTS信号被你的工作站置成space电压用来表示有更多的数据等待发送.
与CTS类似,RTS也是用来调节串行电缆两个终端之间的数据传送流量.大多数工作站把这个信号一直置为
space电压.
1.4 异步通讯
对于支持串行通讯的机器而言,它需要知道如何判别数据起始和终止.这篇指南将介绍异步串行数据.
在异步模式下,串行数据直到有字符被发送前一直保持mark状态.在每个字符之前有一开始位,紧接着是结束位,一个可选的奇偶位和若干个停止位.起始位总是space,告诉机器串行数据已经准备好了.数据可以在任何时候被发送或接收, 因此称之为异步的.
可选的奇偶位简单地统计数据中包含奇数个1还是偶数个1.如果有偶数个1,则这位为0,称偶校验位.如果是奇数个1,则 该位为0,称奇校验位.通常还有spaceparity,mark parity和no parity的说法.SpaceParity就是校验位总是0,markParity就是校验位总是1,NoParity表示不使用或不传输校验位.
接着的那位是终止位.在字符之间可以有1,1.5或2个终止位,它们的值总是1.以前终止位是为了让机器有更多的时间去处理前一个字符,但现在仅仅是用于在机器接收字符时的同步化.
异步数据格式通常用诸如"8N1","7E1"等等表示.前者表示8个数据位,没有校验位,1个终止位.后者表示7个数据位,偶校验位,1个终止位.
什么是全双工和单双工
全双工表示机器可以同时既发送数据又可以接收数据,有两个独立的数据通道(一进一出).
当双工表示机器不能在发送数据的同时又接收数据.通常这意味这仅仅有一个数据通道在使用.这并不意味RS-232的信号不能使用,而是通讯联接仅能使用不支持全双工操作的其它的标准,而不是RS-232.
流量控制
当在两个串行接口之间传输数据时通常有需要调节数据流量.这可能需要对之间的串行通讯联接,某个串行接口或者某个存储介质实行一些限制.对于异步数据通常有两种方法.
一是软件流量控制.使用特殊的字符去标志数据流的开始(XON,DC1,八进制的021或结束(XOFF,DC3,八进制的023).这些字符可以在ASCC中找到定义.然而当传输文本信息时这些字符拥有自身的含义,不能被使用.
另一种是硬件流量控制,用RS232的CTS和RTS信号代替特殊字符用于控制.当接收方准备接收更多的数据时,设置CTS为Space电压,反之设成Mark电压.对应的,当发送方准备发送更多的数据时,设置RTS为space电压.由于硬件的流量控制使用独立的一套信号,比软件的实现更快,因为作同样的工作,后者需要发送或接收多位信息.另外,并不是所有的硬件或操作系统都支持CTS/RTS流量控制.
什么时中断/Break?
一般而言,一个接收或者传输数据的信号直到一个新的字符被传送之前一直保持mark电压.如果信号过了很长时间后才被降低到space电压,通常时1/4到1/2秒,那么我们称这种状态为break./if the signal is dropped to the space voltage for a long period of time,.../
Break有时被用来重置通讯线路或者改变诸如Modem的通讯设备的工作模式.第三章的"如何操作Modem"将更深入地谈论这个问题.
1.5 同步通讯
与异步数据不同的是,同步数据是一种恒定的位流.为了从通讯线上读出数据,机器必须发送或者接收一个普通的位作为时钟以达到发送端和接收端的同步.
对于同步,机器必须标志数据的起始位置.实现它的最普通的方法时使用类似串行数据链路控制SDLC或者高速数据链路控制HDLC之类的数据包协议.
每一个协议定义了固定的位顺序以表示数据包的开始和结束,同时也定义了被用来表示没有数据时使用的位顺序.机器根据这些位顺序可以知道数据包的开始位.
因为同步协议不使用每个字符的同步位,所以它们一般能比异步通讯提高至少25%的性能,适合远程网络和两个以上的串行接口的配置.
尽管同步协议拥有速度优势,但大多数RS232硬件仍然由于额外的硬件和必要的软件而没有支持它.
1.6 访问串行端口
类似于所有设备,UNIX系统通过设备文件提供了对串行端口的访问.为了访问它,仅仅需要打开相应的设备文件.
串行端口文件
在UNIX系统的每一个串行端口都有一个或者更多的设备文件与它们相对应(在/dev/目录下).
Table2
打开串行端口
既然串行端口是一个文件,open(2)函数可以被用来访问它.UNIX系统的一个特点是一般用户无法访问设备文件.所以需要更改你所关心的设备文件的访问权限,以超级用户来运行程序或者在你的程序中使用setuid,从而拥有设备文件的访问权.
这里,我们假设该文件可以被所有用户访问.在运行IRIX的SGI工作站上打开串行端口的代码如下:
listing-1 open a serial port
#include <stdio.h> /*standard input/output definition */ #include <string.h> /*stringfunction definition */ #include <unistd.h> /*UNIX standard function definition */ #include <fcntl.h> /*File control definition */ #iclude <errno.h> /* Error number definition */ #include <termios.h> /*POSIX terminal control definition */ /* open_port() --open serail port 1 return the file descriptor on success or -1 on error */ int open_port(void) { int fd;/*File descriptor for the port */ fd = open("/dev/ttyf1",O_RDWR | O_NOCTTY | O_NDELAY ); if( fd == -1 ){ /*Could not open the port */ perror("open_port:Unable to open /dev/ttyf1 -"); } else fcntl(fd,F_SETFL,0); return fd; }
其他的系统需要更换设备文件名,代码是一样的.
端口的打开选项
你会发现当我们打开设备文件后,我们除了用读写模式外还用了另外两个标志:
fd = open("/dev/ttyf1",O_RDWR | O_NOCTTY | O_NDELAY );
O_NOCTTY标志告诉UNIX系统,这个程序不成为对应这个端口的控制终端,如果没有指定这个标志,那么任何一个输入,诸如
键盘中止信号等等,都将会影响你的进程.类似于getty的程序当启动login进程时都使用了这个特性,但是一个用户程序都
不需要这个特性.
O_NDELAY标志告诉UNIX系统这个程序不关心DCD信号线所处的状态---whether the other end of the port is up and running
如果你想指定这个标志,你的进程将会一直处在睡眠态直到DCD信号线是Space电压.
写数据到端口
写数据到端口很简单,就是用write(2)系统调用把数据发送出去.
n = write(fd,"ATZ\r",4);
if( n < 0 )
fputs("write() of 4 bytes failed!\n",stderr);
write返回有多少个字节被发送出去,如果出错,则返回为-1.通常你可能遇到的唯一的错误是EIO,当MODEM或者数据链路
撤销数据载波探测时会出现这种情况,这种情况将一直存在直到你关闭端口.
从端口中读取数据
从端口中读出数据有些技巧.当年在RAW数据模式下操作时,每一个read(2)系统调用将返回当前串行输入缓存区中存在的
字符数.如果没有字符,这个系统调用将一直阻塞到有字符到达或者间隔时钟过期,或者错误发生.read函数如下设置后将会
立即返回.
fcntl(fd,F_SETFL,FNDELAY);
FNDELAY选项将导致当端口上没有字符可读时,read函数返回0恢复到一般状态,调用fcntl时不带FNDELAY选项.
fcntl(fd,F_SETFL,0);
在用O_NDELAY打开端口之后也可以这样来恢复.
关闭串行端口
为了关闭串行端口,只需要使用close系统调用
close(fd);
关闭串行端口经常会设置DTR信号为低,导致大多数的MODEM挂起.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zeroless/archive/2006/01/10/575457.aspx
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zeroless/archive/2006/01/10/575457.aspx
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zeroless/archive/2006/01/10/575457.aspx