Serial port


L. Padilla


The serial port is, by far, the most commonly used port, and not only in PCs. It was designed for long distance communications and so it was fundamental to use as less cables as possible. To establish a successful connection using serial ports only 2 cables are needed for a one-way data flow (or for a half-duplex communication) and 3 cables for a full-duplex communication (software handshaking). However it is common the use of other lines, specially for short distance connections (hardware handshaking). The maximum cable length varies from 80 to 900 meters for data speeds between 19,200 and 110 bauds, although it depends on its quality.

Physical layer

The communication is physically controlled by an integrated circuit called Universal Asynchronous Receiver-Transmitter (UART). Typical UARTs are the 8250, 8251, 16450 and 16550. Today most of the serial ports you can find (included PCs and its devices) follow the Recommended Standard 232, revision C (RS-232-C). It uses inverse logic and so a logic 0 is an output between +5 and +25 Volts or an input between +3 and +25 Volts. A logic 1 is an output between -5 and -25 Volts or an input between -3 and -25 Volts. By default the serial port asserts the negative level in all of its output lines. The input impedance can be approximated by a resistance of around 500 Ohms in parallel with a capacitor of around 30 nF. Between two real RS-232-C compatibles lines can be left opened or short-circuited with any other line without risk of damage. If they get damaged at least you know they weren't real RS-232-C compatibles :-)

Serial ports come in two flavors: Data Terminal Equipment (DTE) and Data Communications Equipment (DCE). The first type is intended to be at both ends of a communication line and so typical DTEs are computers, terminals and printers. DCEs are intended to be in the middle of the communication chain and so the modem is a classical DCE. Lately it has been common to use male connectors for DTEs and female connectors for DCEs, however there is no real consensus on that yet, so the only way to know what kind of port you are dealing with is to read the manual of the device or experimenting. A DTE transmits in the line which the DCE listens to and vice-versa. Here is the pin-out of a DTE RS-232-C (PC port), the pin-out of a DCE is complementary to the DTE.

              DB-25P (male)                          DB-9P (male)

  1  2  3  4  5  6  7  8  9 10 11 12 13              1  2  3  4  5
_________________________________________          _________________
\ .  .  .  .  .  .  .  .  .  .  .  .  . /          \ .  .  .  .  . /
 \ .  .  .  .  .  .  .  .  .  .  .  .  /            \ .  .  .  .  /
  \___________________________________/              \___________/
  14 15 16 17 18 19 20 21 22 23 24 25                 6  7  8  9

             DB-25P pin-out                          DB-9P pin-out
  ------------------------------------               -------------
  (o) pin  2 Transmit Data       (TxD)               (i) pin 1 DCD
  (i) pin  3 Receive Data        (RxD)               (i) pin 2 RxD
  (o) pin  4 Request To Send     (RTS)               (o) pin 3 TxD
  (i) pin  5 Clear To Send       (CTS)               (o) pin 4 DTR
  (i) pin  6 Data Set Ready      (DSR)               (-) pin 5 GND
  (-) pin  7 Ground              (GND)               (i) pin 6 DSR
  (i) pin  8 Data Carrier Detect (DCD)               (o) pin 7 RTS
  (o) pin 20 Data Terminal Ready (DTR)               (i) pin 8 CTS
  (i) pin 22 Ring Indicator      (RI)                (i) pin 9 RI
      Rest of pins not connected

      (o) = pin is for output
      (i) = pin is for input
      (-) = pin is common reference

If you want to connect two devices through a serial port you have to know what kind they are. If they are a DTE and a DCE, like in a PC-modem connection, then there is no problem. You just have to connect them in a pin-by-pin basis, pin 1 with pin 1, pin 2 with pin 2, etc. However if they both are the same type, with the previous cable you will never get them to communicate. You have to exchange complementary lines, and that is what a null-modem cable does. Depending on the software you will have to switch certain lines, but if you do it for all of them you will be sure that any software will run with such a cable. Here is the scheme of a null-modem cable for all the possible connector combinations, note that DCD is shorted with DSR and RI is left open (unconnected).

    DB-25          DB-25     DB-9          DB-9     DB-25          DB-9
    --------------------     ------------------     -------------------
TxD  2 ------\/------  2     3 ------\/------ 3      2 ------\/------ 3 TxD
RxD  3 ------/\------  3     2 ------/\------ 2      3 ------/\------ 2 RxD

DCD  8 --\        /--  8     1 --\        /-- 1      8 --\        /-- 1 DCD
DSR  6 ---\--\/--/---  6     6 ---\--\/--/--- 6      6 ---\--\/--/--- 6 DSR
DTR 20 ------/\------ 20     4 ------/\------ 4     20 ------/\------ 4 DTR

CTS  5 ------\/------  5     8 ------\/------ 8      5 ------\/------ 8 CTS
RTS  4 ------/\------  4     7 ------/\------ 7      4 ------/\------ 7 RTS

