分类:
2012-12-07 16:36:12
原文地址:终端IO编程B(《Linux编程技术详解》第6章) 作者:yuchuan2008
6.6 串口通信的基本概念
Linux系统通过串口终端设备文件来实现对串口设备的访问。串口是计算机上常见的接口,往往用于调试设备和连接一些对传输速度要求不高的设备。本节将介绍如何在Linux系统中编写C程序来访问串口,并进行读写操作。
6.6.1 串行通信与串口定义
串口的数据传输是以串行方式进行的。串口在数据通信中,一次只传输一个比特的数据。串行数据的传输速度用bps或波特率来描述。串行通信设备也被称为数据通信设备(DCE,Data Communication Equipment)或数据终端设备(DTE,Data Terminal Equipment)。
常用的串口是RS-232C接口(又称EIA RS-232C),是一个25脚的DB25连接器。RS-232C定义的传输长度为8m,具体的引脚定义如表6.8所示。
表6.8 RS-232C引脚定义
引 脚 |
操 作 |
符 号 |
数 据 流 向 |
说 明 |
2 |
发送数据 |
TXD |
DTE→DCE |
DTE发送数据 |
3 |
接收数据 |
RXD |
DTE←DCE |
DTE接收数据 |
4 |
请求发送数据 |
RTS |
DTE→DCE |
DTE请求DCE切换到发送方式 |
5 |
允许发送数据 |
CTS |
DTE←DCE |
DCE通告DTE线路准备好,可以发送数据 |
6 |
数据设备准备好 |
DSR |
DTE←DCE |
DCE准备好 |
7 |
接地 |
|
|
信号地 |
8 |
载波检测 |
DCD |
DTE←DCE |
DCE接收到远程载波 |
20 |
数据终端准备好 |
DTR |
DTE→DCE |
DTE准备好 |
22 |
振铃提示 |
RI |
DTE←DCE |
DCE与线路接通,开始振铃 |
6.6.2 串口通信的基本参数
串口一般用于ASCII码字符的传输。最基本的串口通信只需3个引脚即可实现,分别是地线、接收和发送。其他引脚用于握手协议。由于串口通信属于异步通信,可以在进行通信时不使用握手协议。
为了正确实现串口间的通信,必须对串口的参数进行设置。图6.13所示为使用Windows中的超级终端进行串口通信时设置参数的界面。参数具体说明如下:
图6.13 串口通信参数设置
1.每秒位数
即波特率。该参数表示每秒传输的比特数。例如,对于发送端,2400波特率表示每秒发送2400bit;对于接收端而言,2400波特率意味着串口通信在数据线上的采样率为2400Hz。由于波特率和距离之间成反比,距离相隔很近的设备间才可以实现高波特率通信。
2.数据位
表示通信中实际数据位的参数。在计算机发送的数据包中,实际的数据往往不会是8位。在串口通信中,可以选择5、6、7或8位,如图6.14所示。设定数据位主要考虑所要传输的数据内容。如果要传输的是标准的ASCII码,由于ASCII码的范围是0~127,因此使用7位就可以了。如果要传输的是扩展ASCII码,其范围是0~255,必须使用8位。当然,7位或8位数据位中不仅仅是数据,还包括开始/停止位、数据位以及奇偶校验位等。
3.奇偶校验位
该位用于串口通信中的简单检错。奇偶校验位主要有:偶校验、奇校验、标记、空格的方式,也可以不使用校验,如图6.15所示。奇/偶校验是通过统计数据中高位或低位的个数来实现校验的。而标记、空格并不真正检测数据,只是通过简单的置位来实现对数据的检测。通过置位方式,可以判断出是否存在噪声干扰数据通信或数据传输,以及接收是否存在不同步的现象。
图6.14 数据位设置
图6.15 奇偶校验位设置
4.停止位
停止位用于标志该数据包数据结束,可以取1位、1.5位或2位,如图6.16所示。停止位不仅仅用于数据包的传输结束标志,还提供了计算机之间校正同步时钟的机会。用于停止位的位数越多,不同时钟同步的容忍程度越大。但是由于停止位占用了数据空间,过多的停止位将导致数据传输速度的下降。
5.数据流控制
通过串口传输数据时,由于计算机之间处理速度或其他因素的影响,会造成丢失数据的现象。例如,台式机与单片机之间的通信,接收端数据缓冲区已满的情况下,继续收到数据,新发送来的数据就会由于无法处理造成丢失。数据流控制用于解决这个问题。通过控制发送数据的速度,确保数据不会出现丢失。
数据流控制可以分为软件流控制(Xon/Xoff)和硬件流控制,如图6.17所示,也可以选择不使用数据流控制。软件流控制使用特殊的字符作为启动或停止的标志。而硬件流控制通过使用硬件信号(CTR/RTS)来实现。使用硬件流控制时,在接收端准备好接收数据后,设定CTS为1,否则CTS为0。同样,如果发送端准备好要发送数据,则设定RTS为1;如果还未准备好,设置CTS为0。
图6.16 停止位设置
图6.17 数据流控制设置
6.7 在Linux下进行串口通信
在Linux系统中,串口设备是通过串口终端设备文件来访问的,也就是通过访问/dev/ttyS0、/dev/ttyS1、/dev/ttyS2、/dev/ttyS3这些设备文件实现对串口的访问。对串口进行读写要经过下面几个步骤。
6.7.1 打开串口
与打开文件类似,打开串口同样使用open函数。注意对于串口的打开操作,必须使用O_NOCTTY参数。该参数表示:如果打开的是一个终端设备,程序不会成为对应这个端口的控制终端。如果没有使用该标志,任何一个输入(例如,键盘中止信号等)都将影响进程。具体代码如下:
|
6.7.2 设置串口通信参数
串口通信参数指的是波特率、数据位、奇偶校验位和停止位。对串口实现控制的时候同样要用到termio结构体。下面将结合具体的代码说明如何设置这些参数。
1.波特率设置
获得端口波特率信息是通过cfgetispeed函数和cfgetospeed函数来实现的。cfgetispeed函数用于获得结构体termios_p中的输入波特率信息,而cfgetospeed函数用于获得结构体termios_p中的输出波特率信息。这两个函数的具体信息如表6.9所示。
表6.9 cfgetispeed函数和cfgetospeed函数
头文件 |
| ||
函数形式 |
speed_t cfgetispeed(const struct termios *termios_p); speed_t cfgetospeed(const struct termios *termios_p); | ||
返回值 |
成功 |
失败 |
是否设置errno |
返回termios_p结构中的输入/输出端口的波特率 |
−1 |
是 |
cfsetispeed函数和cfsetospeed函数用于设置端口的输入/输出波特率。一般情况下,输入和输出波特率是相等的。cfsetispeed函数和cfsetospeed函数的函数声明信息如表6.10所示。
表6.10 cfsetispeed函数和cfsetospeed函数
头文件 |
| ||
函数形式 |
int cfsetispeed(struct termios *termios_p, speed_t speed); int cfsetospeed(struct termios *termios_p, speed_t speed); | ||
返回值 |
成功 |
失败 |
是否设置errno |
返回termios_p结构中的输入/输出端口的波特率 |
−1 |
是 |
cfsetispeed函数和cfsetospeed函数会修改结构体termios_p中的波特率信息,其中参数speed可以使用表6.11中所列出的宏。
表6.11 speed参数常用波特率信息
宏 定 义 |
波特率(单位:bit/s) |
宏 定 义 |
波特率(单位:bit/s) |
B0 |
0 |
B1800 |
1800 |
B50 |
50 |
B2400 |
2400 |
B75 |
75 |
B4800 |
4800 |
B110 |
110 |
B9600 |
9600 |
B134 |
134 |
B19200 |
19200 |
B150 |
150 |
B38400 |
38400 |
B200 |
200 |
B57600 |
57600 |
B300 |
300 |
B115200 |
115200 |
B600 |
600 |
B230400 |
230400 |
B1200 |
1200 |
|
|
使用cfsetispeed函数和cfsetospeed函数进行串口波特率设置具体代码如下所示:
#include |
2.数据位
数据位指的是每字节中实际数据所占的比特数。要修改数据位可以通过修改termios结构体中c_cflag成员来实现。CS5、CS6、CS7和CS8分别表示数据位为5、6、7和8。值得注意的是,在设置数据位时,必须先使用CSIZE做位屏蔽。具体设置代码如下:
|
3.奇偶校验位
奇偶校验可以选择偶校验、奇校验、空格等方式,也可以不使用校验。如果要设置为偶校验的话,首先要将termios结构体中c_cflag设置PARENB标志,并清除PARODD标志。如果要设置奇校验,要同时设置termios结构体中c_cflag设置PARENB标志和PARODD标志。如果不想使用任何校验的话,清除termios结构体中c_cflag的PARENB位。表6.12所示为设置奇偶校验的具体方法。
表6.12 设置奇偶校验位
设 置 |
具 体 代 码 |
无校验 |
opt.c_cflag &= ~PARENB; |
奇校验 |
opt.c_cflag |= (PARODD | PARENB); |
偶校验 |
opt.c_cflag &= ~ PARENB; opt.c_cflag &= ~PARODD; |
空格 |
opt.c_cflag &= ~PARENB; opt.c_cflag &= ~CSTOPB; |
下面给出将串口通信的奇偶校验设置为偶校验的例子,具体代码如下:
#include |
4.数据流控制
数据流控制指是使用何种方法来标志数据传输的开始和结束。可以选择不使用数据流控制、使用硬件进行流控制和使用软件进行流控制。数据流控制设置如表6.13所示。
表6.13 数据流控制设置
设 置 |
具 体 代 码 |
不使用数据流控制 |
opt.c_cflag &= ~CRTSCTS |
硬件 |
opt.c_cflag |= CRTSCTS |
软件 |
opt.c_cflag | = IXON|IXOFF|IXANY |
由于使用硬件流控制需要相应连接的电缆,常用的流控制方法还是使用软件进行流控制。下面给出了设置不使用数据流控制的相关代码:
|
6.7.3 读写串口
读写串口是通过使用read函数和write函数实现的。在Linux系统中,对设备的读写类似于对文件的读写。下面给出对串口的写操作的代码:
|
6.7.4 关闭串口
在完成对设备文件读写操作后,需要调用close函数关闭该文件描述符。