串行通信基础

来源:互联网 发布:县域经济金融数据库 编辑:程序博客网 时间:2024/05/01 17:58

串口通信基础

5th Edition

Michael R. Sweet

本章主要介绍串口通信、RS-232和其他一些用于大多数计算机的标准以及怎样通过C语言访问串口。

1.什么是串行通信?

计算机传输数据时每次传输1个或多个比特(bit)。串行通信每次传输一个比特的数据。串行通信包含大多数的网络设备,键盘,鼠标,调制解调器和终端等。

当你用串行方式发送或接受数据时每次仅传输一位。每一位代表onoff。通常1代表ON状态,0代表OFF状态。

串行数据传输速率通常用比特每秒(bps)或波特率表示(baud)。这代表每秒传输01的个数。在计算机发展的开始阶段,300波特被认为是相当快的,但是现在应用RS232的计算机的传输速度可达430,800波特。波特率超过1000时,通常表示成千波特(kilo baud),或kbps(例如:9.6k, 19.2k等等)。波特率超过1,000,000时可以用兆波特或Mbps(如1.5Mbps)来表示。

串行设备或端口被称为数据通讯设备或数据终端设备,它们之间的区别很简单,一个发送,一个接受,实现信息交换。当把两个DTE或两个DCE接口相连,实现了串行无调制解调器电缆或适配器的信号交互

2.什么是RS-232

RS-232EIA定义的串行通信的标准电气接口。常说的RS-232是电子工业协会EIA(Electronic Industries Association)定义的串行通信电气标准。RS-232根据电压的范围分为ABC三类。最常用的是RS-232C,用-3V-12V表示mark(on),用+3V+12V表示space(off)RS-232C标准指出信号的传输距离大约为8m。在波特足够低的时候信号通常可以传的稍远一些。

除了线路发送和接收数据外,还支持时间选择、状态、和握手。

除此之外其他标准还有RS-422RS-574RS-422采用低电压和差分信号,传输距离可达300左右。RS-574则是9-pin 串行连接器和电压的标准。

信号定义