RI  22 --|        |-- 22     9 --|        |-- 9     22 --|        |-- 9 RI

The bits of every byte are sent in series, that is, one after the other, starting with the Least Significant Bit (LSB) and ending with the Most Significant Bit (MSB). Each byte of data is preceded by a logic 0 (start bit), also called a Space (S) and is followed by a logic 1 (stop bit), also called a Mark (M). The port can be configured to send bytes of 5, 6, 7 or 8 bits with or without parity bit, thought if bytes of 8 bits are selected then no parity bit is allowed. The parity bit can be configured to be even, odd, space (always 0), mark (always 1) or none. It can also be selected the length of the stop bit to be 1, 1.5 or 2 bits long, thought I have found that when 1.5 stop bits are selected it actually uses 2 stop bits (it may depend on the UART). The most common configuration of the serial port is 8 data bits, no parity bit and 1 stop bit. In this case the sending of the bytes 01hex and FEhex would look like:

            LSB                         MSB         LSB                         MSB
 Rest   StB  1   0   0   0   0   0   0   0  SpB StB  0   1   1   1   1   1   1   1  SpB   Rest
        ___     ___ ___ ___ ___ ___ ___ ___     ___ ___
       |   |   |                           |   |       |
___ ___|   |___|                           |___|       |___ ___ ___ ___ ___ ___ ___ ___ ___ ___
 M   M   S   M   S   S   S   S   S   S   S   M   S   S   M   M   M   M   M   M   M   M   M   M

Rest = Default state of the line (mark)
StB  = Start bit (space)
SpB  = Stop  bit (mark)

The final parameter which must be configured is the speed, which ranges from 50 to 115,200 bauds. Bauds means symbols per second, certain devices like modems can send several bits per symbol and so not always X bauds means X bits per second. Imagine for example that a modem could send 1 out of 4 frequencies (symbols) in a communication. This would mean that it sends 2 bits per symbol and so if the modem works at X bauds it is sending 2 * X bits per second. But even that is not completely true as long as we can see in the example above that 2 bits (start and stop bits) per byte contain no information. They are included for synchronization purposes only. A more accurate calculation of the information sent per unit of time can be estimated noting that we send 10 bits (only 8 with information) per byte. Then if a PC is working at 19,200 bauds it is sending 1,920 bytes per second. Note that this is true for a PC (in which each symbol contains only 1 bit, positive or negative voltage of the line) configured as mentioned above. For other configurations just follow the same reasoning.

Using the port

The serial port can be configured using the DOS command MODE, the Control Panel of Windows or any communications utility. Then it can be used to send and receive data with DOS (through redirection), Windows or any communications program. However you can easily write your own applications. The are two ways to do this. One is to use the high level commands or routines which can be found in most of the programming languages, such as BASIC or C. Many times you can use the serial port as it was a file or the standard input or output. This is a very easy way to use the serial port within your programs, however it may be quite inefficient.

The PC BIOS routines are far from optimal and will not be able to reach the highest data speeds. Using low level languages (not necessarily assembler) you can write your own routines to get the top speed of 115,200 bauds. You can even write routines to handle interruptions from the port and this will let you have communications in the background. However this document will not go into the deep details of the UART programming, for that you should look elsewhere on the Web or buy a book. I will briefly describe the basics of the UART control for the purposes of simple interfacing, i.e., using the control lines rather than the serial line.

The UART is controlled writing to and reading from its registers which are accessed through 8 port addresses. The base addresses are 03F8h, 02F8h, 03E8h and 02E8h for ports COM1, COM2, COM3 and COM4 respectively. The meaning of each port address is the following:

The important port addresses for simple interfacing are those which control the input (CTS, DSR, RI, DCD) and output (DTR, RTS) lines. The ports and the meaning of the bits are the following, where bit 0 is the LSB and bit 7 is the MSB (note that the control lines do not follow inverse logic):

Using the commands and routines which every programming language has to read from and write to the ports, you can set and check the status of the control lines of the serial port. This will let you interface with your own devices, for example you can open/close a relay which feeds a motor, a light, etc.; or you can check if a cable has been cut (alarm) or a switch has been activated, etc. For instance, if you want to monitor the status of the RI line of COM1 and activate RTS when RI is activated, you can do it with a BASIC program like the following:

10 WHILE 1 : REM *** Endless loop ***
20 RI = INP (&h03FE) AND &h40 : REM *** Read port and mask bit for RI ***
30 IF (RI <> 0) THEN GOTO 50 : REM *** Check if RI is activated ***
50 OUT &h03FC, &h02 : REM *** Activate RTS ***
60 END

E-mail: padilla at domain "gae ucm es" (my PGP/GPG public key)
First version: 9-Jun-1997, last update: 28-Aug-2002
This link:
Color line
Back Go to the parent page: Specifications of useful PC ports.