See also, Part Two and
Part Three
Normally, 'digital' data input into a
PC is just that – you
use your digits; just two of them in my case, as I
have never graduated beyond the two fingered school
of typing. However, there are other ways to get data
into and out of your PC – infra-red ports, network
cards, the USB (Universal Serial Bus) and of course
the good old-fashioned serial and parallel ports. The
serial port and parallel port are typically used to
connect either a modem or a printer to your PC. However,
you can use them for other purposes. For example, you
can use the parallel port to control other hardware – train
sets, automated dog walkers and other such useful devices.
You can also use the serial port to perform the same
functions – and that is
what I’ll be looking at this month.
Since the serial and parallel ports can perform the
same types of functions in controlling external devices
(other than printers and modems, of course), why use
one rather than the other? Well, as with most things,
it’s horses for courses. The parallel port is better
at transferring lots of data – it has eight signal
lines compared with a serial port’s one. The parallel
port also produces data signals directly at the usual
logic levels of 3V or 5V. With the serial port you have
to decode the data stream into characters and it operates
at a rather inconvenient 10V. You have to use a level
converter to get down to logic chip voltages. On the
other hand, the serial port can operate over much larger
distances than a parallel port – and most importantly
- it has fewer wires.
At first sight, the idea of fewer wires being better
might seem crazy. But unless you like long sessions with
a soldering iron, fewer is definitely better: it takes
a lot, lot longer to debug wires than it does
a program – believe me, cut-and-paste
isn’t too good when you're working with solder-and-chips.
If you’ve
just spent a few days swearing at a particularly obscure
software problem, then a few soldered connections might
seem trivial by comparison. However, digital hardware
has one characteristic that may not be apparent to programmers – it
isn’t digital! Glitches, cross-talk, voltage spikes
and things that go bump in the night are par for the
hardware course. Not for nothing does the excellent book
on ‘how to do it’ electronics, “The
Art of Electronics” by Horowitz and Hill,
contain the word ‘art’!
Null modem
Here are two computers
connected in different ways. The first uses two modems
and the public telephone system, while the second eliminates
both the modems and the telephone network.
A) two computers connected via the public network |
B) two computers connected
via a null-modem cable |
Comm with two m’s There’s another good reason for using the serial
port rather than the parallel port. First, the parallel
port is often used for its original purpose – printing.
And with Windows 98 and beyond, it can be quite difficult
to persuade the operating system that you really don’t
want to have a printer; with Windows XP, you need the
device driver kit to communicate directly with a parallel
port. But also, many PCs have two serial ports as well
as a dedicated mouse port. This means that you can connect
the two ports ‘back-to-back’ for testing.
This is important – testing communications hardware
can be tricky. Just making sure that your cable is wired
up ok and that the PC end of things is working is a major
step towards a successful project. Finally, Visual Basic
comes with a ready made component for handling communication
ports, the MsComm control.
MsComm is a simplification of the underlying API calls
for controlling a communication port. And, while it does
quite a bit of what I want it to do, it has some restrictions
which mean I’ll have to move to using the full
API calls later on. But for now, I’ll use MsComm
to test out the serial ports and, just as importantly,
the wire between them. To do this, I’ll set up
one communication port, COM1 say, to write data to the
other port, COM2.
The way to do this is to connect the two ports together
using a ‘null-modem cable’. This rather odd
term comes from the idea that two serial ports are normally
connected together over the telephone network using a
two modems, one at either end. If you want to connect
two computers locally, then it’s expensive to use
your telephone company to do the job; it’s cheaper
and easier to use a simple cable. Actually, while the
cable may be cheap, it’s not that simple. The intricacies
of a null-modem cable are as good a place as any to sort
out what all those pins do in a serial port. You have
to understand these or the operation of the MsComm control
(and its limitations) won’t make very much sense.
Here’s
the basic communications program with communications
events caused by RTS and DTR switching shown in the EventLog
window.
Communicating - the basics
Serial communication is a heart quite a simple idea.
There are three pins that are important. Data is transmitted
over one pin (Transmit Data or TXD for short) and received
over another pin (Receive Data or RXD). The data is sent
sequentially as a series of on-off pulses down the wire,
so a byte will take eight bits or pulses to transmit.
In fact, there are one or two other bits needed
as well for synchronisation and error checking, but that’s
the basics. The third wire that’s needed is the
Ground wire (GND) – these are electrical signals
and so need a return path. While you can get away with
just three wires, it’s often useful to have other
control signals to make things easier for the software.
There are six other signals: Ring Indicator (RI) is set
by a modem when it detects an incoming call. Carrier
Detect (CD) is again set by the modem when it detects
another modem as the originator of the incoming call.
For a null-modem, RI and CD can are ignored.
This leaves four other signals which come in pairs.
Request To Send (RTS) and Clear To Send (CTS) are used
by the PC to signal that it is ready to write or read
data respectively. Data Terminal Ready (DTR) and Data
Set Ready (DSR) do a similar sort of job (there are actually
finer details of what these signals should be used for – but
that needn’t bother us here). So for our null-modem
purposes there are three pairs of wires – and these
need to be ‘crossed over’ for the two ports
to communicate. That is, the RCD pin of one port must
be connected to the TXD pin of the second and so on.
This means that when COM1 transmits data (on TXD) COM2
will receive data on RCD. The complete wiring between
the two connectors looks like:
COM1 |
COM2 |
RCD |
2 |
TXD |
3 |
TXD |
3 |
RCD |
2 |
DTR |
4 |
DSR |
6 |
GND |
5 |
GND |
5 |
DSR |
6 |
DTR |
4 |
RTS |
7 |
CTS |
8 |
CTS |
8 |
RTS |
7 |
If you’re confident with a soldering iron you
can get the parts separately and wire them up or if you’d
rather leave it to an expert, get a ready made cable – though
check out the type of ports of the back of your PC first.
Older PCs tend to have one 25 pin port and one 9 pin
port – all of the above wiring refers to the more
modern 9-pin varieties.
OK, so assuming you’re equipped with a suitable
null-modem cable and you’ve plugged it into the
two ports what next? One way to check that everything
is working OK is to use two HyperTerminal sessions, one
connected to COM1 the other to COM2 with exactly the
same speed settings. You should be able to type from
one screen to the other with no trouble. Another way
(more interesting, of course!) is to use a Visual Basic
program.
I’ve written a simple program using mostly the
default settings of the two communication ports to illustrate
how events are communicated back to Visual Basic. In
the program COMMS.VBP, there are two text boxes that
display the input received on the respective port and
two sets of buttons that toggle DTR and RTS. There’s
also an Initialize button that opens the ports and sets
off a polling loop. The code initially sets COM1 and
COM2 up in a similar manner with both RTS and DTR off:
With MSComm1 .DTREnable = False .RTSEnable = False .CommPort = 1 .PortOpen = True End With
Once set up the program just polls for input:
Do While MSComm1.PortOpen And MSComm2.PortOpen s1 = MSComm1.Input s2 = MSComm2.Input If s1 <> "" Then Port2.Text = Port2.Text & s1 ElseIf s2 <> "" Then Port1.Text = Port1.Text & s2 Else DoEvents End If Loop
There are two things to notice about this simple loop.
First, the loop condition tests to see if the ports are
still open. If you don’t do this, you will get
an annoying error when you close the program. For some
reason, Visual Basic seems to close the ports before
unloading the form. Secondly, the DoEvents keyword ‘releases’ the
program to look for other things – such as a button
click or a communication event.
In the DTR (and RTS) toggle code, you’ll see
this:
With MSComm1 .PortOpen = False If .DTREnable = False Then .DTREnable = True Else .DTREnable = False End If .PortOpen = True End With
These communication events (DSR corresponding to DTR
and CTS corresponding to RTS) events are detected in
the OnComm event code:
Private Sub MSComm1_OnComm() EventLog.Text = EventLog.Text & "Port1: " _
& CommEventText(MSComm1.CommEvent) & vbCrLf End Sub
and just written to the EventLog window.
All this looks pretty neat and simple but there’s
a ‘gotcha’: to set a control signal (say,
RTS) you have to close the port, set RTS and then reopen
it. This is disastrous if you are communicating with
some hardware that isn’t really a modem – you
can lose data in the small interval while the port is
closed.
The problem is that the operating system uses these
control wires to signal to the modem that your program
is ready (that’s the main use of DTR) and it uses
the RTS/CTS wires to implement hardware flow control.
Normally, you’d be quite happy with this – but
not if you want to control your patent dog-walker (or
train set) directly. I’ll look at this next month.
Pins and Names
The diagram shows the pin connections (pinouts) of
a 9-way serial port. Each pin has a two of three letter
mnemonic as follows:
Pin
# |
Mnemonic |
Full name |
1 |
CD |
Carrier Detect |
2 |
RCD |
Receive Data |
3 |
TXD |
Transmit Data |
4 |
DTR |
Data Terminal Ready |
5 |
GND |
Ground |
6 |
DSR |
Data Set Ready |
7 |
RTS |
Request To Send |
8 |
CTS |
Clear To Send |
9 |
RI |
Ring Indicator |
Copyright © 2005 Dermot Hogan
June 2005 |