RS-232标准定义了18种不同的信号。其中有6种是在UNIX环境中可用的。(关于引脚的定义请参见表1

GND-逻辑接地

从技术上讲,逻辑接地不是信号,但是如果没有它其他信号将无法工作。实际上   逻辑接地是一个参考电平用来定义其他信号的正负。

TXD 数据发送

TXD信号从工作站向计算机或其他终端(如MODEM)设备发送数据(发送信号)。高电平为1,低电平为0

RXD 数据接收

RXD信号是接收信号,像TXD信号一样高电平为1,低电平为0

引脚

描述

引脚

描述

1

14

辅助TXD

2

TXD - 数据发送

15

发送时钟

3

RXD - 数据接收

16

辅助 RXD

4

RTS - 请求发送

17

接受时钟

5

CTS -清除发送

18

未分配

6

DSR - 数据就绪

19

辅助RTS

7

GND -逻辑接地

20

DTR – 数据终端就绪

8

DCD -数据载波检测

21

信号质量检测

9

保留

22

环形检测

10

保留

23

数据速率选择

11

未分配

24

传送时钟

12

辅助DCD

25

未分配

13

辅助CTS

 

 

1-RS232 引脚分配

DCD 数据载波检测

DCD信号是从串行线路的另一端收到的信号。0电平表示两台设备当前是连通的。DCD信号并不总是有效。

DTR 数据终端就绪

DTR由数据终端产生的用来表示是否就绪,0表示就绪,1表示没有就绪。DTR信号通常在你打开串口时自动有效。

CTS 清除发送

CTS信号来自另一端,0电平表示你可以发送数据。CTS通常用来控制两个设备间的串行数据流。

RTS 请求发送

RTS信号是请求发送信号,它设置为0表示有数据要发送。

CTS一样,RTS也是用来控制设备间的串行数据流。多数设备都将该信号始终设置为0

异步通信

对计算机来说,进行串行通信需要确定一个字符的结束和下一个的开始。这是异步通信独有的特点。

在异步通信模式中串行数据保持1状态直道一个字符被传送。起始位在每个字符的前面,然后紧接着是一个可选的校验位,和一个或多个停止位。起始位总是为0,它用来告诉计算机可以传送新数据。数据可以在任何时候发送和接收,所以称为异步通信。

1 - 异步数据传输

 

可选的校验位就是一个简单的数据位,用来表明数据保护奇数或偶数个1。偶校验时,如果数据中已经有偶数个1,则校验位为0。奇校验时,当数据中有奇数个1时校验位设置为0。经常听到的术语还有:0校验,1校验,无校验。0校验时校验位总是被设置为0,而1校验则是把校验位总是设置为1。无校验就是没有校验位。

其余的位称作停止位。停止位可以设置为1个、1.5个或2bit,他总是被设置为1。停止位传统上是让计算机有时间去处理前面的字符,但是现在仅仅是用来使计算机接收数据同步。

异步数据格式通常表示成"8N1", "7E1"等等。意思分别是“8个数据位,无校验位,1个停止位”,“7个数据位,偶校验,1个停止位”。

什么是全双工和半双工?

全双工的意思是计算机可以同时接收和发送数据,也就是说其拥有两条独立的信道(一条用来接收,另一条用来发送)。

半双工的意思是计算机不能同时接收和发送数据。通常这意味着仅有一条信道用来通信。这并不是说不使用任何RS-232信号。更确切的说通信链路用了其他一些标准除了不支持全双工通信RS-232标准外。

流量控制

当两个串行设备传输数据时,控制流量是非常必要的。这是由于中间的串行通信线路,串行口或存储介质的限制。在异步通信中通常使用两种方法。

第一种方法通常叫做软件流量控制,它用专门的字符来启动(XONDC1021 八进制)或停止(XOFF DC3, 023 八进制)数据流。这些字符定义在美国标准信息交换码(ASCII码)中。在传送文本信息时这些控制字符是非常有用的,但是如果不对其进行专门的编程控制,这些控制字符是不能用于其他格式的信息传送的。

第二中方法是硬件流量控制,用RS-232标准中的CTSRTS信号来代替专门控制字符。接收方当准备好接收数据时就将CTS信号设置成0电平,没有准备好就设置为1电平。同样,发送方当准备好发送数据时,就将RTS设置成0电平,没有准备好就将其设置为1电平。因为硬件流量控制使用的是专门的信号设置,所以他比软件方式快的多,因为软件要完成同样的任务需要发送和接收额外的数据来完成。CTS/RTS流量控制并没有被所有的硬件和操作系统支持。

什么是停顿

正常情况下一个数据接收或发送信号保持在高电平,直到一个新数据要传送。如果这个信号跳变到低电平并持续一个较长的时钟周期通常是1/41/2秒,便说明这是一个停顿状态。

Break有时用作复位或改变通信设备的操作模式,例如调制解调器。(在第三章谈一下调制解调器中将作更深入的讨论)

同步通信

不像异步通信那样,同步通信数据向一系列的持续的比特流。为了读取线路上的数据,计算机必须提供或接收一个(同步位)来使接收端和发送端同步。

即使在同步通信中,计算机也必须标记数据的开始。最常用的做法是用规定协议的数据包,像串行数据链路控制协议(“SDLC”)或高速数据链路控制协议(“HDLC”)。

每个协议定义特定的数据位序列来代表数据包的起始和结束。而且也定义了位序列表示没有数据。这些数据序列使计算机能识别数据包的起始。

因为同步协议没有每个字符的同步位,他通常比异步传输提高25%的性能。这适合远程网络和多于两个串行设备的配置中。

尽管速度上有优势,但是大多数RS-232硬件都不支持同步通信协议,这是由于他需要额外的软硬件。

访问串口

像所有设备一样,UNIX通过访问设备文件来访问串口。要访问串口你只需简单的打开相应的设备文件。

串口文件

UNIX系统上每个串口都有一个或多个设备文件(该文件在/dev目录下)与之关联。

系统

端口1

端口2

IRIX®

/dev/ttyf1

/dev/ttyf2

HP-UX

/dev/tty1p0

/dev/tty2p0

Solaris®/SunOS®

/dev/ttya

/dev/ttyb

Linux®

/dev/ttyS0

/dev/ttyS1

Digital UNIX®

/dev/tty01

/dev/tty02

2-串口设备文件

打开串口

因为串口就是一个文件,所以用open(2)函数来访问即可。但UNIX下有一个限制就是设备文件通常普通用户是不能访问的。工作区包括包含上述改变访问控制权限的文件,你可以使程序运行在超级用户下(root)或设置程序的userid以使其成为设备的拥有者。

现在我们假定文件可以被所有用户访问。下面的代码用来打开一个运行着IRIX 系统的sgi®工作站的串口1

Listing 1 - Opening a serial port.

#include <stdio.h>   /* Standard input/output definitions */

#include <string.h>  /* String function definitions */

#include <unistd.h>  /* UNIX standard function definitions */

#include <fcntl.h>   /* File control definitions */

#include <errno.h>   /* Error number definitions */

#include <termios.h> /* POSIX terminal control definitions */

 

/*

 * 'open_port()' - Open serial port 1.

 *

 * Returns 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(1M/8)程序用了这个特性,当启动登录进程时,但是正常用户程序一般不需要这个功能。

O_NDELAY标志告诉UNIX程序将不关心DCD信号,不管另一端串口设备是否正在运行。如果你没有指定这个标志,你的程序将一直处于休眠状态直到DCD信号置为0

向端口写数据

向端口写数据是非常简单的,使用系统调用write(2)来发送数据就行了。

n = write(fd, "ATZ/r", 4);

if (n < 0)

{

      fputs("write() of 4 bytes failed!/n", stderr);

}

函数write返回发送的字节输,如果中间发生错误则返回-1。通常EIO是仅有的错误,就是当调制解调器吊线的时候。这种情况将持续直到你关闭串口。

从串口读取数据

从串口读取数据有点棘手。当你在原始数据模式下操作串口时,每个系统调用将返回许多字符存放在输入缓冲区中。如果没有字符,接收进程将阻塞,直到有新字符到达、超时或有错误发生。read函数通过下面这样也可以即时返回:

fcntl(fd, F_SETFL, FNDELAY);

FNDELAY选项的应用使得read函数在串口没有字符到达时返回0。要想恢复到通常的阻塞行为,调用没有FNDELAY选项的fcntl()即可:

fcntl(fd, F_SETFL, 0);

这个函数同样用于通过O_NDELAY选项打开串行端口

关闭串口

用系统调用close可以关闭串口:

close(fd);

关闭串口通常设置DTR信号地电平,这将使调制解调器挂起。

 英文原文:

Basics of Serial Communications

This chapter introduces serial communications, RS-232 and other standards that are used on most computers as well as how to access a serial port from a C program.

What Are Serial Communications?

Computers transfer information (data) one or more bits at a time. Serial refers to the transfer of data one bit at a time. Serial communications include most network devices, keyboards, mice, MODEMs, and terminals.

When doing serial communications each word (i.e. byte or character) of data you send or receive is sent one bit at a time. Each bit is either on or off. The terms you'll hear sometimes are mark for the on state and space for the off state.

The speed of the serial data is most often expressed as bits-per-second ("bps") or baudot rate ("baud"). This just represents the number of ones and zeroes that can be sent in one second. Back at the dawn of the computer age, 300 baud was considered fast, but today computers can handle RS-232 speeds as high as 430,800 baud! When the baud rate exceeds 1,000, you'll usually see the rate shown in kilo baud, or kbps (e.g. 9.6k, 19.2k, etc). For rates above 1,000,000 that rate is shown in megabaud, or Mbps (e.g. 1.5Mbps).

When referring to serial devices or ports, they are either labeled as Data Communications Equipment ("DCE") or Data Terminal Equipment ("DTE"). The difference between these is simple - every signal pair, like transmit and receive, is swapped. When connecting two DTE or two DCE interfaces together, a serial null-MODEM cable or adapter is used that swaps the signal pairs.

What Is RS-232?

RS-232 is a standard electrical interface for serial communications defined by the Electronic Industries Association ("EIA"). RS-232 actually comes in 3 different flavors (A, B, and C) with each one defining a different voltage range for the on and off levels. The most commonly used variety is RS-232C, which defines a mark (on) bit as a voltage between -3V and -12V and a space (off) bit as a voltage between +3V and +12V. The RS-232C specification says these signals can go about 25 feet (8m) before they become unusable. You can usually send signals a bit farther than this as long as the baud is low enough.

Besides wires for incoming and outgoing data, there are others that provide timing, status, and handshaking:

Table 1 - RS-232 Pin Assignments

Pin

Description

Pin

Description

1

Earth Ground

14

Secondary TXD

2

TXD - Transmitted Data

15

Transmit Clock

3

RXD - Received Data

16

Secondary RXD

4

RTS - Request To Send

17

Receiver Clock

5

CTS - Clear To Send

18

Unassigned

6

DSR - Data Set Ready

19

Secondary RTS

7

GND - Logic Ground

20

DTR - Data Terminal Ready

8

DCD - Data Carrier Detect

21

Signal Quality Detect

9

Reserved

22

Ring Detect

10

Reserved

23

Data Rate Select

11

Unassigned

24

Transmit Clock

12

Secondary DCD

25

Unassigned

13

Secondary CTS

 

 

 

Two standards for serial interfaces you may also see are RS-422 and RS-574. RS-422 uses lower voltages and differential signals to allow cable lengths up to about 1000ft (300m). RS-574 defines the 9-pin PC serial connector and voltages.

Signal Definitions

The RS-232 standard defines some 18 different signals for serial communications. Of these, only six are generally available in the UNIX environment.

GND - Logic Ground

Technically the logic ground is not a signal, but without it none of the other signals will operate. Basically, the logic ground acts as a reference voltage so that the electronics know which voltages are positive or negative.

TXD - Transmitted Data

The TXD signal carries data transmitted from your workstation to the computer or device on the other end (like a MODEM). A mark voltage is interpreted as a value of 1, while a space voltage is interpreted as a value of 0.

RXD - Received Data

The RXD signal carries data transmitted from the computer or device on the other end to your workstation. Like TXD, mark and space voltages are interpreted as 1 and 0, respectively.

DCD - Data Carrier Detect

The DCD signal is received from the computer or device on the other end of your serial cable. A space voltage on this signal line indicates that the computer or device is currently connected or on line. DCD is not always used or available.

DTR - Data Terminal Ready

The DTR signal is generated by your workstation and tells the computer or device on the other end that you are ready (a space voltage) or not-ready (a mark voltage). DTR is usually enabled automatically whenever you open the serial interface on the workstation.

CTS - Clear To Send

The CTS signal is received from the other end of the serial cable. A space voltage indicates that is alright to send more serial data from your workstation.

CTS is usually used to regulate the flow of serial data from your workstation to the other end.

RTS - Request To Send

The RTS signal is set to the space voltage by your workstation to indicate that more data is ready to be sent.

Like CTS, RTS helps to regulate the flow of data between your workstation and the computer or device on the other end of the serial cable. Most workstations leave this signal set to the space voltage all the time.

Asynchronous Communications

For the computer to understand the serial data coming into it, it needs some way to determine where one character ends and the next begins. This guide deals exclusively with asynchronous serial data.

In asynchronous mode the serial data line stays in the mark (1) state until a character is transmitted. A start bit precedes each character and is followed immediately by each bit in the character, an optional parity bit, and one or more stop bits. The start bit is always a space (0) and tells the computer that new serial data is available. Data can be sent or received at any time, thus the name asynchronous.

Figure 1 - Asynchronous Data Transmission

The optional parity bit is a simple sum of the data bits indicating whether or not the data contains an even or odd number of 1 bits. With even parity, the parity bit is 0 if there is an even number of 1's in the character. With odd parity, the parity bit is 0 if there is an odd number of 1's in the data. You may also hear the terms space parity, mark parity, and no parity. Space parity means that the parity bit is always 0, while mark parity means the bit is always 1. No parity means that no parity bit is present or transmitted.

The remaining bits are called stop bits. There can be 1, 1.5, or 2 stop bits between characters and they always have a value of 1. Stop bits traditionally were used to give the computer time to process the previous character, but now only serve to synchronize the receiving computer to the incoming characters.

Asynchronous data formats are usually expressed as "8N1", "7E1", and so forth. These stand for "8 data bits, no parity, 1 stop bit" and "7 data bits, even parity, 1 stop bit" respectively.

What Are Full Duplex and Half Duplex?

Full duplex means that the computer can send and receive data simultaneously - there are two separate data channels (one coming in, one going out).

Half duplex means that the computer cannot send or receive data at the same time. Usually this means there is only a single data channel to talk over. This does not mean that any of the RS-232 signals are not used. Rather, it usually means that the communications link uses some standard other than RS-232 that does not support full duplex operation.

Flow Control

It is often necessary to regulate the flow of data when transferring data between two serial interfaces. This can be due to limitations in an intermediate serial communications link, one of the serial interfaces, or some storage media. Two methods are commonly used for asynchronous data.

The first method is often called "software" flow control and uses special characters to start (XON or DC1, 021 octal) or stop (XOFF or DC3, 023 octal) the flow of data. These characters are defined in the American Standard Code for Information Interchange ("ASCII"). While these codes are useful when transferring textual information, they cannot be used when transferring other types of information without special programming.

The second method is called "hardware" flow control and uses the RS-232 CTS and RTS signals instead of special characters. The receiver sets CTS to the space voltage when it is ready to receive more data and to the mark voltage when it is not ready. Likewise, the sender sets RTS to the space voltage when it is ready to send more data. Because hardware flow control uses a separate set of signals, it is much faster than software flow control which needs to send or receive multiple bits of information to do the same thing. CTS/RTS flow control is not supported by all hardware or operating systems.

What Is a Break?

Normally a receive or transmit data signal stays at the mark voltage until a new character is transferred. If the signal is dropped to the space voltage for a long period of time, usually 1/4 to 1/2 second, then a break condition is said to exist.

A break is sometimes used to reset a communications line or change the operating mode of communications hardware like a MODEM. Chapter 3, Talking to Modems covers these applications in more depth.

Synchronous Communications

Unlike asynchronous data, synchronous data appears as a constant stream of bits. To read the data on the line, the computer must provide or receive a common bit clock so that both the sender and receiver are synchronized.

Even with this synchronization, the computer must mark the beginning of the data somehow. The most common way of doing this is to use a data packet protocol like Serial Data Link Control ("SDLC") or High-Speed Data Link Control ("HDLC").

Each protocol defines certain bit sequences to represent the beginning and end of a data packet. Each also defines a bit sequence that is used when there is no data. These bit sequences allow the computer see the beginning of a data packet.

Because synchronous protocols do not use per-character synchronization bits they typically provide at least a 25% improvement in performance over asynchronous communications and are suitable for remote networking and configurations with more than two serial interfaces.

Despite the speed advantages of synchronous communications, most RS-232 hardware does not support it due to the extra hardware and software required.

Accessing Serial Ports

Like all devices, UNIX provides access to serial ports via device files. To access a serial port you simply open the corresponding device file.

Serial Port Files

Each serial port on a UNIX system has one or more device files (files in the /dev directory) associated with it:

Table 2 - Serial Port Device Files

System

Port 1

Port 2

IRIX®

/dev/ttyf1

/dev/ttyf2

HP-UX

/dev/tty1p0

/dev/tty2p0

Solaris®/SunOS®

/dev/ttya

/dev/ttyb

Linux®

/dev/ttyS0

/dev/ttyS1

Digital UNIX®

/dev/tty01

/dev/tty02

 

Opening a Serial Port

Since a serial port is a file, the open(2) function is used to access it. The one hitch with UNIX is that device files are usually not accessible by normal users. Workarounds include changing the access permissions to the file(s) in question, running your program as the super-user (root), or making your program set-userid so that it runs as the owner of the device file.

For now we'll assume that the file is accessible by all users. The code to open serial port 1 on an sgi® workstation running IRIX is:

Listing 1 - Opening a serial port.

#include <stdio.h>   /* Standard input/output definitions */

#include <string.h>  /* String function definitions */

#include <unistd.h>  /* UNIX standard function definitions */

#include <fcntl.h>   /* File control definitions */

#include <errno.h>   /* Error number definitions */

#include <termios.h> /* POSIX terminal control definitions */

 

/*

 * 'open_port()' - Open serial port 1.

 *

 * Returns 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);

}

Other systems would require the corresponding device file name, but otherwise the code is the same.

Open Options

You'll notice that when we opened the device file we used two other flags along with the read+write mode:

fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);

The O_NOCTTY flag tells UNIX that this program doesn't want to be the "controlling terminal" for that port. If you don't specify this then any input (such as keyboard abort signals and so forth) will affect your process. Programs like getty(1M/8) use this feature when starting the login process, but normally a user program does not want this behavior.

The O_NDELAY flag tells UNIX that this program doesn't care what state the DCD signal line is in - whether the other end of the port is up and running. If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.

Writing Data to the Port

Writing data to the port is easy - just use the write(2) system call to send data it:

n = write(fd, "ATZ/r", 4);

if (n < 0)

    fputs("write() of 4 bytes failed!/n", stderr);

The write function returns the number of bytes sent or -1 if an error occurred. Usually the only error you'll run into is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line. This condition will persist until you close the port.

Reading Data from the Port

Reading data from a port is a little trickier. When you operate the port in raw data mode, each read(2) system call will return however many characters are actually available in the serial input buffers. If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs. The read function can be made to return immediately by doing the following:

fcntl(fd, F_SETFL, FNDELAY);

The FNDELAY option causes the read function to return 0 if no characters are available on the port. To restore normal (blocking) behavior, call fcntl() without the FNDELAY option:

fcntl(fd, F_SETFL, 0);

This is also used after opening a serial port with the O_NDELAY option.

Closing a Serial Port

To close the serial port, just use the close system call:

close(fd);

Closing a serial port will also usually set the DTR signal low which causes most MODEMs to hang up.

 

原创粉丝点击