Copyright 1999, Analog Devices, Inc. All rights reserved. Analog Devices assumes no responsibility for customer product design or the use or application of customers’ products
or for any infringements of patents or rights of others which may result from Analog Devices assistance. All trademarks and logos are property of their respective holders.
Information furnished by Analog Devices Applications and Development Tools Engineers is believed to be accurate and reliable, however no responsibility is assumed by Analog
Devices regarding the technical accuracy of the content provided in all Analog Devices’ Engineer-to-Engineer Notes.
Implementing A Software UART On The
ADSP-2181 EZ-KIT-LITE
a
EE-89Page 2
Technical Notes on using Analog Devices’ DSP components and development tools
This document describes a software implementation of a Universal Asynchronous Receiver Transmitter
(UART). The UART is implemented as a program running on the ADSP-2181 EZ Kit Lite. This document
will also provide basic background on serial and asynchronous transmission.
2. BACKGROUND
2.1 Serial Communication
Digital data are transmitted along paths that may physically consist of wires, radio waves, microwaves.
Such paths are often referred to as data buses. The digital data that are carried on such buses are encoded in a
digital format such as BCD, ASCII, or 8-bit words.
When data are transmitted serially, only one data path is required since the data are sent one bit at a
time. Cabling costs are lower than other methods of communication since serial communication requires the
minimum amount of wires. Serial transmission methods are characterized by how many bits per second they
can transmit. This unit of measurement is call a baud (1 bit/s). Common baud rates in serial systems are 110,
300, 600, 1200, 2400, 4800, 9600 and 19200.
2.2 Asynchronous Serial Communication
Most serial interfacing is done in an asynchronous manner. In this method, the transmitter sends a
character whenever one is available. And there is no synchronization clock pulse between the transmitter and
receiver to control the start of a character. This method is relatively slow since it requires a handshake for each
character of data transfer. In serial asynchronous systems, however, handshaking is performed by using a start
bit and one or two stop bits at the beginning and end of each character that is transmitted (As shown in Figure
1). The start bit is a logic low and the stop bit is a logic high. A parity bit is sometime added after the end of
the data bits for the receiver to detect transmission error. The number of such start, stop, and parity bits must
be agreed upon by both the transmitter and receiver.
EE-89Page 4
Technical Notes on using Analog Devices’ DSP components and development tools
Start <-------------------- Data Bits -------------------> Parity Stop
idle state 0 1 2 3 4 5 6 7 idle state
Figure 1 - ASCII character ‘8’ with one start bit, one even parity bit and one stop bit
2.3 Universal Asynchronous Receiver/Transmitter
The Universal Asynchronous Receiver/Transmitter (UART) is a dedicated single chip that is controlled
by a internal clock. This chip converts characters into a series of pulses or a series of pulses back into
characters. Using its clock, the UART transmitter controls the duration of pulses with no delay between them
as it sends a character. The receiver always monitors the incoming line and when a start bit is detected, the
UART will clock in bits at a set baud rate. When the receiver has collected all the data bits, it converts them
into a character and stops sampling.
A Digital Signal Processor (DSP) can be programmed to perform the same operation as a dedicated
UART chip. This can be accomplished by one of three methods. The first method is to tie the data receive line
to the interrupt input of the processor so that when a start bit comes along, the processor gets interrupted. This
lets the processor perform some other task and interrupts occur whenever data comes along on the serial line.
The second method is to have the transmit and receive lines of the serial device connected to the FLAG OUT
and the FLAG IN pins on the DSP. The Processor will have to poll the FLAG IN pin continuously using a
timer to see if a start bit is present. This method may tie up the processor. The third method uses the serial port
instead of the timer and the FLAG IN pin to sample and output data. The main advantage of this technique is
that it uses no timer interrupt, keeping the timer free for other operations. Also, no overhead will be produced
with the timer interrupt service routine (3 times per bit * 8 bits = 24 services).
The example program and the UART driver in this example polls the FLAG IN pin continuously and
uses the timer to implement UART. In this example, the ADSP-2181 transmits and receives serial data
asynchronously by connecting the transmit and receive lines of the serial device to the FLAG OUT and the
EE-89Page 5
Technical Notes on using Analog Devices’ DSP components and development tools
FLAG IN pins. When there is a character to be sent by the DSP, the software transmitter converts it to a
sequence of zeros and ones, and sends them down the line contiguously, LSB (Least Significant Bit) first. When
the DSP finishes sending a character, the line goes into an idle (high) state until the transmitter sends other
character. When a character is available to be received, the software receiver shifts in bits and constructs
words by sampling the FLAG IN pin.
3. HARDWARE
A serial cable is used to connect he EZ Kit Lite board to the serial device. The ADSP-2181 is
interfaced to an RS-232 line driver which is in turn connected to any RS-232 compatible device. The line
driver is used to convert the 5 volt logic level of the ADSP-2181 to the proper RS-232 line voltages, and vice
versa.
Figure 2 shows the connection between the ADSP-2181 and the line driver ADM232AAR. The
FLAG IN and FLAG OUT pins are used as independent receive and transmit lines.
DSP ADM232AAR RS-232 Connector
ADSP-2181FO RX
FI TX
Figure 2 - EZ Kit Lite System Configuration
EE-89Page 6
Technical Notes on using Analog Devices’ DSP components and development tools
The UART program supports most common baud rates. However, the autobaud feature can only
detect 2400, 3600, 9200 and 19200 baud. The word to be transmitted or received should have 8 data bits
and no parity bit. The program adds 1 start bit and 1 stop bit automatically when transmitting.
4.2 Program Flow
The UART program consists of the following subroutines:
• Bit processing timer interrupt service routine (uart_isr)
• Transmit routine (trans_bit)
The Automatic baud rate detection routine must be called first after a system reset. This subroutine
will wait for a ASCII ‘8’ character to be downloaded from the serial device. Then this subroutine configures
Serial Port 1 as the FLAG IN and FLAG OUT pin for receiving and transmitting. Once the character is
received, the routine figures out the current baud rate setting of the serial device and pass it on to the initialization
routine.
The Initialization routine must be called after the automatic baud rate detection routine. This routine
reads the detected baud rate constant from the autobaud routine and sets the internal timer of the UART to
match the baud rate. Then this subroutine configures Serial Port 1 as the FLAG IN and FLAG OUT pin for
receiving and transmitting. The status flags of the UART are set or reset here to indicate that the UART is ready
for operation.
After the autobaud and initialization routines are called upon after system reset, the Bit processingtimer interrupt service routine is called. This happens every time the timer expires and issues an interrupt.
This routine will set or reset the FLAG OUT pin to transmit one bit at a time if there is a character to be sent
out. The routine then checks to see If there are bits to be received from the FLAG IN pin by polling the FLAG
EE-89Page 7
Technical Notes on using Analog Devices’ DSP components and development tools
IN pin continuously to look for the start bit (logic low). If the start bit is detected, the routine will shift in one bit
at a time and signal if a whole character has been received.
The Transmit routine is used to send a character transmit request to the UART. This routine copies the
character to be transmitted to the transmit buffer with the correct number of stop and start bits added. The
transmit routine then sets a flag to notify the UART that a character is waiting to be transmitted.
EE-89Page 8
Technical Notes on using Analog Devices’ DSP components and development tools
For the software UART to function properly, the program must know the baud rate setting of the serial
device that it is trying to communicate with. Instead of setting the baud manually, this autobaud feature of the
UART will automatically detect and match the current serial device’s baudrate.
The autobaud subroutine must be called after a system restart. The user should transmit an ‘8’ from the
serial terminal to the EZ Kit Lite board at restart. The character ‘8’ was chosen because
representation has 3 consecutive high bits with all other bits low. Autobauding works as follows:
1. The subroutine loads the timer with maximum value (0xFFFF).
2. The subroutine waits for a start bit (0) by polling the FLAG IN pin.
3. When a start bit is detected, the routine waits for the beginning of the three high bits in ‘8’’s ASCII
representation to arrive.
4. The timer counts down during the receiving period of the 3 high bits.
5. The number of cycles taken to receive those 3 bits is then compared to the number of cycles a known
baud rate took to receive 3 bits.
6. If a match is found, the autobaud sets the timer constant to operate the UART at the same baud rate.
The number of cycles needed to process 3 bits and the timer constant for common baud rates can be
found by using the following formula. Use the following formula to find the number of cycles needed for
processing 1/3 bit:
Number of Cycles Needed to process 1/3 bit = ( ( processor frequency / ( 3 * baud rate ) ) - 1 *
BAUD Rate
(bits/sec)
Cycles Needed
for 3 Bits
Cycles Needed
for 1/3 Bit
2400416614629
4800208262314
9600104041156
EE-89Page 9
Technical Notes on using Analog Devices’ DSP components and development tools
{*****************************************************
* Name: auto
* input: none
* output: none
*
* description: This function figures out the terminal’s
* baud rate by counting the cycle time
* to tx 3 bits. This function waits for
* the char '8' to be downloaded from the
* terminal and calculates the time constant.
* This time constant is compared to known
* constant of different baudrates.
* Once the baudrate is known, it returns
* a variable which is then used by UART to
* clock in or transmit chars.
*
* note: Should be called before initialize in
* the main program. ASCII for char '8'
* is: 00111000. LSB is rx first.
*
* #cycles/(1/3 bit) = (freq/(3*Baudrate)) - 1
*
* baudrate #cycles/3 bits #cycles/(1/3 bit)
* -----------------------------------------------------* 2400 41668 4630
* 4800 20834 2315
* 9600 10417 1157
* 19200 5208 579
********************************************************}
.module autobaud;
.include <system.k>;
.var baud_const;{ used in uart.dsp }
.global baud_const;
.entry auto; { used in main program }
auto:
{ set timer to count from 0xFFFF }
dis timer;
ax0 = 0xffff;
dm(TCOUNT) = ax0;
EE-89Page 11
Technical Notes on using Analog Devices’ DSP components and development tools
The initialization routine is called to prepare and set up the UART to transmit and receive a character.
First, this routine gets the timer constant and sets the timer to issue interrupts at 3 times the baud rate. This
provides sufficient clock resolution to handle the asynchronous data stream. For applications requiring greater
resolution, the interrupt rate may be changed to higher odd multiples of the baud rate.
The initialization routine next configures Serial Port 1 (SPORT1) as the FLAG IN and FLAG OUT
pins. This routine then sets the FLAG OUT pin high to indicate an idle line. Finally, all pending interrupts are
cleared, the timer is enabled, and it starts to count down.
4.5 Bit Processing Timer Interrupt Service Routine
Two interrupt service routine is the central routine of the UART program. This routine is executed
every time the timer counter expires and issues an interrupt. Since the timer is running at three times the baud
rate, it will be called three times for every bit transmitted or received. The interrupt service routine is divided
into two sections, the transmit section and the receive section.
The routine begins by switching to the secondary set of registers in order to preserve the register content
for the main program. Next, this routine checks the transmit flag to see if there is a transmit request. If there is
a character to be transmitted, the transmit section is executed; if not, the routine skips the transmit section and
jumps directly to the receive section.
Because the timer runs at three times the baud rate, a bit will be sent once every three timer interrupts
while in transmit mode. The transmit section must decide if a bit should be sent during the current interrupt. If a
bit is to be transmitted, the routine shifts the word in the transmit buffer out, LSB first. This bit will determine
whether the FLAG OUT pin is set high or low. The routine will then update all the necessary transmit flags and
then execute the receive section.
The receive section first checks to see if the stop bit of the last word have been received. If it has, the
routine waits for the stop bit period to pass and returns to the main routine. If the stop bit has not been
received, the receiver is either in the middle of receiving a word or waiting to receive a new word.
EE-89Page 14
Technical Notes on using Analog Devices’ DSP components and development tools
When the receiver is waiting for a new word, it samples the FLAG IN pin to check for a start bit. If
none is found, the routine returns to the main routine. If a start bit is detected, the routine sets the receive
counter to one more than the normal count. This is done so the UART can sample near the middle of each bit in
the data stream. When the receiver is in the middle of receiving a word, the routine will sample the FLAG IN
pin and shift in a bit once every three timer interrupts until there are no more bits left to be received. The
receiver will set the word ready flag and update the necessary flags to indicate a word has been received.
4.6 Transmit Routine
This routine is called in the main program to transmit a character using UART. It copies the word to be
transmitted from the AX1 register to the transmit buffer with stop and start bits added. The routine then sets the
transmit request flag to notify the UART that a character is waiting to be transmitted. If the UART is busy, this
routine will wait in a loop until the UART transmitter becomes available.
{-----transmit variables-----}
.var uart_tx_buffer; { bits are tx from this buffer }
.var tx_bits_left; { contains # of bits left to tx }
.var main_tx_buffer; { contains the word to be txed }
.var tx_counter; { uart txs when the count=0 }
.var tx_flag; { 1=transmit request, 0=no req }
{-----receive variables-----}
.var uart_rx_buffer; { bits are rx into this buffer }
.var main_rx_buffer; { contains the rx word }
.var rx_bits_left; { contains # of bits left to rx }
.var incomming; { 1=uart is in the middle of rx }
.var rx_counter; { uart clocks in a bit when = 0 }
.var rx_a_word; { signals main prog a word ready }
.var stop_bit;{ 1 = stop bit period reached }
.global main_rx_buffer;
.global rx_a_word;
{**********************************************************************
* Name: initialize
* input: non e
* output: none
*
* description: This function sets the timer to generate
* interrupts at three times the baud rate.
* It also configures Serial Port 1, (SPORT1)
* , as the FLAG IN and FLAG OUT pin s.
* It then sets flags that indicate the UART
* is ready to tx and rx. Finally the FLAG
* OUT pin is set and the timer is enabled.
*
* notes: This function should be called at the
* beginning of the main routine.
*************************************************************************}
initialize:
{ Initialize the timer to tick @ 3x Baudrate }
ax0 = dm(baud_const);{ set by autobaud }
dm(TCOUNT) = ax0;
dm(TPERIOD) = ax0;
EE-89Page 16
Technical Notes on using Analog Devices’ DSP components and development tools
* Name: uart_isr
* input: none
* output: none
*
* description: This ISR is called every time the timer
* expires and issues an interrupt. This
* routine will xmit one bit at a time using
* the flag out pin. If there is a word to be
EE-89Page 17
Technical Notes on using Analog Devices’ DSP components and development tools
* received, the routine will shift in bits by
* reading the flag in pin.
*
* note: Since the internal timer is running at 3x
* baud rate, bits are processed only once
* for every 3 timer interrupts.
***********************************************************}
uart_isr:
ena sec_reg; { save content of registers }
{ Something to Transmit? }
ax0 = dm(tx_flag); { Is there a tx request? }
none = pass ax0;
if eq jump receive; { if not goto receive, if yes..}
transmit:
{ Decrement the transmit counter }
ay0 = dm(tx_counter);
ar = ay0 - 1;
dm(tx_counter) = ar;
{ Send out a char. during this interrupt? }
if ne jump receive; { if not goto receive, if yes..}
{ Shift out tx buffer's LSB into SR0. Test it to }
{ set or reset the flag out pin }
sr1 = dm(uart_tx_buffer);
sr0 = 0;
sr = lshift sr1 by -1 (hi);
dm(uart_tx_buffer) = sr1;
ar = pass sr0;
if ge reset flag_out; { test the sign bit of SR0}
if lt set flag_out;
{ Reload the transmit counter }
ax0 = 3; { 3 interrupts later transmit again }
dm(tx_counter) = ax0;
{ Decrement the bits left to transmit counter }
ax0 = dm(tx_bits_left);
EE-89Page 18
Technical Notes on using Analog Devices’ DSP components and development tools
* Name: trans_char
* Input: ax1 <-- ASCII char to be transmitted
* output: none
*
* description: This function is called in the main routine
* to transmit a char using UART. It sets
* the transmit flag to notify the UART that a
* char is waiting to be transmitted. I t then
* copies the main transmit buffer to the UART
* tansmit buffer with stop and start bit added
***************************************************************************}
trans_char:
{ Is the transmitter busy? Wait if it is }
wait: ax0 = dm(tx_flag);
none = pass ax0;
if ne jump wait;
{ The number of bits will be defined in main routine }
ax0 = dm(num_tx_bits);
dm(tx_bits_left) = ax0;
{ copy the char. to the internal transmit buffer }
dm(main_tx_buffer) = ax1;
sr1 = ax0; { init SR1 to be 0 }
sr0 = b#1111111000000000; { adding stop bit }
ar = dm(main_tx_buffer);
sr = sr or lshift ar by 1 (lo); { adding start bit }
dm(uart_tx_buffer) = sr0;
{ set the transmit flag }
ax0 = 1;
dm(tx_flag) = ax0;
EE-89Page 21
Technical Notes on using Analog Devices’ DSP components and development tools
echo.dsp is an example of a program that uses the software UART routine to transmit and receive. This
example will show how to use the UART routine. The program will read in a character from a serial device and
echo it back.
For this example you will need a PC and the ADSP-2181 EZ Kit Lite board connected to one of the
comm. ports.
5.2 Program Files
The following files are needed to create the example program:
• echo.dspMain program that echoes characters back.
• uart.achUART system architecture file.
• make.batDOS batch file that assembles, links and creates a PROM file for the files
listed above.
The make.bat batch file should be used to create the executable and the PROM file for the example
program. The user should burn or download the PROM file to the EZ Kit Lite’s EPROM after the make.bat
file successfully creates the echo.exe and echo.bnm files.
5.3 The Main Routine
The main echo routine uses the software UART subroutine to receive and transmit character back to
the serial device. The main routine first uses the autobaud routine to automatically determine what the current
baud rate of the serial device is. Then the main routine calls the initialization routine to match the baud rate and
prepare the software UART for transmit and receive characters.
EE-89Page 23
Technical Notes on using Analog Devices’ DSP components and development tools
When the serial device’s baud rate is successfully detected by the autobaud routine, the main routine will
send a string of text to the terminal displaying the detected baud rate. The routine will then loop to wait for a
character available flag from the UART. If one is available, the main routine will place the character in the
transmit register (AX1) and call the transmit routine to send it back out.
Listings of all the program files and system files needed for the example program are included in this
document. Information on the EZ Kit Lite board and the ADSP-2181 can be found in the ADSP-2100 Family
EZ-Kit Lite Reference Manual.
{*****************************************************
* Name: echo
* Input: none
* Output: none
*
* Description: This program uses the UART driver and
* the autobaud detection function to echo
* back any char it receives. First, it
* varifies the functionality of the auto
* baud by sending a text string back
* to the terminal. After sending the
* text string, the program checks to see
* if a word is ready from the UART driver.
* If it is, the trans_char function is
* then used to send the char back to
* terminal.
*
* calls: initialize
* auto
* trans_char
******************************************************}
.module echoing;
.include <system.k>;
.entry start; { for the interrupt vector table }
.external initialize;
.external trans_char;
.external rx_a_word;
EE-89Page 24
Technical Notes on using Analog Devices’ DSP components and development tools