Beruflich Dokumente
Kultur Dokumente
o 4 - Architectural Overview
o 5 - USB Data Flow Model
o 9 - USB Device Frame Work, and
o 10 - USB Host Hardware and Software.
Peripheral hardware (Electronics) designers on the other hand may only need to read
chapters,
o 4 - Architectural Overview
o 5 - USB Data Flow Model
o 6 - Mechanical, and
o 7 - Electrical.
The Universal Serial Bus is host controlled. There can only be one host per bus. The
specification in itself, does not support any form of multimaster arrangement. However
the On-The-Go specification which is a tack on standard to USB 2.0 has introduced a Host
Negotiation Protocol which allows two devices negotiate for the role of host. This is
aimed at and limited to single point to point connections such as a mobile phone and
personal organiser and not multiple hub, multiple device desktop configurations. The
USB host is responsible for undertaking all transactions and scheduling bandwidth. Data
can be sent by various transaction methods using a token-based protocol.
In my view the bus topology of USB is somewhat limiting. One of the original intentions
of USB was to reduce the amount of cabling at the back of your PC. Apple people will say
the idea came from the Apple Desktop Bus, where both the keyboard, mouse and some
other peripherals could be connected together (daisy chained) using the one cable.
However USB uses a tiered star topology, simular to that of 10BaseT Ethernet. This
imposes the use of a hub somewhere, which adds to greater expense, more boxes on
your desktop and more cables. However it is not as bad as it may seem. Many devices
have USB hubs integrated into them. For example, your keyboard may contain a hub
which is connected to your computer. Your mouse and other devices such as your digital
camera can be plugged easily into the back of your keyboard. Monitors are just another
peripheral on a long list which commonly have in-built hubs.
This tiered star topology, rather than simply daisy chaining devices together has some
benefits. Firstly power to each device can be monitored and even switched off if an
overcurrent condition occurs without disrupting other USB devices. Both high, full and
low speed devices can be supported, with the hub filtering out high speed and full speed
transactions so lower speed devices do not receive them.
Up to 127 devices can be connected to any one USB bus at any one given time. Need
more devices? - simply add another port/host. While most earlier USB hosts had two
ports, most manufacturers have seen this as limiting and are starting to introduce 4 and
5 port host cards with an internal port for hard disks etc. The early hosts had one USB
controller and thus both ports shared the same available USB bandwidth. As bandwidth
requirements grew, we are starting to see multi-port cards with two or more controllers
allowing individual channels.
The USB host controllers have their own specifications. With USB 1.1, there were two
Host Controller Interface Specifications, UHCI (Universal Host Controller Interface)
developed by Intel which puts more of the burden on software (Microsoft) and allowing
for cheaper hardware and the OHCI (Open Host Controller Interface) developed by
Compaq, Microsoft and National Semiconductor which places more of the burden on
hardware(Intel) and makes for simpler software. Typical hardware / software engineer
relationship. . .
With the introduction of USB 2.0 a new Host Controller Interface Specification was
needed to describe the register level details specific to USB 2.0. The EHCI (Enhanced
Host Controller Interface) was born. Significant Contributors include Intel, Compaq, NEC,
Lucent and Microsoft so it would hopefully seem they have pooled together to provide us
one interface standard and thus only one new driver to implement in our operating
systems. Its about time.
USB as its name would suggest is a serial bus. It uses 4 shielded wires of which two are
power (+5v & GND). The remaining two are twisted pair differential data signals. It uses
a NRZI (Non Return to Zero Invert) encoding scheme to send data with a sync field to
synchronise the host and receiver clocks.
USB supports plug’n’plug with dynamically loadable and unloadable drivers. The user
simply plugs the device into the bus. The host will detect this addition, interrogate the
newly inserted device and load the appropriate driver all in the time it takes the
hourglass to blink on your screen provided a driver is installed for your device. The end
user needs not worry about terminations, terms such as IRQs and port addresses, or
rebooting the computer. Once the user is finished, they can simply lug the cable out, the
host will detect its absence and automatically unload the driver.
The loading of the appropriate driver is done using a PID/VID (Product ID/Vendor ID)
combination. The VID is supplied by the USB Implementor's forum at a cost and this is
seen as another sticking point for USB. The latest info on fees can be found on the USB
Implementor’s Website
Other standards organisations provide a extra VID for non-commercial activities such as
teaching, research or fiddling (The Hobbyist). The USB Implementors forum has yet to
provide this service. In these cases you may wish to use one assigned to your
development system's manufacturer. For example most chip manufacturers will have a
VID/PID combination you can use for your chips which is known not to exist as a
commercial device. Other chip manufacturers can even sell you a PID to use with their
VID for your commercial device.
Another more notable feature of USB, is its transfer modes. USB supports Control,
Interrupt, Bulk and Isochronous transfers. While we will look at the other transfer modes
later, Isochronous allows a device to reserve a defined amount of bandwidth with
guaranteed latency. This is ideal in Audio or Video applications where congestion may
cause loss of data or frames to drop. Each transfer mode provides the designer trade-
offs in areas such as error detection and recovery, guaranteed latency and bandwidth.
Connectors
All devices have an upstream connection to the host and all hosts have a downstream
connection to the device. Upstream and downstream connectors are not mechanically
interchangeable, thus eliminating illegal loopback connections at hubs such as a
downstream port connected to a downstream port. There are commonly two types of
connectors, called type A and type B which are shown below.
Electrical
Unless you are designing the silicon for a USB device/transceiver or USB host/hub, there
is not all that much you need to know about the electrical specifications in chapter 7. We
briefly address the essential points here.
As we have discussed, USB uses a differential transmission pair for data. This is encoded
using NRZI and is bit stuffed to ensure adequate transitions in the data stream. On low
and full speed devices, a differential ‘1’ is transmitted by pulling D+ over 2.8V with a
15K ohm resistor pulled to ground and D- under 0.3V with a 1.5K ohm resistor pulled to
3.6V. A differential ‘0’ on the other hand is a D- greater than 2.8V and a D+ less than
0.3V with the same appropriate pull down/up resistors.
The receiver defines a differential ‘1’ as D+ 200mV greater than D- and a differential ‘0’
as D+ 200mV less than D-. The polarity of the signal is inverted depending on the speed
of the bus. Therefore the terms ‘J’ and ‘K’ states are used in signifying the logic levels. In
low speed a ‘J’ state is a differential 0. In high speed a ‘J’ state is a differential 1.
USB transceivers will have both differential and single ended outputs. Certain bus states
are indicated by single ended signals on D+, D- or both. For example a single ended zero
or SE0 can be used to signify a device reset if held for more than 10mS. A SE0 is
generated by holding both D- and D+ low (< 0.3V). Single ended and differential outputs
are important to note if you are using a transceiver and FPGA as your USB device. You
cannot get away with sampling just the differential output.
The low speed/full speed bus has a characteristic impedance of 90 ohms +/- 15%. It is
therefore important to observe the datasheet when selecting impedance matching series
resistors for D+ and D-. Any good datasheet should specify these values and tolerances.
High Speed (480Mbits/s) mode uses a 17.78mA constant current for signalling to reduce
noise.
Speed Identification
A USB device must indicate its speed by pulling either the D+ or D- line high to 3.3 volts.
A full speed device, pictured below will use a pull up resistor attached to D+ to specify
itself as a full speed device. These pull up resistors at the device end will also be used by
the host or hub to detect the presence of a device connected to its port. Without a pull
up resistor, USB assumes there is nothing connected to the bus. Some devices have this
resistor built into its silicon, which can be turned on and off under firmware control,
others require an external resistor.
For example Philips Semiconductor has a SoftConnectTM technology. When first
connected to the bus, this allows the microcontroller to initialise the USB function device
before it enables the pull up speed identification resistor, indicating a device is attached
to the bus. If the pull up resistor was connected to Vbus, then this would indicate a device
has been connected to the bus as soon as the plug is inserted. The host may then
attempt to reset the device and ask for a descriptor when the microprocessor hasn’t
even started to initialise the usb function device.
Other vendors such as Cypress Semiconductor also use a programmable resistor for Re-
NumerationTM purposes in their EzUSB devices where the one device can be enumerated
for one function such as In field programming then be disconnected from the bus under
firmware control, and enumerate as another different device, all without the user lifting
an eyelid. Many of the EzUSB devices do not have any Flash or OTP ROM to store code.
They are bootstraped at connection.
Figure 2 : Full Speed Device with pull up resistor connected to D+
Low power bus powered functions draw all its power from the VBUS and cannot draw any
more than one unit load. The USB specification defines a unit load as 100mA. Low power
bus powered functions must also be designed to work down to a VBUS voltage of 4.40V
and up to a maximum voltage of 5.25V measured at the upsteam plug of the device. For
many 3.3V devices, LDO regulators are mandatory.
High power bus powered functions will draw all its power from the bus and cannot draw
more than one unit load until it has been configured, after which it can then drain 5 unit
loads (500mA Max) provided it asked for this in its descriptor. High power bus functions
must be able to be detected and enumerated at a minimum 4.40V. When operating at a
full unit load, a minimum VBUS of 4.75 V is specified with a maximum of 5.25V. Once
again, these measurements are taken at the upstream plug.
Self power functions may draw up to 1 unit load from the bus and derive the rest of it’s
power from an external source. Should this external source fail, it must have provisions
in place to draw no more than 1 unit load from the bus. Self powered functions are easier
to design to specification as there is not so much of an issue with power consumption.
The 1 unit bus powered load allows the detection and enumeration of devices without
mains/secondary power applied.
No USB device, whether bus powered or self powered can drive the VBUS on its upstream
facing port. If VBUS is lost, the device has a lengthy 10 seconds to remove power from the
D+/D- pull-up resistors used for speed identification.
Other VBUS considerations are the Inrush current which must be limited. This is outlined in
the USB specification paragraph 7.2.4.1 and is commonly overlooked. Inrush current is
contributed to the amount of capacitance on your device between VBUS and ground. The
spec therefore specifies that the maximum decoupling capacitance you can have on
your device is 10uF. When you disconnect the device after current is flowing through the
inductive USB cable, a large flyback voltage can occur on the open end of the cable. To
prevent this, a 1uF minimum VBUS decoupling capacitance is specified.
For the typical bus powered device, it can not drain any more than 500mA which is not
unreasonable. So what is the complication you ask? Perhaps Suspend Mode?
Suspend Current
Suspend mode is mandatory on all devices. During suspend, additional constrains come
into force. The maximum suspend current is proportional to the unit load. For a 1 unit
load device (default) the maximum suspend current is 500uA. This includes current from
the pull up resistors on the bus. At the hub, both D- and D+ have pull down resistors of
15K ohms. For the purposes of power consumption, the pull down resistor at the device
is in series with the 1.5K ohms pull up, making a total load of 16.5K ohms on a VTERM of
typically 3.3v. Therefore this resistor sinks 200uA before we even start.
Another consideration for many devices is the 3.3V regulator. Many of the USB devices
run on 3.3V. The PDIUSBD11 is one such example. Linear regulators are typically quite
inefficient with average quiescent currents in the order of 600uA, therefore more
efficient and thus expensive regulators are called for. In the majority of cases, you must
also slow down or stop clocks on microcontrollers to fall within the 500uA limit.
Many developers ask in the USB Implementor's Forum, what are the complications of
exceeding this limit? It is understood, that most hosts and hubs don’t have the ability to
detect such an overload of this magnitude and thus if you drain maybe 5mA or even
10mA you should still be fine, bearing in mind that at the end of the day, your device
violates the USB specification. However in normal operation, if you try to exceed the
100mA or your designated permissible load, then expect the hub or host to detect this
and disconnect your device, in the interest of the integrity of the bus.
Of course these design issues can be avoided if you choose to design a self powered
device. Suspend currents may not be a great concern for desktop computers but with
the introduction of the On-The-Go Specification we will start seeing USB hosts built into
mobile phones and mobile organisers. The power consumption pulled from these devices
will adversely effect the operating life of the battery.
• A high speed bus will have micro-frames sent every 125.0 µs ±62.5 ns.
• A full speed bus will have a frame sent down each 1.000 ms ±500 ns.
• A low speed bus will have a keep alive which is a EOP (End of Packet) every 1ms only in the absence of
any low speed data.
The term "Global Suspend" is used when the entire USB bus enters suspend mode
collectively. However selected devices can be suspended by sending a command to the
hub that the device is connected too. This is referred to as a "Selective Suspend."
The device will resume operation when it receives any non idle signalling. If a device has
remote wakeup enabled then it may signal to the host to resume from suspend.
This allows resonators to be used for low cost low speed devices, but rules them out for
full or high speed devices.
USB Protocols
Unlike RS-232 and similar serial interfaces where the format of data being sent is not
defined, USB is made up of several layers of protocols. While this sounds complicated,
don’t give up now. Once you understand what is going on, you really only have to worry
about the higher level layers. In fact most USB controller I.C.s will take care of the lower
layer, thus making it almost invisible to the end designer.
Each USB transaction consists of a
As we have already discussed, USB is a host centric bus. The host initiates all
transactions. The first packet, also called a token is generated by the host to describe
what is to follow and whether the data transaction will be a read or write and what the
device’s address and designated endpoint is. The next packet is generally a data packet
carrying the payload and is followed by an handshaking packet, reporting if the data or
token was received successfully, or if the endpoint is stalled or not available to accept
data.
o Sync
All packets must start with a sync field. The sync field is 8 bits long at low
and full speed or 32 bits long for high speed and is used to synchronise the
clock of the receiver with that of the transmitter. The last two bits indicate
where the PID fields starts.
o PID
PID stands for Packet ID. This field is used to identify the type of packet that
is being sent. The following table shows the possible values.
Group PID Value Packet Identifier
Token 0001 OUT Token
1001 IN Token
0101 SOF Token
1101 SETUP Token
0011 DATA0
1011 DATA1
Data
0111 DATA2
1111 MDATA
0010 ACK Handshake
1010 NAK Handshake
Handshake
1110 STALL Handshake
0110 NYET (No Response Yet)
1100 PREamble
1100 ERR
Special
1000 Split
0100 Ping
There are 4 bits to the PID, however to insure it is received correctly, the 4
bits are complemented and repeated, making an 8 bit PID in total. The
resulting format is shown below.
PID0 PID1 PID2 PID3 nPID0 nPID1 nPID2 nPID3
o ADDR
The address field specifies which device the packet is designated for. Being 7
bits in length allows for 127 devices to be supported. Address 0 is not valid,
as any device which is not yet assigned an address must respond to packets
sent to address zero.
o ENDP
o CRC
Cyclic Redundancy Checks are performed on the data within the packet
payload. All token packets have a 5 bit CRC while data packets have a 16 bit
CRC.
o EOP
End of packet. Signalled by a Single Ended Zero (SE0) for approximately 2 bit
times followed by a J for 1 bit time.
In - Informs the USB device that the host wishes to read information.
Out - Informs the USB device that the host wishes to send information.
Setup - Used to begin control transfers.
o Data Packets
There are two types of data packets each capable of transmitting up to 1024
bytes of data.
Data0
Data1
High Speed mode defines another two data PIDs, DATA2 and MDATA.
Data packets have the following format,
Sync PID Data CRC16 EOP
There are three type of handshake packets which consist simply of the PID
The SOF packet consisting of an 11-bit frame number is sent by the host
every 1ms ± 500ns on a full speed bus or every 125 µs ± 0.0625 µs on a
high speed bus.
Frame
Sync PID CRC5 EOP
Number
USB Functions
When we think of a USB device, we think of a USB peripheral, but a USB device could
mean a USB transceiver device used at the host or peripheral, a USB Hub or Host
Controller IC device, or a USB peripheral device. The standard therefore makes
references to USB functions which can be seen as USB devices which provide a capability
or function such as a Printer, Zip Drive, Scanner, Modem or other peripheral.
So by now we should know the sort of things which make up a USB packet. No? You're
forgotten how many bits make up a PID field already? Well don't be too alarmed.
Fortunately most USB functions handle the low level USB protocols up to the transaction
layer (which we will cover next chapter) in silicon. The reason why we cover this
information is most USB function controllers will report errors such as PID Encoding Error.
Without briefly covering this, one could ask what is a PID Encoding Error? If you
suggested that the last four bits of the PID didn't match the inverse of the first four bits
then you would be right.
Most functions will have a series of buffers, typically 8 bytes long. Each buffer will belong
to an endpoint - EP0 IN, EP0 OUT etc. Say for example, the host sends a device
descriptor request. The function hardware will read the setup packet and determine from
the address field whether the packet is for itself, and if so will copy the payload of the
following data packet to the appropriate endpoint buffer dictated by the value in the
endpoint field of the setup token. It will then send a handshake packet to acknowledge
the reception of the byte and generate an internal interrupt within the
semiconductor/micro-controller for the appropriate endpoint signifying it has received a
packet. This is typically all done in hardware.
The software now gets an interrupt, and should read the contents of the endpoint buffer
and parse the device descriptor request.
Endpoints
Endpoints can be described as sources or sinks of data. As the bus is host centric,
endpoints occur at the end of the communications channel at the USB function. At the
software layer, your device driver may send a packet to your devices EP1 for example.
As the data is flowing out from the host, it will end up in the EP1 OUT buffer. Your
firmware will then at its leisure read this data. If it wants to return data, the function
cannot simply write to the bus as the bus is controlled by the host. Therefore it writes
data to EP1 IN which sits in the buffer until such time when the host sends a IN packet to
that endpoint requesting the data. Endpoints can also be seen as the interface between
the hardware of the function device and the firmware running on the function device.
All devices must support endpoint zero. This is the endpoint which receives all of the
devices control and status requests during enumeration and throughout the duration
while the device is operational on the bus.
Pipes
While the device sends and receives data on a series of endpoints, the client software
transfers data through pipes. A pipe is a logical connection between the host and
endpoint(s). Pipes will also have a set of parameters associated with them such as how
much bandwidth is allocated to it, what transfer type (Control, Bulk, Iso or Interrupt) it
uses, a direction of data flow and maximum packet/buffer sizes. For example the default
pipe is a bi-directional pipe made up of endpoint zero in and endpoint zero out with a
control transfer type.
USB defines two types of pipes
• Stream Pipes have no defined USB format, that is you can send any type of data down a stream pipe
and can retrieve the data out the other end. Data flows sequentially and has a pre-defined direction,
either in or out. Stream pipes will support bulk, isochronous and interrupt transfer types. Stream pipes
can either be controlled by the host or device.
• Message Pipes have a defined USB format. They are host controlled, which are initiated by a request
sent from the host. Data is then transferred in the desired direction, dictated by the request. Therefore
message pipes allow data to flow in both directions but will only support control transfers.
Endpoint Types
The Universal Serial Bus specification defines four transfer/endpoint types,
o Control Transfers
o Interrupt Transfers
o Isochronous Transfers
o Bulk Transfers
Control Transfers
Control transfers are typically used for command and status operations. They are
essential to set up a USB device with all enumeration functions being performed
using control transfers. They are typically bursty, random packets which are
initiated by the host and use best effort delivery. The packet length of control
transfers in low speed devices must be 8 bytes, high speed devices allow a packet
size of 8, 16, 32 or 64 bytes and full speed devices must have a packet size of 64
bytes.
A control transfer can have up to three stages.
o The Setup Stage is where the request is sent. This consists of three packets. The setup token is
sent first which contains the address and endpoint number. The data packet is sent next and
always has a PID type of data0 and includes a setup packet which details the type of request. We
detail the setup packet later. The last packet is a handshake used for acknowledging successful
receipt or to indicate an error. If the function successfully receives the setup data (CRC and PID
etc OK) it responds with ACK, otherwise it ignores the data and doesn’t send a handshake
packet. Functions cannot issue a STALL or NAK packet in response to a setup packet.
o The optional Data Stage consists of one or multiple IN or OUT transfers. The
setup request indicates the amount of data to be transmitted in this stage. If
it exceeds the maximum packet size, data will be sent in multiple transfers
each being the maximum packet length except for the last packet.
The data stage has two different scenarios depending upon the direction of
data transfer.
IN: When the host is ready to receive control data it issues an IN Token. If the function
receives the IN token with an error e.g. the PID doesn't match the inverted PID bits, then
it ignores the packet. If the token was received correctly, the device can either reply with
a DATA packet containing the control data to be sent, a stall packet indicating the
endpoint has had a error or a NAK packet indicating to the host that the endpoint is
working, but temporary has no data to send.
OUT: When the host needs to send the device a control data packet, it issues an OUT
token followed by a data packet containing the control data as the payload. If any part of
the OUT token or data packet is corrupt then the function ignores the packet. If the
function's endpoint buffer was empty and it has clocked the data into the endpoint buffer
it issues an ACK informing the host it has successfully received the data. If the endpoint
buffer is not empty due to processing of the previous packet, then the function returns a
NAK. However if the endpoint has had a error and its halt bit has been set, it returns a
STALL.
o Status Stage reports the status of the overall request and this once again varies due to direction
of transfer. Status reporting is always performed by the function.
IN: If the host sent IN token(s) during the data stage to receive data,
then the host must acknowledge the successful recept of this data.
This is done by the host sending an OUT token followed by a zero
length data packet. The function can now report its status in the
handshaking stage. An ACK indicates the function has completed the
command is now ready to accept another command. If an error
occurred during the processing of this command, then the function will
issue a STALL. However if the function is still processing, it returns a
NAK indicating to the host to repeat the status stage later.
OUT: If the host sent OUT token(s) during the data stage to transmit
data, the function will acknowledge the successful recept of data by
sending a zero length packet in response to an IN token. However if an
error occurred, it should issue a STALL or if it is still busy processing
data, it should issue a NAK asking the host to retry the status phase
later.
2. Data0 Packet Sync PID Data0 CRC16 EOP Device Descriptor Request
1. In Token Sync PID ADDR ENDP CRC5 EOP Address & Endpoint Number
2. Data0 Packet Sync PID Data0 CRC16 EOP Last 4 bytes + Padding
2. Data1 Packet Sync PID Data1 CRC16 EOP Zero Length Packet
Interrupt Transfers
Any one who has had experience of interrupt requests on microcontrollers will
know that interrupts are device generated. However under USB if a device requires
the attention of the host, it must wait until the host polls it before it can report that
it needs urgent attention!
Interrupt Transfers
Guaranteed Latency
Stream Pipe - Unidirectional
Error detection and next period retry.
o IN: The host will periodically poll the interrupt endpoint. This rate of polling is
specified in the endpoint descriptor which is covered later. Each poll will
involve the host sending an IN Token. If the IN token is corrupt, the function
ignores the packet and continues monitoring the bus for new tokens.
If an interrupt has been queued by the device, the function will send a data
packet containing data relevant to the interrupt when it receives the IN
Token. Upon successful recept at the host, the host will return an ACK.
However if the data is corrupted, the host will return no status. If on the
other hand a interrupt condition was not present when the host polled the
interrupt endpoint with an IN token, then the function signals this state by
sending a NAK. If an error has occurred on this endpoint, a STALL is sent in
reply to the IN token instead.
o OUT: When the host wants to send the device interrupt data, it issues an
OUT token followed by a data packet containing the interrupt data. If any
part of the OUT token or data packet is corrupt then the function ignores the
packet. If the function's endpoint buffer was empty and it has clocked the
data into the endpoint buffer it issues an ACK informing the host it has
successfully received the data. If the endpoint buffer is not empty due to
processing of a previous packet, then the function returns an NAK. However
if an error occurred with the endpoint consequently and its halt bit has been
set, it returns a STALL.
Isochronous Transfers
Isochronous transfers occur continuously and periodically. They typically contain
time sensitive information, such as an audio or video stream. If there were a delay
or retry of data in an audio stream, then you would expect some erratic audio
containing glitches. The beat may no longer be in sync. However if a packet or
frame was dropped every now and again, it is less likely to be noticed by the
listener.
Isochronous Transfers provide
The above diagram shows the format of an Isochronous IN and OUT transaction.
Isochronous transactions do not have a handshaking stage and cannot report
errors or STALL/HALT conditions.
Bulk Transfers
Bulk transfers can be used for large bursty data. Such examples could include a
print-job sent to a printer or an image generated from a scanner. Bulk transfers
provide error correction in the form of a CRC16 field on the data payload and error
detection/re-transmission mechanisms ensuring data is transmitted and received
without error.
Bulk transfers will use spare un-allocated bandwidth on the bus after all other
transactions have been allocated. If the bus is busy with isochronous and/or
interrupt then bulk data may slowly trickle over the bus. As a result Bulk transfers
should only be used for time insensitive communication as there is no guarantee of
latency.
Bulk Transfers
Used to transfer large bursty data.
Error detection via CRC, with guarantee of delivery.
No guarantee of bandwidth or minimum latency.
Stream Pipe - Unidirectional
Full & high speed modes only.
Bulk transfers are only supported by full and high speed devices. For full speed
endpoints, the maximum bulk packet size is either 8, 16, 32 or 64 bytes long. For
high speed endpoints, the maximum packet size can be up to 512 bytes long. If the
data payload falls short of the maximum packet size, it doesn't need to be padded
with zeros. A bulk transfer is considered complete when it has transferred the
exact amount of data requested, transferred a packet less than the maximum
endpoint size of transferred a zero-length packet.
The above diagram shows the format of a bulk IN and OUT transaction.
o IN: When the host is ready to receive bulk data it issues an IN Token. If the
function receives the IN token with an error, it ignores the packet. If the
token was received correctly, the function can either reply with a DATA
packet containing the bulk data to be sent, or a stall packet indicating the
endpoint has had a error or a NAK packet indicating to the host that the
endpoint is working, but temporary has no data to send.
o OUT: When the host wants to send the function a bulk data packet, it issues
an OUT token followed by a data packet containing the bulk data. If any part
of the OUT token or data packet is corrupt then the function ignores the
packet. If the function's endpoint buffer was empty and it has clocked the
data into the endpoint buffer it issues an ACK informing the host it has
successfully received the data. If the endpoint buffer is not empty due to
processing a previous packet, then the function returns an NAK. However if
the endpoint has had an error and it's halt bit has been set, it returns a
STALL.
Bandwidth Management
The host is responsible in managing the bandwidth of the bus. This is done at
enumeration when configuring Isochronous and Interrupt Endpoints and
throughout the operation of the bus. The specification places limits on the bus,
allowing no more than 90% of any frame to be allocated for periodic transfers
(Interrupt and Isochronous) on a full speed bus. On high speed buses this limitation
gets reduced to no more than 80% of a microframe can be allocated for periodic
transfers.
So you can quite quickly see that if you have a highly saturated bus with periodic
transfers, the remaining 10% is left for control transfers and once those have been
allocated, bulk transfers will get its slice of what is left.
USB Descriptors
All USB devices have a hierarchy of descriptors which describe to the host
information such as what the device is, who makes it, what version of USB it
supports, how many ways it can be configured, the number of endpoints and their
types etc
The more common USB descriptors are
Device Descriptors
Configuration Descriptors
Interface Descriptors
Endpoint Descriptors
String Descriptors
USB devices can only have one device descriptor. The device descriptor includes
information such as what USB revision the device complies to, the Product and
Vendor IDs used to load the appropriate drivers and the number of possible
configurations the device can have. The number of configurations indicate how
many configuration descriptors branches are to follow.
The configuration descriptor specifies values such as the amount of power this
particular configuration uses, if the device is self or bus powered and the number
of interfaces it has. When a device is enumerated, the host reads the device
descriptors and can make a decision of which configuration to enable. It can only
enable one configuration at a time.
For example, It is possible to have a high power bus powered configuration and a
self powered configuration. If the device is plugged into a host with a mains power
supply, the device driver may choose to enable the high power bus powered
configuration enabling the device to be powered without a connection to the
mains, yet if it is connected to a laptop or personal organiser it could enable the
2nd configuration (self powered) requiring the user to plug your device into the
power point.
The configuration settings are not limited to power differences. Each configuration
could be powered in the same way and draw the same current, yet have different
interface or endpoint combinations. However it should be noted that changing the
configuration requires all activity on each endpoint to stop. While USB offers this
flexibility, very few devices have more than 1 configuration.
The interface descriptor could be seen as a header or grouping of the endpoints
into a functional group performing a single feature of the device. For example you
could have a multi-function fax/scanner/printer device. Interface descriptor one
could describe the endpoints of the fax function, Interface descriptor two the
scanner function and Interface descriptor three the printer function. Unlike the
configuration descriptor, there is no limitation as to having only one interface
enabled at a time. A device could have 1 or many interface descriptors enabled at
once.
Interface descriptors have a bInterfaceNumber field specifying the Interface
number and a bAlternateSetting which allows an interface to change settings on
the fly. For example we could have a device with two interfaces, interface one and
interface two. Interface one has bInterfaceNumber set to zero indicating it is the
first interface descriptor and a bAlternativeSetting of zero.
Interface two would have a bInterfaceNumber set to one indicating it is the
second interface and a bAlternativeSetting of zero (default). We could then
throw in another descriptor, also with a bInterfaceNumber set to one indicating it
is the second interface, but this time setting the bAlternativeSetting to one,
indicating this interface descriptor can be an alternative setting to that of the other
interface descriptor two.
When this configuration is enabled, the first two interface descriptors with
bAlternativeSettings equal to zero is used. However during operation the host
can send a SetInterface request directed to that of Interface one with a alternative
setting of one to enable the other interface descriptor.
This gives an advantage over having two configurations, in that we can be
transmitting data over interface zero while we change the endpoint settings
associated with interface one without effecting interface zero.
Each endpoint descriptor is used to specify the type of transfer, direction, polling
interval and maximum packet size for each endpoint. Endpoint zero, the default
control endpoint is always assumed to be a control endpoint and as such never has
a descriptor.
Device Descriptors
The device descriptor of a USB device represents the entire device. As a result a
USB device can only have one device descriptor. It specifies some basic, yet
important information about the device such as the supported USB version,
maximum packet size, vendor and product IDs and the number of possible
configurations the device can have. The format of the device descriptor is shown
below.
Offset Field Size Value Description
o The bcdUSB field reports the highest version of USB the device supports.
The value is in binary coded decimal with a format of 0xJJMN where JJ is the
major version number, M is the minor version number and N is the sub minor
version number. e.g. USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and
USB 1.0 as 0x0100.
o The bDeviceClass, bDeviceSubClass and bDeviceProtocol are used by
the operating system to find a class driver for your device. Typically only the
bDeviceClass is set at the device level. Most class specifications choose to
identify itself at the interface level and as a result set the bDeviceClass as
0x00. This allows for the one device to support multiple classes.
o The bMaxPacketSize field reports the maximum packet size for endpoint
zero. All devices must support endpoint zero.
o The idVendor and idProduct are used by the operating system to find a
driver for your device. The Vendor ID is assigned by the USB-IF.
o The bcdDevice has the same format than the bcdUSB and is used to
provide a device version number. This value is assigned by the developer.
o Three string descriptors exist to provide details of the manufacturer, product
and serial number. There is no requirement to have string descriptors. If no
string descriptor is present, a index of zero should be used.
o bNumConfigurations defines the number of configurations the device
supports at its current speed.
Configuration Descriptors
A USB device can have several different configurations although the majority of
devices are simple and only have one. The configuration descriptor specifies how
the device is powered, what the maximum power consumption is, the number of
interfaces it has. Therefore it is possible to have two configurations, one for when
the device is bus powered and another when it is mains powered. As this is a
"header" to the Interface descriptors, its also feasible to have one configuration
using a different transfer mode to that of another configuration.
Once all the configurations have been examined by the host, the host will send a
SetConfiguration command with a non zero value which matches the
bConfigurationValue of one of the configurations. This is used to select the desired
configuration.
Offset Field Size Value Description
D6 Self Powered
D5 Remote Wakeup
Interface Descriptors
The interface descriptor could be seen as a header or grouping of the endpoints
into a functional group performing a single feature of the device. The interface
descriptor conforms to the following format,
Offset Field Size Value Description
0 bLength 1 Number Size of Descriptor in Bytes (9 Bytes)
Endpoint Descriptors
Endpoint descriptors are used to describe endpoints other than endpoint zero.
Endpoint zero is always assumed to be a control endpoint and is configured before
any descriptors are even requested. The host will use the information returned
from these descriptors to determine the bandwidth requirements of the bus.
Offset Field Size Value Description
String Descriptors
String descriptors provide human readable information and are optional. If they are
not used, any string index fields of descriptors must be set to zero indicating there
is no string descriptor available.
The strings are encoded in the Unicode format and products can be made to
support multiple languages. String Index 0 should return a list of supported
languages. A list of USB Language IDs can be found in Universal Serial Bus
Language Identifiers (LANGIDs) version 1.0
Offset Field Size Value Description
These timeout periods are quite acceptable for even the slowest of devices, but
can be a restriction during debugging. 50mS doesn't provide for many debugging
characters to be sent at 9600bps on an asynchronous serial port or for a In Circuit
Debugger/Emulator to single step or to break execution to examine the internal
Registers. As a result, USB requires some different debugging methods to that of
other microcontroller projects.
Casually reading through the XP DDK, one may note the Host Controller
Driver now has a USBUSER_OP_SEND_ONE_PACKET command which is
commented to read "This API is used to implement the 'single step' USB
transaction development tool." While such a tool has not been released yet,
we can only hope to see one soon.
Each request starts with a 8 byte long Setup Packet which has the following
format,
Offset Field Size Value Description
Index or
4 wIndex 2 Index
Offset
Number of bytes to transfer if there is
6 wLength 2 Count a data phase
The bmRequestType field will determine the direction of the request, type of
request and designated recipient. The bRequest field determines the request
being made. The bmRequestType is normally parsed and execution is branched to
a number of handlers such as a Standard Device request handler, a Standard
Interface request handler, a Standard Endpoint request handler, a Class Device
request handler etc. How you parse the setup packet is entirely up to your
preference. Others may choose to parse the bRequest first and then determine the
type and recipient based on each request.
Standard requests are common to all USB devices and are detailed in the next
coming pages. Class requests are common to classes of drivers. For example, all
device conforming to the HID class will have a common set of class specific
requests. These will differ to a device conforming to the communications class and
differ again to that of a device conforming to the mass storage class.
And last of all is the vendor defined requests. These are requests which you as the
USB device designer can assign. These are normally different from device to
device, but this is all up to your implementation and imagination.
A common request can be directed to different recipients and based on the
recipient perform different functions. A GetStatus Standard request for example,
can be directed at the device, interface or endpoint. When directed to a device it
returns flags indicating the status of remote wakeup and if the device is self
powered. However if the same request is directed at the interface it always returns
zero, or should it be directed at an endpoint will return the halt flag for the
endpoint.
The wValue and wIndex fields allow parameters to be passed with the request.
wLength is used the specify the number of bytes to be transferred should there
be a data phase.
Standard Requests
Section 9.4 of the USB specification details the "Standard Device" requests
required to be implemented for every USB device. The standard provides a single
table grouping items by request. Considering most firmware will parse the setup
packet by recipient we will opt to break up the requests based by recipient for
easier examination and implementation.
CLEAR_FEATURE Feature
0000 0000b Zero Zero None
(0x01) Selector
Feature
0000 0000b SET_FEATURE (0x03) Zero Zero None
Selector
Device
0000 0000b SET_ADDRESS (0x05) Zero Zero None
Address
Zero or
GET_DESCRIPTOR Descriptor Descriptor
1000 0000b Language Descriptor
(0x06) Type & Index Length
ID
Zero or
SET_DESCRIPTOR Descriptor Descriptor
0000 0000b Language Descriptor
(0x07) Type & Index Length
ID
GET_CONFIGURATION Configuration
1000 0000b Zero Zero 1
(0x08) Value
SET_CONFIGURATION Configuration
0000 0000b Zero Zero None
(0x09) Value
o The Get Status request directed at the device will return two bytes during
the data stage with the following format,
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
Remote Self
Reserved
Wakeup Powered
o If D0 is set, then this indicates the device is self powered. If clear, the device
is bus powered. If D1 is set, the device has remote wakeup enabled and can
wake the host up during suspend. The remote wakeup bit can be by the
SetFeature and ClearFeature requests with a feature selector of
DEVICE_REMOTE_WAKEUP (0x01)
o Clear Feature and Set Feature requests can be used to set boolean
features. When the designated recipient is the device, the only two feature
selectors available are DEVICE_REMOTE_WAKEUP and TEST_MODE. Test
mode allows the device to exhibit various conditions. These are further
documented in the USB Specification Revision 2.0.
o Set Address is used during enumeration to assign a unique address to the
USB device. The address is specified in wValue and can only be a maximum
of 127. This request is unique in that the device does not set its address until
after the completion of the status stage. (See Control Transfers.) All other
requests must complete before the status stage.
o Set Descriptor/Get Descriptor is used to return the specified descriptor in
wValue. A request for the configuration descriptor will return the device
descriptor and all interface and endpoint descriptors in the one request.
Endpoint Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor
Request.
Interface Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor
Request.
String Descriptors include a Language ID in wIndex to allow for multiple language
support.
o Get Configuration/Set Configuration is used to request or set the current
device configuration. In the case of a Get Configuration request, a byte will
be returned during the data stage indicating the devices status. A zero value
means the device is not configured and a non-zero value indicates the
device is configured. Set Configuration is used to enable a device. It should
contain the value of bConfigurationValue of the desired configuration
descriptor in the lower byte of wValue to select which configuration to
enable.
GET_STATUS Interface
1000 0001b Zero Interface Two
(0x00) Status
CLEAR_FEATURE Feature
0000 0001b Interface Zero None
(0x01) Selector
SET_FEATURE Feature
0000 0001b Interface Zero None
(0x03) Selector
GET_INTERFACE Alternate
1000 0001b Zero Interface One
(0x0A) Interface
SET_INTERFACE Alternative
0000 0001b Interface Zero None
(0x11) Setting
• wIndex is normally used to specify the referring interface for requests directed at
the interface. Its format is shown below.
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
Reserved Interface Number
• Get Status is used to return the status of the interface. Such a request to the
interface should return two bytes of 0x00, 0x00. (Both bytes are reserved for
future use)
• Clear Feature and Set Feature requests can be used to set boolean features.
When the designated recipient is the interface, the current USB Specification
Revision 2 specifies no interface features.
• Get Interface and Set Interface set the Alternative Interface setting which is
described in more detail under the Interface Descriptor.
GET_STATUS Endpoint
1000 0010b Zero Endpoint Two
(0x00) Status
CLEAR_FEATURE Feature
0000 0010b Endpoint Zero None
(0x01) Selector
SET_FEATURE Feature
0000 0010b Endpoint Zero None
(0x03) Selector
SYNCH_FRAME
1000 0010b Zero Endpoint Two FrameNumber
(0x12)
o The wIndex field is normally used to specify the referring endpoint and
direction for requests directed to an endpoint. Its format is shown below.
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
Reserved Halt
o Clear Feature and Set Feature are used to set Endpoint Features. The
standard currently defines one endpoint feature selector, ENDPOINT_HALT
(0x00) which allows the host to stall and clear an endpoint. Only endpoints
other than the default endpoint is recommended to have this functionality.
o A Synch Frame request is used to report an endpoint synchronisation
frame.
Interfacing the Standard Parallel Port
Table of Contents
Introduction to Parallel Ports
Hardware Properties
Centronics?
Port Addresses
Software Registers - Standard Parallel Port (SPP)
Bi-directional Ports
Using the Parallel Port to Input 8 Bits
Nibble Mode
Using the Parallel Port's IRQ
Parallel Port Modes in BIOS
Parallel Port Modes and the ECP's Extended Control Register
PDF Version
Newer Parallel Port’s are standardized under the IEEE 1284 standard first released
in 1994. This standard defines 5 modes of operation which are as follows,
1. Compatibility Mode.
2. Nibble Mode. (Protocol not Described in this Document)
3. Byte Mode. (Protocol not Described in this Document)
4. EPP Mode (Enhanced Parallel Port).
5. ECP Mode (Extended Capabilities Mode).
The aim was to design new drivers and devices which were compatible with each
other and also backwards compatible with the Standard Parallel Port (SPP).
Compatibility, Nibble & Byte modes use just the standard hardware available on
the original Parallel Port cards while EPP & ECP modes require additional hardware
which can run at faster speeds, while still being downwards compatible with the
Standard Parallel Port.
Compatibility mode or "Centronics Mode" as it is commonly known, can only send
data in the forward direction at a typical speed of 50 kbytes per second but can be
as high as 150+ kbytes a second. In order to receive data, you must change the
mode to either Nibble or Byte mode. Nibble mode can input a nibble (4 bits) in the
reverse direction. E.g. from device to computer. Byte mode uses the Parallel's bi-
directional feature (found only on some cards) to input a byte (8 bits) of data in the
reverse direction.
Extended and Enhanced Parallel Ports use additional hardware to generate and manage handshaking. To
output a byte to a printer (or anything in that matter) using compatibility mode, the software must,
1. Write the byte to the Data Port.
2. Check to see is the printer is busy. If the printer is busy, it will not accept any data, thus any
data which is written will be lost.
3. Take the Strobe (Pin 1) low. This tells the printer that there is the correct data on the data
lines. (Pins 2-9)
4. Put the strobe high again after waiting approximately 5 microseconds after putting the strobe
low. (Step 3)
This limits the speed at which the port can run at. The EPP & ECP ports get around
this by letting the hardware check to see if the printer is busy and generate a
strobe and /or appropriate handshaking. This means only one I/O instruction need
to be performed, thus increasing the speed. These ports can output at around 1-2
megabytes per second. The ECP port also has the advantage of using DMA
channels and FIFO buffers, thus data can be shifted around without using I/O
instructions.
Hardware Properties
Below is a table of the "Pin Outs" of the D-Type 25 Pin connector and the
Centronics 34 Pin connector. The D-Type 25 pin connector is the most common
connector found on the Parallel Port of the computer, while the Centronics
Connector is commonly found on printers. The IEEE 1284 standard however
specifies 3 different connectors for use with the Parallel Port. The first one, 1284
Type A is the D-Type 25 connector found on the back of most computers. The 2nd
is the 1284 Type B which is the 36 pin Centronics Connector found on most
printers.
IEEE 1284 Type C however, is a 36 conductor connector like the Centronics, but
smaller. This connector is claimed to have a better clip latch, better electrical
properties and is easier to assemble. It also contains two more pins for signals
which can be used to see whether the other device connected, has power. 1284
Type C connectors are recommended for new designs, so we can look forward on
seeing these new connectors in the near future.
The above table uses "n" in front of the signal name to denote that the signal is
active low. e.g. nError. If the printer has occurred an error then this line is low. This
line normally is high, should the printer be functioning correctly. The "Hardware
Inverted" means the signal is inverted by the Parallel card's hardware. Such an
example is the Busy line. If +5v (Logic 1) was applied to this pin and the status
register read, it would return back a 0 in Bit 7 of the Status Register.
The output of the Parallel Port is normally TTL logic levels. The voltage levels are
the easy part. The current you can sink and source varies from port to port. Most
Parallel Ports implemented in ASIC, can sink and source around 12mA. However
these are just some of the figures taken from Data sheets, Sink/Source 6mA,
Source 12mA/Sink 20mA, Sink 16mA/Source 4mA, Sink/Source 12mA. As you can
see they vary quite a bit. The best bet is to use a buffer, so the least current is
drawn from the Parallel Port.
Centronics?
Centronics is an early standard for transferring data from a host to the printer. The
majority of printers use this handshake. This handshake is normally implemented
using a Standard Parallel Port under software control. Below is a simplified diagram
of the `Centronics' Protocol.
Data is first applied on the Parallel Port pins 2 to 7. The host then checks to see if
the printer is busy. i.e. the busy line should be low. The program then asserts the
strobe, waits a minimum of 1uS, and then de-asserts the strobe. Data is normally
read by the printer/peripheral on the rising edge of the strobe. The printer will
indicate that it is busy processing data via the Busy line. Once the printer has
accepted data, it will acknowledge the byte by a negative pulse about 5uS on the
nAck line.
Quite often the host will ignore the nAck line to save time. Latter in the Extended
Capabilities Port, you will see a Fast Centronics Mode, which lets the hardware do
all the handshaking for you. All the programmer must do is write the byte of data
to the I/O port. The hardware will check to see if the printer is busy, generate the
strobe. Note that this mode commonly doesn't check the nAck either.
Port Addresses
The Parallel Port has three commonly used base addresses. These are listed in
table 2, below. The 3BCh base address was originally introduced used for Parallel
Ports on early Video Cards. This address then disappeared for a while, when
Parallel Ports were later removed from Video Cards. They has now reappeared as
an option for Parallel Ports integrated onto motherboards, upon which their
configuration can be changed using BIOS.
LPT1 is normally assigned base address 378h, while LPT2 is assigned 278h.
However this may not always be the case as explained later. 378h & 278h have
always been commonly used for Parallel Ports. The lower case h denotes that it is
in hexadecimal. These addresses may change from machine to machine.
Address Notes:
3BCh - 3BFh Used for Parallel Ports which were incorporated on to Video
Cards - Doesn't support ECP addresses
378h - 37Fh Usual Address For LPT 1
278h - 27Fh Usual Address For LPT 2
Table 2 Port Addresses
When the computer is first turned on, BIOS (Basic Input/Output System) will
determine the number of ports you have and assign device labels LPT1, LPT2 &
LPT3 to them. BIOS first looks at address 3BCh. If a Parallel Port is found here, it is
assigned as LPT1, then it searches at location 378h. If a Parallel card is found
there, it is assigned the next free device label. This would be LPT1 if a card wasn't
found at 3BCh or LPT2 if a card was found at 3BCh. The last port of call, is 278h
and follows the same procedure than the other two ports. Therefore it is possible
to have a LPT2 which is at 378h and not at the expected address 278h.
What can make this even confusing, is that some manufacturers of Parallel Port
Cards, have jumpers which allow you to set your Port to LPT1, LPT2, LPT3. Now
what address is LPT1? - On the majority of cards LPT1 is 378h, and LPT2, 278h, but
some will use 3BCh as LPT1, 378h as LPT1 and 278h as LPT2. Life wasn't meant to
be easy.
The assigned devices LPT1, LPT2 & LPT3 should not be a worry to people wishing
to interface devices to their PC's. Most of the time the base address is used to
interface the port rather than LPT1 etc. However should you want to find the
address of LPT1 or any of the Line PrinTer Devices, you can use a lookup table
provided by BIOS. When BIOS assigns addresses to your printer devices, it stores
the address at specific locations in memory, so we can find them.
Note 1 : Address 0000:040E in the BIOS Data Area may be used as the Extended Bios Data Area in
PS/2 and newer Bioses.
The above table, table 3, shows the address at which we can find the Printer Port's
addresses in the BIOS Data Area. Each address will take up 2 bytes. The following
sample program in C, shows how you can read these locations to obtain the
addresses of your printer ports.
#include <stdio.h>
#include <dos.h>
void main(void)
{
unsigned int far *ptraddr; /* Pointer to location of Port Addresses */
unsigned int address; /* Address of Port */
int a;
Note 1 : If the Port is Bi-Directional then Read and Write Operations can be performed on the
Data Register.
The base address, usually called the Data Port or Data Register is simply used for outputting
data on the Parallel Port's data lines (Pins 2-9). This register is normally a write only port. If
you read from the port, you should get the last byte sent. However if your port is bi-directional,
you can receive data on this address. See Bi-directional Ports for more detail.
Offset Name Read/Write Bit No. Properties
Base + 1 Status Port Read Only Bit 7 Busy
Bit 6 Ack
Bit 5 Paper Out
Bit 4 Select In
Bit 3 Error
Bit 2 IRQ (Not)
Bit 1 Reserved
Bit 0 Reserved
Table 5 Status Port
The Status Port (base address + 1) is a read only port. Any data written to this port will be
ignored. The Status Port is made up of 5 input lines (Pins 10,11,12,13 & 15), a IRQ status
register and two reserved bits. Please note that Bit 7 (Busy) is a active low input. E.g. If bit 7
happens to show a logic 0, this means that there is +5v at pin 11. Likewise with Bit 2. (nIRQ) If
this bit shows a '1' then an interrupt has not occurred.
Offset Name Read/Write Bit No. Properties
Base + 2 Control Port Read/Write Bit 7 Unused
Bit 6 Unused
Bit 5 Enable Bi-Directional Port
Bit 4 Enable IRQ Via Ack Line
Bit 3 Select Printer
Bit 2 Initialize Printer (Reset)
Bit 1 Auto Linefeed
Bit 0 Strobe
Table 6 Control Port
The Control Port (base address + 2) was intended as a write only port. When a printer is
attached to the Parallel Port, four "controls" are used. These are Strobe, Auto Linefeed,
Initialize and Select Printer, all of which are inverted except Initialize.
The printer would not send a signal to initialize the computer, nor would it tell the computer to
use auto linefeed. However these four outputs can also be used for inputs. If the computer has
placed a pin high (e.g. +5v) and your device wanted to take it low, you would effectively short
out the port, causing a conflict on that pin. Therefore these lines are "open collector" outputs
(or open drain for CMOS devices). This means that it has two states. A low state (0v) and a
high impedance state (open circuit).
Normally the Printer Card will have internal pull-up resistors, but as you would expect, not all
will. Some may just have open collector outputs, while others may even have normal totem
pole outputs. In order to make your device work correctly on as many Printer Ports as possible,
you can use an external resistor as well. Should you already have an internal resistor, then it
will act in Parallel with it, or if you have Totem pole outputs, the resistor will act as a load.
An external 4.7k resistor can be used to pull the pin high. I wouldn't use anything lower, just in
case you do have an internal pull up resistor, as the external resistor would act in parallel
giving effectively, a lower value pull up resistor. When in high impedance state the pin on the
Parallel Port is high (+5v). When in this state, your external device can pull the pin low and
have the control port change read a different value. This way the 4 pins of the Control Port can
be used for bi-directional data transfer. However the Control Port must be set to xxxx0100 to
be able to read data, that is all pins to be +5v at the port so that you can pull it down to GND
(logic 0).
Bits 4 & 5 are internal controls. Bit four will enable the IRQ (See Using the Parallel Ports IRQ)
and Bit 5 will enable the bi-directional port meaning that you can input 8 bits using (DATA0-7).
This mode is only possible if your card supports it. Bits 6 & 7 are reserved. Any writes to these
two bits will be ignored.
Bi-directional Ports
The schematic diagram below, shows a simplified view of the Parallel Port's Data Register.
The original Parallel Port card's implemented 74LS logic. These days all this is crammed into
one ASIC, but the theory of operation is still the same.
The non bi-directional ports were manufactured with the 74LS374's output enable tied
permanent low, thus the data port is always output only. When you read the Parallel Port's
data register, the data comes from the 74LS374 which is also connected to the data pins. Now
if you can overdrive the '374 you can effectively have a Bi-directional Port. (or a input only port,
once you blow up the latches output!)
What is very concerning is that people have actually done this. I've seen one circuit, a scope
connected to the Parallel Port distributed on the Internet. The author uses an ADC of some
type, but finds the ADC requires transistors on each data line, to make it work! No wonder why.
Others have had similar trouble, the 68HC11 cannot sink enough current (30 to 40mA!)
Bi-directional ports use Control Bit 5 connected to the 374's Output Enable so that it's output
drivers can be turned off. This way you can read data present on the Parallel Port's Data Pins,
without having bus conflicts and excessive current drains.
Bit 5 of the Control Port enables or disables the bi-directional function of the Parallel Port. This
is only available on true bi-directional ports. When this bit is set to one, pins 2 to 9 go into high
impedance state. Once in this state you can enter data on these lines and retrieve it from the
Data Port (base address). Any data which is written to the data port will be stored but will not
be available at the data pins. To turn off bi-directional mode, set bit 5 of the Control Port to '0'.
However not all ports behave in the same way. Other ports may require setting bit 6 of the
Control Port to enable Bi-directional mode and setting of Bit 5 to dis-enable Bi-directional
mode, Different manufacturers implement their bi-directional ports in different ways. If you wish
to use your Bi-directional port to input data, test it with a logic probe or multimeter first to make
sure it is in bi-directional mode.
Using The Parallel Port to Input 8 Bits.
If your Parallel Port doesn't support bi-directional mode, don't despair. You can input a
maximum of 9 bits at any one given time. To do this you can use the 5 input lines of the Status
Port and the 4 inputs (open collector) lines of the Control Port.
The inputs to the Parallel Port has be chosen as such, to make life easier for us. Busy just
happens to be the MSB (Bit 7) of the Status Port, then in ascending order comes Ack, Paper
Out and Select, making up the most significant nibble of the Control Port. The Bars are used to
represent which inputs are Hardware inverted, i.e. +5v will read 0 from the register, while GND
will read 1. The Status Port only has one inverted input.
The Control port is used to read the least significant nibble. As described before, the control
port has open collector outputs, i.e. two possible states, high impedance and GND. If we
connect our inputs directly to the port (For example an ADC0804 with totem pole outputs), a
conflict will result if the input is high and the port is trying to pull it down. Therefore we use
open collector inverters.
However this is not always entirely necessary. If we were connecting single pole switches to
the port with a pull up resistor, then there is no need to bother with this protection. Also if your
software initializes the control port with xxxx0100 so that all the pins on the control port are
high, then it may be unnecessary. If however you don't bother and your device is connected to
the Parallel Port before your software has a chance to initialize then you may encounter
problems.
Another problem to be aware of is the pull up resistors on the control port. The average pull-up
resistor is 4.7k. In order to pull the line low, your device will need to sink 1mA, which some low
powered devices may struggle to do. Now what happens if I suggest that some ports have 1K
pull up resistors? Yes, there are such cards. Your device now has to sink 5mA. More reason to
use the open collector inverters.
Open collector inverters were chosen over open collector buffers as they are more popular,
and thus easier to obtain. There is no reason, however why you can't use them. Another
possibility is to use transistors.
The input, D3 is connected via the inverter to Select Printer. Select Printer just happens to be
bit 3 of the control port. D2, D1 & D0 are connected to Init, Auto linefeed and strobe,
respectively to make up the lower nibble. Now this is done, all we have to do is assemble the
byte using software. The first thing we must do is to write xxxx0100 to the Control Port. This
places all the control port lines high, so they can be pulled down to input data.
outportb(CONTROL, inportb(CONTROL) & 0xF0 | 0x04);
Now that this is done, we can read the most significant nibble. This just happens to be the
most significant nibble of the status port. As we are only interested in the MSnibble we will
AND the results with 0xF0, so that the LSnibble is clear. Busy is hardware inverted, but we
won't worry about it now. Once the two bytes are constructed, we can kill two birds with one
stone by toggling Busy and Init at the same time.
a = (inportb(STATUS) & 0xF0); /* Read MSnibble */
We can now read the LSnibble. This just happens to be LSnibble of the control port - How
convenient! This time we are not interested with the MSnibble of the port, thus we AND the
result with 0x0F to clear the MSnibble. Once this is done, it is time to combine the two bytes
together. This is done by OR'ing the two bytes. This now leaves us with one byte, however we
are not finished yet. Bits 2 and 7 are inverted. This is overcome by XOR'ing the byte with 0x84,
which toggles the two bits.
a = a |(inportb(CONTROL) & 0x0F); /* Read LSnibble */
a = a ^ 0x84; /* Toggle Bit 2 & 7 */
Note: Some control ports are not open collector, but have totem pole outputs. This is
also the case with EPP and ECP Ports. Normally when you place a Parallel Port in ECP
or EPP mode, the control port becomes totem pole outputs only. Now what happens if
you connect your device to the Parallel Port in this mode? Therefore, in the interest of
portability I recommend using the next circuit, reading a nibble at a time.
Nibble Mode.
Nibble mode is the preferred way of reading 8 bits of data without placing the port in reverse
mode and using the data lines. Nibble mode uses a Quad 2 line to 1 line multiplexer to read a
nibble of data at a time. Then it "switches" to the other nibble and reads its. Software can then
be used to construct the two nibbles into a byte. The only disadvantage of this technique is that
it is slower. It now requires a few I/O instructions to read the one byte, and it requires the use
of an external IC.
The operation of the 74LS157, Quad 2 line to 1 line multiplexer is quite simple. It simply acts
as four switches. When the A/B input is low, the A inputs are selected. E.g. 1A passes through
to 1Y, 2A passes through to 2Y etc. When the A/B is high, the B inputs are selected. The Y
outputs are connected up to the Parallel Port's status port, in such a manner that it represents
the MSnibble of the status register. While this is not necessary, it makes the software easier.
To use this circuit, first we must initialize the multiplexer to switch either inputs A or B. We will
read the LSnibble first, thus we must place A/B low. The strobe is hardware inverted, thus we
must set Bit 0 of the control port to get a low on Pin 1.
outportb(CONTROL, inportb(CONTROL) | 0x01); /* Select Low Nibble (A)*/
Once the low nibble is selected, we can read the LSnibble from the Status Port. Take note that
the Busy Line is inverted, however we won't tackle it just yet. We are only interested in the
MSnibble of the result, thus we AND the result with 0xF0, to clear the LSnibble.
a = (inportb(STATUS) & 0xF0); /* Read Low Nibble */
Now it's time to shift the nibble we have just read to the LSnibble of variable a,
a = a >> 4; /* Shift Right 4 Bits */
We are now half way there. It's time to get the MSnibble, thus we must switch the multiplexer
to select inputs B. Then we can read the MSnibble and put the two nibbles together to make a
byte,
outportb(CONTROL, inportb(CONTROL) & 0xFE); /* Select High Nibble (B)*/
a = a |(inportb(STATUS) & 0xF0); /* Read High Nibble */
byte = byte ^ 0x88;
The last line toggles two inverted bits which were read in on the Busy line. It may be necessary
to add delays in the process, if the incorrect results are being returned.
Using the Parallel Port's IRQ
The Parallel Port's interrupt request is not used for printing under DOS or Windows. Early
versions of OS-2 used them, but don't anymore. Interrupts are good when interfacing
monitoring devices such as high temp alarms etc, where you don't know when it is going to be
activated. It's more efficient to have an interrupt request rather than have the software poll the
ports regularly to see if something has changed. This is even more noticeable if you are using
your computer for other tasks, such as with a multitasking operating system.
The Parallel Port's interrupt request is normally IRQ5 or IRQ7 but may be something else if
these are in use. It may also be possible that the interrupts are totally disabled on the card, if
the card was only used for printing. The Parallel Port interrupt can be disabled and enabled
using bit 4 of the control register, Enable IRQ Via Ack Line. Once enabled, an interrupt will
occur upon a low to high transition (rising edge) of the nACK. However like always, some
cards may trigger the interrupt on the high to low transition.
The following code is an Interrupt Polarity Tester, which serves as two things. It will determine
which polarity your Parallel Port interrupt is, while also giving you an example for how to use
the Parallel Port's Interrupt. It checks if your interrupt is generated on the rising or falling edge
of the nACK line. To use the program simply wire one of the Data lines (Pins 2 to 9) to the Ack
Pin (Pin 10). The easiest way to do this is to bridge some solder from DATA7 (Pin 9) to ACK
(Pin 10) on a male DB25 connector.
#include <dos.h>
void main(void)
{
int c;
int intno; /* Interrupt Vector Number */
int picmask; /* PIC's Mask */
clrscr();
printf("Parallel Port Interrupt Polarity Tester\n");
printf("IRQ %d : INTNO %02X : PIC Addr 0x%X : Mask 0x
%02X\n",IRQ,intno,picaddr,picmask);
interflag = 0; /* Reset Interrupt Flag */
delay(10);
outportb(DATA,0x00); /* High to Low Transition */
delay(10); /* Wait */
if (interflag == 1) printf("Interrupts Occur on High to Low Transition of ACK.\n");
else
{
outportb(DATA,0xFF); /* Low to High Transition */
delay(10); /* wait */
if (interflag == 1) printf("Interrupts Occur on Low to High Transition of ACK.\n");
else printf("No Interrupt Activity Occurred. \nCheck IRQ Number, Port Address and
Wiring.");
}
For the hobbyist, EPP is more commonly used than ECP. EPP differs from ECP by
the fact that the EPP Port generates and controls all the transfers to and from the
peripheral. ECP on the other hand requires the peripheral to negotiate a reverse
channel and control the handshaking. This is harder to achieve with common glue
logic, thus really requires a dedicated controller or ECP Peripheral Chip.
Paper Out, Select and Error are not defined in the EPP handshake. These lines can
be utilised in any way by the user. The status of these lines can be determined at
anytime by viewing the SPP Status Register. Unfortunately there are no spare
output's. This can become a hassle regularly.
The EPP Handshake
In order to perform a valid exchange of data using EPP we must follow the EPP
handshake. As the hardware does all the work, this handshake only requires to be
used for your hardware and not for software as the case with SPP. To initiate an
EPP cycle your software needs to perform only one I/O operation to the relevant
EPP Register. Details on this, latter.
Note If implementing EPP 1.7 Handshake (Pre IEEE 1284) the Data and Address Strobes can be asserted
to start a cycle regardless of the wait state. EPP 1.9 will only start a cycle once wait is low. Both
EPP 1.7 and EPP 1.9 require the wait to be high to finish a cycle.
The EPP's Software Registers.
The EPP Port also has a new set of registers. However 3 of them have been
inherited from the Standard Parallel Port. Below is a table showing the new and
existing registers.
As you can see, the first 3 addresses are exactly the same than the Standard
Parallel Port Register and behave in exactly the same way. Therefore if you used a
Enhanced Parallel Port, you can output data to Base + 0 in exactly the same
fashion than you would if it was a Standard Parallel Port (SPP). If you were to
connect a printer, and use compatibility mode then you would have to check to see
if the port is busy and then assert & de-assert the strobe using the Control and
Status Port, then wait for the Ack.
If you wish to communicate with a EPP compatible device then all you have to do,
is place any data you wish to send in the EPP Data Register at Base + 4 and the
card will generate all the necessary handshaking required. Likewise if you wish to
send an address to your device, then you use the EPP Address Register at offset
+3.
Both the EPP Address Register and the EPP Data Register are read / write, thus to
read data from your device, you can use the same registers. However the EPP
Printer Card has to initiate a read Cycle as both the nData Strobe and nAddress
Strobe are outputs. Your device can signal a read request via the use of the
interrupt and have your ISR perform the Read Operation.
The Status Port has one little modification. Bit 0, which was reserved in the SPP
register set, now becomes the EPP Time-out Bit. This bit will be set when an EPP
time-out occurs. This happens when the nWait line is not deasserted within
approximately 10uS (depending upon the port) of the IOW or IOR line being
asserted. The IOW and IOR are the I/O Read and Write lines present on the ISA Bus.
The EPP mode is very depended of the ISA bus timing. When a read cycle is
performed, the port must undertake the appropriate Read/Write handshake and
return the data in that ISA cycle. Of course this doesn't occur within one ISA cycle,
thus the port uses the IOCHRDY (I/O Channel Ready) on the ISA bus to introduce
wait states, until the cycle completes. Now imagine if a EPP Read or Write is
started with no peripheral connected? The port never gets an acknowledgment
(nWait), thus keeps sending requests for wait states, and your computer locks up.
Therefore the EPP implements a type of watchdog, which times out after
approximately 10uS.
The three registers, Base + 5, Base + 6 and Base + 7 can be used for 16 and 32
bit read/write operations if your port supports it. This can further reduce your I/O
operations. The Parallel Port can only transport 8 bits at a time, thus any 32 or 16
bit word written to the Parallel Port will be split into byte size blocks and sent via
the Parallel Port's 8 data lines.
EPP Programming Considerations.
EPP only has two main registers and a Time-out Status Flag, What could there
possibly be to set up?
Before you can start any EPP cycles by reading and writing to the EPP Data and
Address Ports, the port must be configured correctly. In the idle state, an EPP port
should have it's nAddress Strobe, nData Strobe, nWrite and nReset lines inactive,
high. Some ports require you to set this up before starting any EPP Cycle.
Therefore our first task is to manually initialise these lines using the SPP Registers.
Writing XXXX0100 to the control port will do this.
On some cards, if the Parallel Port is placed in reverse mode, a EPP Write cycle
cannot be performed. Therefore it is also wise to place the Parallel Port in forward
mode before using EPP. Clearing Bit 5 of the Control Register should result in an
more enjoyable programming session, without tearing your hair out.
The EPP Timeout bit we have already discussed. When this bit is set, the EPP port
may not function correctly. A common scenario is always reading 0xFF from either
the Address or Data Cycles. This bit should be cleared for reliable operation, and
constantly checked.
Another feature of ECP is a real time data compression. It uses Run Length
Encoding (RLE) to achieve data compression ratio's up to 64:1. This comes is
useful with devices such as Scanners and Printers where a good part of the data is
long strings which are repetitive.
The ECP is backwards compatible to the SPP and EPP. When operating in SPP
mode, the individual lines operate in exactly the same fashion than the SPP and
thus are labeled Strobe, Auto Linefeed, Init, Busy etc. When operating in EPP
mode, the pins function according to the method described in the EPP protocol and
have a different method of Handshaking. When the port is operating in ECP mode,
then the following labels are assigned to each pin.
SPP
Pin ECP Signal IN/OUT Function
Signal
A low on this line indicates, that there is valid data at the
1 Strobe HostCLK Out host. When this pin is de-asserted, the +ve clock edge
should be used to shift the data into the device.
2-9 Data 0-7 Data 0-7 In/Out Data Bus. Bi-directional
A low on this line indicates, that there is valid data at the
10 Ack PeriphCLK In Device. When this pin is de-asserted, the +ve clock edge
should be used to shift the data into the Host.
When in reverse direction a HIGH indicates Data, while
11 Busy PeriphAck In a LOW indicates a Command Cycle.
In forward direction, functions as PeriphAck.
Paper Out /
12 nAckReverse In When Low, Device acknowledges Reverse Request.
End
13 Select X-Flag In Extensibility Flag
When in forward direction a HIGH indicates Data, while
Auto
14 Host Ack Out a LOW indicates a Command Cycle.
Linefeed
In reverse direction, functions as HostAck.
15 Error / PeriphRequest In A LOW set by the device indicates reverse data is
Fault available
16 Initialize nReverseRequest Out A LOW indicates data is in reverse direction
Select A HIGH indicates Host is in 1284 Transfer Mode. Taken
17 1284 Active Out
Printer low to terminate.
18-
Ground Ground GND Ground
25
Table 1. Pin Assignments For Extended Capabilities Parallel Port Connector.
The HostAck and PeriphAck lines indicate whether the signals on the data line are
data or a command. If these lines are high then data is placed on the data lines
(Pins 2-7). If a command cycle is taking place then the appropriate line will be low,
ie if the host is sending a command, then HostAck will be low or if the
device/peripheral is sending a command the PeriphAck line will be low.
A command cycle can be one of two things, either a RLE count or an address. This
is determined by the bit 7 (MSB) of the data lines, ie Pin 9. If bit 7 is a 0, then the
rest of the data (bits 0-6) is a run length count which is used with the data
compression scheme. However if bit 7 is a 1, then the data present on bits 0 to 6 is
a channel address. With one bit missing this can only be a value from 0 to
127(DEC).
and that the ECP handshake has many more steps. This would suggest that ECP
would be slower that SPP. However this is not the case as all of these steps above
are controlled by the hardware on your I/O control. If this handshake was
implemented via software control then it would be a lot slower that it's SPP
counterpart.
For example, if a string of 25 'A's were to be sent, then a run count byte equal to
24 would be sent first, followed by the byte 'A'. The receiving peripheral on receipt
of the Run Length Count, would expand (Repeat) the next byte a number of times
determined via the run count.
The Run Length Byte has to be distinguished from other bytes in the Data Path. It
is sent as a Command to the ECP's Address FIFO Port. Bytes sent to this register
can be of two things, a Run Length Count or an Address. These are distinguished
by the MSB, Bit 7. If Bit 7 is Set (1), then the other 7 bits, bits 0 to 6 is a channel
address. If Bit 7 is Reset (0), then the lower 7 bits is a run length count. By using
the MSB, this limits channel Addresses and Run Length Counts to 7 Bits (0 - 127).
Bit Function
7:5 Selects Current Mode of Operation
000 Standard Mode
001 Byte Mode
010 Parallel Port FIFO Mode
011 ECP FIFO Mode
100 EPP Mode
101 Reserved
110 FIFO Test Mode
111 Configuration Mode
4 ECP Interrupt Bit
3 DMA Enable Bit
2 ECP Service Bit
1 FIFO Full
0 FIFO Empty
Table 3 ECR - Extended Control Register
The three MSB of the Extended Control Register selects the mode of
operation. There are 7 possible modes of operation, but not all ports will
support all modes. The EPP mode is one such example, not being available
on some ports. Below is a table of Modes of Operation.
Modes of Operation
Standard Mode Selecting this mode will cause the ECP port to behave as a Standard Parallel Port,
without Bi-directional functionality.
Byte Mode /
Behaves as a SPP in Bi-directional (Reverse) mode.
PS/2 Mode
Parallel Port In this mode, any data written to the Data FIFO will be sent to the peripheral using
FIFO Mode the SPP Handshake. The hardware will generate the handshaking required. Useful
with non-ECP devices such as Printers. You can have some of the features of ECP
like FIFO buffers and hardware generation of handshaking but with the existing
SPP handshake instead of the ECP Handshake.
ECP FIFO Standard Mode for ECP Use. This mode uses the ECP Handshake, already
Mode described.
EPP On some chipsets, this mode will enable EPP to be used. While on others, this mode
Mode/Reserved is still reserved.
Reserved Currently Reserved
FIFO Test While in this mode, any data written to the Test FIFO Register will be placed into
Mode the FIFO and any data read from the Test FIFO register will be read from the
FIFO buffer. The FIFO Full/Empty Status Bits will reflect their true value, thus
FIFO depth, among other things can be determined in this mode.
Configuration In this mode, the two configuration registers, cnfgA & cnfgB become available at
Mode their designated Register Addresses.
As outlined above, when the port is set to operate in Standard Mode, it will
behave just like a Standard Parallel Port (SPP) with no bi-directional data
transfer. If you require bi-directional transfer, then set the mode to Byte
Mode. The Parallel Port FIFO mode and ECP FIFO mode both use hardware to
generate the necessary handshaking signals. The only difference between
each mode is that The Parallel Port FIFO Mode uses SPP handshaking, thus
can be used with your SPP printer. ECP FIFO mode uses ECP handshaking.
The FIFO test mode can be used to test the capacity of the FIFO Buffers as
well as to make sure they function correctly. When in FIFO test mode, any
byte which is written to the TEST FIFO (Base + 400h) is placed into the FIFO
buffer and any byte which is read from this register is taken from the FIFO
Buffer. You can use this along with the FIFO Full and FIFO Empty bits of the
Extended Control Register to determine the capacity of the FIFO Buffer. This
should normally be about 16 Bytes deep.
The other Bits of the ECR also play an important role in the operation of the
ECP Port. The ECP Interrupt Bit, (Bit 4) enables the use of Interrupts, while
the DMA Enable Bit (Bit 3) enables the use of Direct Memory Access. The
ECP Service Bit (Bit 2) shows if an interrupt request has been initiated. If so,
this bit will be set. Resetting this bit is different with different chips. Some
require you to Reset the Bit, E.g. Write a Zero to it. Others will reset once the
Register has been read.
The FIFO Full (Bit 1) and FIFO Empty (Bit 0) show the status of the FIFO
Buffer. These bits are direction dependent, thus note should be taken of the
Control Register's Bit 5. If bit 0 (FIFO Empty) is set, then the FIFO buffer is
completely empty. If Bit 1 is set then the FIFO buffer is Full. Thus, if neither
bit 0 or 1 is set, then there is data in FIFO, but is not yet full. These bits can
be used in FIFO Test Mode, to determine the capacity of the FIFO Buffer.
Bit Function
7 1 Interrupts are level triggered
0 Interrupts are edge triggered (Pulses)
6:4 00h Accepts Max. 16 Bit wide words
01h Accepts Max. 8 Bit wide words
02h Accepts Max. 32 Bit wide words
03h:07h Reserved for future expansion
3 Reserved
2 Host Recovery : Pipeline/Transmitter Byte included in FIFO?
In forward direction, the 1 byte in the transmitter pipeline doesn't affect
0
FIFO Full.
In forward direction, the 1 byte in the transmitter pipeline is include as
1
part of FIFO Full.
1:0 Host Recovery : Unsent byte(s) left in FIFO
00 Complete Pword
01 1 Valid Byte
10 2 Valid Bytes
11 3 Valid Bytes
Table 4 - Configuration Register A
Configuration Register A can be read to find out a little more about the ECP
Port. The MSB, shows if the card generates level interrupts or edge triggered
interrupts. This will depend upon the type of bus your card is using. Bits 4 to
6, show the buses width within the card. Some cards only have a 8 bit data
path, while others may have a 32 or 16 bit width. To get maximum efficiency
from your card, the software can read the status of these bits to determine
the Maximum Word Size to output to the port.
The 3 LSB's are used for Host Recovery. In order to recover from an error,
the software must know how many bytes were sent, by determining if there
are any bytes left in the FIFO. Some implementations may include the byte
sitting in the transmitter register, waiting to be sent as part of the FIFO's Full
Status, while others may not. Bit 2 determines weather or not this is the
case.
The other problem is that the Parallel Ports output is only 8 bits wide, and
that you many be using 16 bit or 32 bit I/O Instructions. If this is the case,
then part of your Port Word (Word you sent to port) may be sent. Therefore
Bits 0 and 1 give an indication of the number of valid bytes still left in the
FIFO, so that you can retransmit these.
Bit(s) Function
7 1 Compress outgoing Data Using RLE
0 Do Not compress Data
6 Interrupt Status - Shows the Current Status of the IRQ Pin
5:3 Selects or Displays Status of Interrupt Request Line.
000 Interrupt Selected Via Jumper
001 IRQ 7
010 IRQ 9
011 IRQ 10
100 IRQ 11
101 IRQ 14
110 IRQ 15
111 IRQ 5
2:0 Selects or Displays Status of the DMA Channel the Printer Card
Uses
000 Uses a Jumpered 8 Bit DMA Channel
001 DMA Channel 1
010 DMA Channel 2
011 DMA Channel 3
100 Uses a Jumpered 16 Bit DMA Channel
101 DMA Channel 5
110 DMA Channel 6
111 DMA Channel 7
Table 5 - Configuration B Register
Bit 7 of the cnfgB Register selects whether to compress outgoing data using
RLE (Run Length Encoding.) When Set, the host will compress the data
before sending. When reset, data will be sent to the peripheral raw
(Uncompressed). Bit 6 returns the status of the IRQ pin. This can be used to
diagnose conflicts as it will not only reflect the status of the Parallel Ports
IRQ, but and other device using this IRQ.
Bits 5 to 3 give status of about the Port's IRQ assignment. Likewise for bits 2
to 0 which give status of DMA Channel assignment. As mentioned above
these fields may be read/write. The disappearing species of Parallel Cards
which have Jumpers may simply show it's resources as "Jumpered" or it may
show the correct Line Numbers. However these of course will be read only.
Description.
This is the first interfacing example for the Parallel Port. We will start with
something simple. This example doesn't use the Bi-directional feature
found on newer ports, thus it should work with most, if no all Parallel
Ports. It however doesn't show the use of the Status Port as an input. So
what are we interfacing? A 16 Character x 2 Line LCD Module to the
Parallel Port. These LCD Modules are very common these days, and are
quite simple to work with, as all the logic required to run them is on
board.
Schematic
Circuit Description
Above is the quite simple schematic. The LCD panel's Enable and
Register Select is connected to the Control Port. The Control Port is an
open collector / open drain output. While most Parallel Ports have
internal pull-up resistors, there are a few which don't. Therefore by
incorporating the two 10K external pull up resistors, the circuit is more
portable for a wider range of computers, some of which may have no
internal pull up resistors.
We make no effort to place the Data bus into reverse direction. Therefore
we hard wire the R/W line of the LCD panel, into write mode. This will
cause no bus conflicts on the data lines. As a result we cannot read back
the LCD's internal Busy Flag which tells us if the LCD has accepted and
finished processing the last instruction. This problem is overcome by
inserting known delays into our program.
The 10k Potentiometer controls the contrast of the LCD panel. Nothing
fancy here. As with all the examples, I've left the power supply out. You
can use a bench power supply set to 5v or use a onboard +5 regulator.
Remember a few de-coupling capacitors, especially if you have trouble
with the circuit working properly.
#include <dos.h>
#include <string.h>
void main(void)
{
char string[] = {"Testing 1,2,3 "
"It' Works ! "};
char init[10];
int count;
int len;
init[0] = 0x0F; /* Init Display */
init[1] = 0x01; /* Clear Display */
init[2] = 0x38; /* Dual Line / 8 Bits */
len = strlen(string);
The Serial Port is harder to interface than the Parallel Port. In most cases, any device you
connect to the serial port will need the serial transmission converted back to parallel so
that it can be used. This can be done using a UART. On the software side of things, there
are many more registers that you have to attend to than on a Standard Parallel Port.
(SPP)
So what are the advantages of using serial data transfer rather than parallel?
1. Serial Cables can be longer than Parallel cables. The serial port transmits a '1' as -3 to
-25 volts and a '0' as +3 to +25 volts where as a parallel port transmits a '0' as 0v and
a '1' as 5v. Therefore the serial port can have a maximum swing of 50V compared to
the parallel port which has a maximum swing of 5 Volts. Therefore cable loss is not
going to be as much of a problem for serial cables than they are for parallel.
2. You don't need as many wires than parallel transmission. If your device needs to be
mounted a far distance away from the computer then 3 core cable (Null Modem
Configuration) is going to be a lot cheaper that running 19 or 25 core cable. However
you must take into account the cost of the interfacing at each end.
3. Infra Red devices have proven quite popular recently. You may of seen many electronic
diaries and palmtop computers which have infra red capabilities build in. However
could you imagine transmitting 8 bits of data at the one time across the room and
being able to (from the devices point of view) decipher which bits are which? Therefore
serial transmission is used where one bit is sent at a time. IrDA-1 (The first infra red
specifications) was capable of 115.2k baud and was interfaced into a UART. The pulse
length however was cut down to 3/16th of a RS232 bit length to conserve power
considering these devices are mainly used on diaries, laptops and palmtops.
4. Microcontroller's have also proven to be quite popular recently. Many of these have in
built SCI (Serial Communications Interfaces) which can be used to talk to the outside
world. Serial Communication reduces the pin count of these MPU's. Only two pins are
commonly used, Transmit Data (TXD) and Receive Data (RXD) compared with at least 8
pins if you use a 8 bit Parallel method (You may also require a Strobe).
Table of Contents
Part 1 : Hardware (PC's)
Hardware Properties
Serial Pinouts (D25 and D9 connectors)
Pin Functions
Null Modems
Loopback Plugs
DTE/DCE Speeds
Flow Control
The UART (8250's and Compatibles)
Type of UARTS (For PC's)
Part 2 : Serial Ports' Registers (PC's)
Port Addresses and IRQ's
Table of Registers
DLAB ?
Interrupt Enable Register (IER)
Interrupt Identification Register (IIR)
First In / First Out Control Register (FCR)
Line Control Register (LCR)
Modem Control Register (MCR)
Line Status Register (LSR)
Modem Status Register (MSR)
Scratch Register
Part 3 : Programming (PC's)
Polling or Interrupt Driven?
Source Code - Termpoll.c (Polling Version)
Source Code - Buff1024.c (ISR Version)
Interrupt Vectors
Interrupt Service Routine
UART Configuration
Main Routine (Loop)
Determining the type of UART via Software
Part 4 : External Hardware - Interfacing Methods
RS-232 Waveforms
RS-232 Level Converters
Making use of the Serial Format
8250 and compatable UART's
CDP6402, AY-5-1015 / D36402R-9 etc UARTs
Microcontrollers
Part One : Hardware (PC's)
Hardware Properties
Devices which use serial cables for their communication are split into two
categories. These are DCE (Data Communications Equipment) and DTE (Data
Terminal Equipment.) Data Communications Equipment are devices such as your
modem, TA adapter, plotter etc while Data Terminal Equipment is your Computer
or Terminal.
The electrical specifications of the serial port is contained in the EIA (Electronics
Industry Association) RS232C standard. It states many parameters such as -
Above is no where near a complete list of the EIA standard. Line Capacitance,
Maximum Baud Rates etc are also included. For more information please consult
the EIA RS232-C standard. It is interesting to note however, that the RS232C
standard specifies a maximum baud rate of 20,000 BPS!, which is rather slow by
today's standards. A new standard, RS-232D has been recently released.
Serial Ports come in two "sizes", There are the D-Type 25 pin connector and the D-
Type 9 pin connector both of which are male on the back of the PC, thus you will
require a female connector on your device. Below is a table of pin connections for
the 9 pin and 25 pin D-Type connectors.
Null Modems
A Null Modem is used to connect two DTE's together. This is commonly used as a
cheap way to network games or to transfer files between computers using
Zmodem Protocol, Xmodem Protocol etc. This can also be used with many
Microprocessor Development Systems.
Above is my preferred method of wiring a Null Modem. It only requires 3 wires (TD,
RD & SG) to be wired straight through thus is more cost effective to use with long
cable runs. The theory of operation is reasonably easy. The aim is to make to
computer think it is talking to a modem rather than another computer. Any data
transmitted from the first computer must be received by the second thus TD is
connected to RD. The second computer must have the same set-up thus RD is
connected to TD. Signal Ground (SG) must also be connected so both grounds are
common to each computer.
The Data Terminal Ready is looped back to Data Set Ready and Carrier Detect on
both computers. When the Data Terminal Ready is asserted active, then the Data
Set Ready and Carrier Detect immediately become active. At this point the
computer thinks the Virtual Modem to which it is connected is ready and has
detected the carrier of the other modem.
All left to worry about now is the Request to Send and Clear To Send. As both
computers communicate together at the same speed, flow control is not needed
thus these two lines are also linked together on each computer. When the
computer wishes to send data, it asserts the Request to Send high and as it's
hooked together with the Clear to Send, It immediately gets a reply that it is ok to
send and does so.
Notice that the ring indicator is not connected to anything of each end. This line is
only used to tell the computer that there is a ringing signal on the phone line. As
we don't have a modem connected to the phone line this is left disconnected.
LoopBack Plug
This loopback plug can come in extremely handy when writing Serial /
RS232 Communications Programs. It has the receive and transmit lines
connected together, so that anything transmitted out of the Serial Port is
immediately received by the same port. If you connect this to a Serial Port an
load a Terminal Program, anything you type will be immediately displayed
on the screen. This can be used with the examples later in this tutorial.
Please note that this is not intended for use with Diagnostic Programs and
thus will probably not work. For these programs you require a differently
Figure 2 : Loopback Plug wired Loop Back plug which may vary from program to program.
Wiring Diagram
We have already talked briefly about DTE & DCE. A typical Data Terminal Device is
a computer and a typical Data Communications Device is a Modem. Often people
will talk about DTE to DCE or DCE to DCE speeds. DTE to DCE is the speed between
your modem and computer, sometimes referred to as your terminal speed. This
should run at faster speeds than the DCE to DCE speed. DCE to DCE is the link
between modems, sometimes called the line speed.
Most people today will have 28.8K or 33.6K modems. Therefore we should expect
the DCE to DCE speed to be either 28.8K or 33.6K. Considering the high speed of
the modem we should expect the DTE to DCE speed to be about 115,200 BPS.
(Maximum Speed of the 16550a UART) This is where some people often fall into a
trap. The communications program which they use have settings for DCE to DTE
speeds. However they see 9.6 KBPS, 14.4 KBPS etc and think it is your modem
speed.
Today's Modems should have Data Compression build into them. This is very much
like PK-ZIP but the software in your modem compresses and decompresses the
data. When set up correctly you can expect compression ratios of 1:4 or even
higher. 1 to 4 compression would be typical of a text file. If we were transferring
that text file at 28.8K (DCE-DCE), then when the modem compresses it you are
actually transferring 115.2 KBPS between computers and thus have a DCE-DTE
speed of 115.2 KBPS. Thus this is why the DCE-DTE should be much higher than
your modem's connection speed.
Some modem manufacturers quote a maximum compression ratio as 1:8. Lets say
for example its on a new 33.6 KBPS modem then we may get a maximum 268,800
BPS transfer between modem and UART. If you only have a 16550a which can do
115,200 BPS tops, then you would be missing out on a extra bit of performance.
Buying a 16C650 should fix your problem with a maximum transfer rate of 230,400
BPS.
However don't abuse your modem if you don't get these rates. These are
MAXIMUM compression ratios. In some instances if you try to send a already
compressed file, your modem can spend more time trying the compress it, thus
you get a transmission speed less than your modem's connection speed. If this
occurs try turning off your data compression. This should be fixed on newer
modems. Some files compress easier than others thus any file which compresses
easier is naturally going to have a higher compression ratio.
Flow Control
So if our DTE to DCE speed is several times faster than our DCE to DCE speed the
PC can send data to your modem at 115,200 BPS. Sooner or later data is going to
get lost as buffers overflow, thus flow control is used. Flow control has two basic
varieties, Hardware or Software.
Software flow control, sometimes expressed as Xon/Xoff uses two characters Xon
and Xoff. Xon is normally indicated by the ASCII 17 character where as the ASCII
19 character is used for Xoff. The modem will only have a small buffer so when the
computer fills it up the modem sends a Xoff character to tell the computer to stop
sending data. Once the modem has room for more data it then sends a Xon
character and the computer sends more data. This type of flow control has the
advantage that it doesn't require any more wires as the characters are sent via the
TD/RD lines. However on slow links each character requires 10 bits which can slow
communications down.
Hardware flow control is also known as RTS/CTS flow control. It uses two wires in
your serial cable rather than extra characters transmitted in your data lines. Thus
hardware flow control will not slow down transmission times like Xon-Xoff does.
When the computer wishes to send data it takes active the Request to Send line. If
the modem has room for this data, then the modem will reply by taking active the
Clear to Send line and the computer starts sending data. If the modem does not
have the room then it will not send a Clear to Send.
UART stands for Universal Asynchronous Receiver / Transmitter. Its the little box of
tricks found on your serial card which plays the little games with your modem or
other connected devices. Most cards will have the UART's integrated into other
chips which may also control your parallel port, games port, floppy or hard disk
drives and are typically surface mount devices. The 8250 series, which includes
the 16450, 16550, 16650, & 16750 UARTS are the most commonly found type in
your PC. Later we will look at other types which can be used in your homemade
devices and projects.
The 16550 is chip compatible with the 8250 & 16450. The only two differences are
pins 24 & 29. On the 8250 Pin 24 was chip select out which functioned only as a
indicator to if the chip was active or not. Pin 29 was not connected on the
8250/16450 UARTs. The 16550 introduced two new pins in their place. These are
Transmit Ready and Receive Ready which can be implemented with DMA (Direct
Memory Access). These Pins have two different modes of operation. Mode 0
supports single transfer DMA where as Mode 1 supports Multi-transfer DMA.
Mode 0 is also called the 16450 mode. This mode is selected when the FIFO buffers
are disabled via Bit 0 of the FIFO Control Register or When the FIFO buffers are
enabled but DMA Mode Select = 0. (Bit 3 of FCR) In this mode RXRDY is active low
when at least one character (Byte) is present in the Receiver Buffer. RXRDY will go
inactive high when no more characters are left in the Receiver Buffer. TXRDY will
be active low when there are no characters in the Transmit Buffer. It will go
inactive high after the first character / byte is loaded into the Transmit Buffer.
Mode 1 is when the FIFO buffers are active and the DMA Mode Select = 1. In Mode
1, RXRDY will go active low when the trigger level is reached or when 16550 Time
Out occurs and will return to inactive state when no more characters are left in the
FIFO. TXRDY will be active when no characters are present in the Transmit Buffer
and will go inactive when the FIFO Transmit Buffer is completely Full.
All the UARTs pins are TTL compatible. That includes TD, RD, RI, DCD, DSR, CTS,
DTR and RTS which all interface into your serial plug, typically a D-type connector.
Therefore RS232 Level Converters (which we talk about in detail later) are used.
These are commonly the DS1489 Receiver and the DS1488 as the PC has +12 and
-12 volt rails which can be used by these devices. The RS232 Converters will
convert the TTL signal into RS232 Logic Levels.
The UART requires a Clock to run. If you look at your serial card a common crystal
found is either a 1.8432 MHZ or a 18.432 MHZ Crystal. The crystal in connected to
the XIN-XOUT pins of the UART using a few extra components which help the
crystal to start oscillating. This clock will be used for the Programmable Baud Rate
Generator which directly interfaces into the transmit timing circuits but not directly
into the receiver timing circuits. For this an external connection mast be made
from pin 15 (BaudOut) to pin 9 (Receiver clock in.) Note that the clock signal will
be at Baudrate * 16.
If you are serious about pursuing the 16550 UART used in your PC further, then
would suggest downloading a copy of the PC16550D data sheet from National
Semiconductors Site. Data sheets are available in .PDF format so you will need
Adobe Acrobat Reader to read these. Texas Instruments has released the 16750
UART which has 64 Byte FIFO's. Data Sheets for the TL16C750 are available from
the Texas Instruments Site.
8250 First UART in this series. It contains no scratch register. The 8250A was an improved
version of the 8250 which operates faster on the bus side.
8250A This UART is faster than the 8250 on the bus side. Looks exactly the same to software
than 16450.
8250B Very similar to that of the 8250 UART.
16450 Used in AT's (Improved bus speed over 8250's). Operates comfortably at 38.4KBPS.
Still quite common today.
16550 This was the first generation of buffered UART. It has a 16 byte buffer, however it
doesn't work and is replaced with the 16550A.
16550A Is the most common UART use for high speed communications eg 14.4K & 28.8K
Modems. They made sure the FIFO buffers worked on this UART.
16650 Very recent breed of UART. Contains a 32 byte FIFO, Programmable X-On / X-Off
characters and supports power management.
16750 Produced by Texas Instruments. Contains a 64 byte FIFO.
Above is the standard port addresses. These should work for most P.C's. If you just
happen to be lucky enough to own a IBM P/S2 which has a micro-channel bus, then
expect a different set of addresses and IRQ's. Just like the LPT ports, the base
addresses for the COM ports can be read from the BIOS Data Area.
Start Address Function
0000:0400 COM1's Base Address
0000:0402 COM2's Base Address
0000:0404 COM3's Base Address
0000:0406 COM4's Base Address
Table 4 - COM Port Addresses in the BIOS Data Area;
The above table shows the address at which we can find the Communications
(COM) ports addresses in the BIOS Data Area. Each address will take up 2 bytes.
The following sample program in C, shows how you can read these locations to
obtain the addresses of your communications ports.
#include <stdio.h>
#include <dos.h>
void main(void)
{
unsigned int far *ptraddr; /* Pointer to location of Port Addresses */
unsigned int address; /* Address of Port */
int a;
When writing a communications program you have two methods available to you.
You can poll the UART, to see if any new data is available or you can set up an
interrupt handler to remove the data from the UART when it generates a interrupt.
Polling the UART is a lot slower method, which is very CPU intensive thus can only
have a maximum speed of around 34.8 KBPS before you start losing data. Some
newer Pentium Pro's may be able to achieve better rates that this. The other
option is using a Interrupt handler, and that's what we have used here. It will very
easily support 115.2K BPS, even on low end computers.
Polling the UART should not be dismissed totally. It's a good method for
diagnostics. If you have no idea of what address your card is at or what IRQ you
are using you can poll the UART at several different addresses to firstly find which
port your card is at and which one your modem is attached to. Once you know this
information, then you can set up the Interrupt routines for the common IRQs and
by enabling one IRQ at a time using the Programmable Interrupt Controller you can
find out your IRQ, You don't even need a screw driver!
The first step to using interrupts is to work out which interrupt services your serial
card. Table 13 shows the base addresses and IRQ's of some standard ports. IRQ's 3
and 4 are the two most commonly used. IRQ 5 and 7 are sometimes used.
Interrupt Vectors
Once we know the IRQ the next step is to find it's interrupt vector or software
interrupt as some people may call it. Basically any 8086 processor has a set of 256
interrupt vectors numbered 0 to 255. Each of these vectors contains a 4 byte code
which is an address of the Interrupt Service Routine (ISR). Fortunately C being a
high level language, takes care of the addresses for us. All we have to know is the
actual interrupt vector.
The above table shows only the interrupts which are associated with IRQ's. The
other 240 are of no interest to us when programming RS-232 type
communications.
For example if we were using COM3 which has a IRQ of 4, then the interrupt vector
would be 0C in hex. Using C we would set up the vector using the instruction
setvect(0x0C, PORT1INT); where PORT1INT would lead us to a set of instructions which
would service the interrupt.
However before we proceed with that I should say that it is wise to record the old
vectors address and then restore that address once the program is finished. This is
done using oldport1isr = getvect(INTVECT); where oldport1isr is defined using void
interrupt (*oldport1isr)();
Not only should you store the old vector addresses, but also the configuration the
UART was in. Why you Ask? Well it's simple, I wrote a communications program
which was fully featured in the chat side of things. It had line buffering, so no body
could see my spelling mistakes or how slowly I typed. It included anti-bombing
routines and the list goes on. However I couldn't be bothered to program any file
transfer protocols such as Zmodem etc into my communications program.
Therefore I either had to run my communications program in the background of
Telemate using my communications program for chat and everything else it was
designed for and using Telemate to download files. Another method was to run,
say Smodem as a external protocol to my communications program.
Doing this however would mean that my communications program would override
the original speed, parity etc and then when I returned to the original
communications program, everything stopped. Therefore by saving the old
configuration, you can revert back to it before you hand the UART back over to the
other program. Makes sense? However if you don't have any of these programs
you can save yourself a few lines of code. This is what we have done here.
Now, could we be off track just a little? Yes that's right, PORT1INT is the label to
our interrupt handler called a Interrupt Service Routine (ISR). You can put just
about anything in here you want. However calling some DOS routines can be a
problem.
Another device is the MAX-232. It includes a Charge Pump, which generates +10V
and -10V from a single 5v supply. This I.C. also includes two receivers and two
transmitters in the same package. This is handy in many cases when you only
want to use the Transmit and Receive data Lines. You don't need to use two chips,
one for the receive line and one for the transmit. However all this convenience
comes at a price, but compared with the price of designing a new power supply it
is very cheap.
There are also many variations of these devices. The large value of capacitors are
not only bulky, but also expensive. Therefore other devices are available which use
smaller capacitors and even some with inbuilt capacitors. (Note : Some MAX-232's
can use 1 micro farad Capacitors). However the MAX-232 is the most common, and
thus we will use this RS-232 Level Converter in our examples.
Making use of the Serial Format
In order to do anything useful with our Serially transmitted data, we must convert
it back to Parallel. (You could connect an LED to the serial port and watch it flash if
you really want too, but it's not extremely useful). This in the past has been done
with the use of UART's. However with the popularity of cheap Microcontroller's,
these can be more suited to many applications. We will look into the advantages
and disadvantages of each method.
8250 and Compatible UARTs
We have already looked at one type of UART, the 8250 and compatibles found in
your PC. These devices have configuration registers accessible via the data and
address buses which have to be initialized before use. This is not a problem if your
device which you are building uses a Microprocessor. However if you are making a
stand alone device, how are you going to initialize it?
Most Microprocessors / Microcontrollers these days can be brought with build-in
Serial Communication Interfaces (SCI). Therefore there is little need to connect a
40 pin 16550 to, for example a 68HC11 when you can buy one built in. If you are
still in love with the Z-80 or 8086 then an 16550 may be option! (or if you are like
myself, the higher chip count the better. After all it looks more complicated and
impressive! - But a headache to debug!)
Figure 8 : Pin Diagrams for 16550, 16450 & 8250 UARTs
Pin No. Name Notes
Pin 1:8 D0:D7 Data Bus
Receiver Clock Input. The frequency of this input should equal the
Pin 9 RCLK
receivers baud rate x 16
Pin 10 RD Receive Data
Pin 11 TD Transmit Data
Pin 12 CS0 Chip Select 0 - Active High
Pin 13 CS1 Chip Select 1 - Active High
Pin 14 nCS2 Chip Select 2 - Active Low
Baud Output - Output from Programmable Baud Rate Generator.
Pin 15 nBAUDOUT
Frequency = (Baud Rate x 16)
Pin 16 XIN External Crystal Input - Used for Baud Rate Generator Oscillator
Pin 17 XOUT External Crystal Output
Pin 18 nWR Write Line - Inverted
Pin 19 WR Write Line - Not Inverted
Pin 20 VSS Connected to Common Ground
Pin 21 RD Read Line - Inverted
Pin 22 nRD Read Line - Not Inverted
Driver Disable. This pin goes low when CPU is reading from
Pin 23 DDIS UART. Can be connected to Bus Transceiver in case of high
capacity data bus.
Pin 24 nTXRDY Transmit Ready
Address Strobe. Used if signals are not stable during read or write
Pin 25 nADS
cycle
Pin 26 A2 Address Bit 2
Pin 27 A1 Address Bit 1
Pin 28 A0 Address Bit 0
Pin 29 nRXRDY Receive Ready
Pin 30 INTR Interrupt Output
Pin 31 nOUT2 User Output 2
Pin 32 nRTS Request to Send
Pin 33 nDTR Data Terminal Ready
Pin 34 nOUT1 User Output 1
Pin 35 MR Master Reset
Pin 36 nCTS Clear To Send
Pin 37 nDSR Data Set Ready
Pin 38 nDCD Data Carrier Detect
Pin 39 nRI Ring Indicator
Pin 40 VDD + 5 Volts
Table 17 : Pin Assignments for 16550A UART
For more information on the 16550 and compatible UART's see The UART (8250's
and Compatibles) in the first part of this tutorial.
CDP6402, AY-5-1015 / D36402R-9 etc UARTs
Microcontrollers
It is also possible to use microcontrollers to transmit and receive Serial data. As we
have already covered, some of these MCU's (Micro Controller Units) have built in
UART's among other things. Take the application we have used above. We want to
monitor analog voltages using a ADC and then send them serially to the PC. If the
Microcontroller also has a ADC built in along with the UART or SCI, then we could
simply program the device and connect a RS-232 Line Driver. This would minimize
your chip count and make your PCB much smaller.
Take the second example, displaying the serial data to a common 16 character x 2
line LCD display. A common problem with the LCD modules, is they don't accept
cartridge returns, line-feeds, form-feeds etc. By using a microcontroller, not only
can you emulate the UART, but you can also program it to clear the screen, should
a form-feed be sent or advance to the next line should a Line-feed be sent.
The LCD example also required some additional logic (An Inverter) to reset the
data receive line on the UART, and provide a -ve edge on the enable of the LCD to
display the data present on the pins. This can all be done using the Microcontroller
and thus reducing the chip count and the cost of the project.
Talking of chip count, most Microcontrollers have internal oscillators thus you don't
require the 74HC4060 14 Bit Binary Counter and Oscillator. Many Microcontrollers
such as the 68HC05J1A and PIC16C84 have a smaller pin count, than the 40 Pin
UART. This not only makes the project smaller in size, it reduces complexity of the
PCB.
But there are also many disadvantages of the Microcontroller. The major one, is
that you have to program it. For the hobbyist, you may not have a development
system for a Microcontroller or a method of programming it. Then you have to
learn the micro's code and work out how to tackle the problem. At least with the
UART, all you did was plug it in, wire it up and it worked. You can't get much
simpler that that.
So far we have only discussed Full Duplex Transmission, that is that we can
transmit and receive at the same time. If our Microcontroller doesn't have a SCI
then we can Emulate a RS-232 port using a Parallel line under software control.
However Emulation has it's dis-advantages. It only supports slow transmission
speeds, commonly 2400, 9600 or maybe even 19,200 BPS if you are lucky. The
other disadvantage is that it's really only effective in half duplex mode. That is, it
can only communicate in one direction at any one given time. However in many
applications this is not a problem.
As there are many different types of Micro-Controllers all with their different
instruction sets, it is very hard to give examples here which will suit everyone. Just
be aware that you can use them for serial communications and hopefully at a later
date, I can give a limited number of examples with one micro.
Using Interrupts
Interrupts
What are Interrupts?
Interrupts and Intel Architecture
Hardware Interrupts
Programming
Implementing the Interrupt Service Routine (ISR)
Using your new Interrupt Service Routine
The Programmable Interrupt Controller's Operation
The Programmable Interrupt Controller
IRQ2/IRQ9 Redirection
The Programmable Interrupt Controller's Registers
Programmable Interrupt Controller's Addresses
Initialization Command Words (ICWs)
Operation Control Words (OCWs)
Feedback
Feedback
As you could imagine, polling the port would consume quite some time. Time
which could be used doing other things such refreshing the screen, displaying the
time etc. A better alternative would be to use Interrupts. Here, the processor does
your tasks such as refreshing the screen, displaying the time etc, and when a I/O
Port/Device needs attention as a byte has been received or status has changed,
then it sends a Interrupt Request (IRQ) to the processor.
Once the processor receives an Interrupt Request, it finishes its current instruction,
places a few things on the stack, and executes the appropriate Interrupt Service
Routine (ISR) which can remove the byte from the port and place it in a buffer.
Once the ISR has finished, the processor returns to where it left off.
Using this method, the processor doesn't have to waste time, looking to see if your
I/O Device is in need of attention, but rather the device will interrupt the processor
when it needs attention.
The average PC, only has 15 Hardware IRQ's plus one Non-Maskable IRQ. The rest
of the interrupt vectors are used for software interrupts and exception handlers.
Exception handlers are routines like ISR's which get called or interrupted when an
error results. Such an example is the first Interrupt Vector which holds the address
of the Divide By Zero, Exception handler. When a divide by zero occurs the
Microprocessor fetches the address at 0000:0000 and starts executing the code at
this Address.
Hardware Interrupts
The Programmable Interrupt Controller (PIC) handles hardware interrupts. Most
PC's will have two of them located at different addresses. One handles IRQ's 0 to 7
and the other, IRQ's 8 to 15, giving a total of 15 individual IRQ lines, as the second
PIC is cascaded into the first, using IRQ2.
Most of the PIC's initialization is done by BIOS, thus we only have to worry about
two instructions. The PIC has a facility available where we can mask individual
IRQ's so that these requests will not reach the Processor. Thus the first instruction
is to the Operation Control Word 1 (OCW1) to set which IRQ's to mask and which
IRQ's not too.
As there are two PIC's located at different addresses, we must first determine
which PIC we need to use. The first PIC, located at Base Address 0x20h controls
IRQ 0 to IRQ 7. The bit format of PIC1's Operation Control Word 1 is shown below in
table 2.
Note that IRQ 2 is connected to PIC2, thus if you mask this IRQ, then you will be
disabling IRQ's 8 to 15.
The second PIC located at a base address of 0xA0h controls IRQs 8 to 15. Below is
the individual bits required to make up it's Operation Control Word.
As the above table shows the bits required to disable an IRQ, we must invert them
should we want to enable an IRQ. For example, if we want to enable IRQ 3 then we
would send the byte 0xF7 as OCW1 to PIC1. But what happens if one of these IRQs
are already enabled and then we come along and disable it?
Therefore we must first get the mask and use the AND function to output the byte
back to the register with our changes so to cause the least upset to the other IRQs.
Going back to our IRQ3 example, we could use outportb(0x21,(inportb(0x21) & 0xF7); to
enable IRQ3. Take note that the OCW1 goes to the register at Base + 1.
The same procedure must be used to mask (disable) an IRQ once we are finished
with it. However this time we must OR the byte 0x08 to the contents of OCW1.
Such and example of code is outportb(0x21,(inportb(0x21) | 0x08);
The other PIC instruction we have to worry about is the End of Interrupt (EOI). This
is sent to the PIC at the end of the Interrupt Service Routine so that the PIC can
reset the In Service Register. See The Programmable Interrupt Controller for more
information. An EOI can be sent using outportb(0x20,0x20); for PIC1 or
outportb(0xA0,0x20); for PIC2
oldhandler();
void main(void)
{
oldhandler = getvect(INTNO); /* Save Old Interrupt Vector */
setvect(INTNO, yourisr); /* Set New Interrupt Vector Entry */
outportb(0x21,(inportb(0x21) & 0xF7)); /* Un-Mask (Enable) IRQ3 */
Schematic
Circuit Description
The above circuit when in a working state, will wait for a byte to be sent to it before it star
the analog conversion and sends data back to the computer using the 8N1 serial format a
9600 BPS. The circuit is based on a CDP6402C or equivalent UART. This, if you want to cal
is the brains of the operation and performs the conversion of Parallel data to a Serial form
for transmission. The Analog to Digital Conversion is done by the ADC0804, while the MAX
is used to convert TTL/CMOS voltage levels into RS-232 Voltage Levels. The 74HC4060 is a
Oscillator/Divider which is used to generate the UART's Clock.
The Analog to Digital Converter (ADC0804) starts it's conversion when the UART's Data
Received line becomes active. Many people at this stage will say that this circuit cannot w
- The Data Received (DR) output is Active High, while the nWrite (WR) input to the ADC is
Active Low. This circuit is quite correct. If we look at the ADC's operation, on a high to low
transition of the nWrite input the internal Successive Approximation and Shift Registers ar
reset. Provided the nWrite line remains in this state the ADC will remain reset. The conver
process will start when a low to high transition is made on the nWrite input.
Therefore getting back to this circuit, the Data Received output will remain low while there
no data to be received, thus the ADC will remain in the reset mode. When data is received
the UART, a low to high transition will result on the Data Received line and thus on the
connected nWrite pin of the ADC.
This low to high transition will cause the ADC to spring to life and make a digital conversio
the analog voltage on it's pins. Once the conversion is finished, it's nINTR (Interrupt) line w
become active low. This signal is then used to tell the UART to send the data residing on it
Transmitter Buffer Register inputs (TBR8:TBR1). nINTR is also connected to the UART's Da
Received Reset so that the Data Received line will be reset. The circuit is then ready to
repeat the entire process upon receiving the next byte.
#include <dos.h>
#include <stdio.h>
#include <conio.h>
int bufferin = 0;
int bufferout = 0;
unsigned char ch;
char buffer[1025];
void main(void)
{
int c;
outportb(PORT1 + 1 , 0); /* Turn off interrupts - Port1 */
do {
if (kbhit()){c = getch();
outportb(PORT1, c);}
} while (c !=27);
}
The above source code was copied from the example given in the Interfacing the Serial /
RS232 Port. The only modifications made was to change the Baud rate to 9600 BPS and
include an optional line, shown below, to calculate the voltage present at the ADC's pins.
printf("%f volts\n",(float)ch/256 * 5);}
The program can be modified to start the conversion at fixed intervals and to log the recei
result to file. This makes the above circuit more useful, than it is currently presented.
Data Sheets
Data Sheets for all the I.C's used in this example can sought on-line from the Internet. This
a list of where the Author obtained his data sheets from. Some semiconductors may be
available from other manufacturers. The URL for the manufacturer's homepage is given. Y
will need to search for the data sheet using their site's search engines.
I.C's Name Part Number Link to Manufacturers Homepa
CMOS Universal Asynchronous Receiver/Transmitter (UART) CDP6402 Harris Semiconductor
RS-232 Level Converter MAX232 Maxim Integrated Products
8 Bit Analog to Digital Converter ADC0804 Harris Semiconductor
14 Stage Binary Counter 74HC4060 National Semiconductor