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:
- Base address:
- Byte transmitted register. Accessed when writing and DLAB = 0.
- Byte received register. Accessed when reading and DLAB = 0.
- Low byte of the divisor latch register (baud rate). Accessed when
reading or writing with DLAB = 1.
- Base address + 1:
- High byte of the divisor latch register (baud rate). Accessed when
reading or writing with DLAB = 1.
- Interrupt enable register. Accessed when reading or writing with DLAB
= 0.
- Base address + 2:
- Interrupt identification register. Accessed when reading.
- FIFO control register. Accessed when writing.
- Base address + 3:
- Line control register (data bits, parity, stop bits, DLAB). Accessed
when reading or writing.
- Base address + 4:
- Modem control register (DTR, RTS). Accessed when reading or writing.
- Base address + 5:
- Line status register (parity error, etc.). Accessed when reading.
- Base address + 6:
- Modem status register (CTS, DSR, RI, DCD). Accessed when reading.
- Base address + 7:
- Scratch register. Accessed when reading or writing.
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):
- Base address + 4:
- Bit 0: 1 = DTR positive, 0 = DTR negative.
- Bit 1: 1 = RTS positive, 0 = RTS negative.
- Base address + 6:
- Bit 4: 1 = CTS positive, 0 = CTS negative.
- Bit 5: 1 = DSR positive, 0 = DSR negative.
- Bit 6: 1 = RI positive, 0 = RI negative.
- Bit 7: 1 = DCD positive, 0 = DCD negative.
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 ***
40 WEND
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: http://www.gae.ucm.es/~padilla/extrawork/serial.html
Go to the parent page: Specifications of useful PC
ports.