Universal Asynchronous Receiver/Transmitter (UART) On The LM3S8962
Universal Asynchronous Receiver/Transmitter (UART) On The LM3S8962
Universal Asynchronous Receiver/Transmitter (UART) On The LM3S8962
David DeLuca
11/08/2009
ECE 480 DT3
Keywords:
UART, Baud, Interrupt, FIFO, Transmitter, Receiver, Register
Abstract
In order for serial communication to take place in modern computers, peripheral devices
and microcontrollers, a Universal Asynchronous Receiver/Transmitter (UART) is utilized. Due
to its sequential processing of data, cost savings by avoiding using multiple lines for parallel
transmissions is evident. As a critical component in a communication process, UARTs can be
programmed for proper timing sequences and error checking through parity bits. This allows the
designer a certain amount of flexibility when programming register values.
Introduction
Although UARTs have been around since the 1970s, its importance has not diminished
over time. With speed and cost at the core of modern day communication, UART continues to
boast its usefulness with and without electrical wires, including optical fiber, infrared (IrDA) and
bluetooth signals. As the length of a cable extends, more cost in incurred. Sending data over
parallel lines involves using multiple wires for one transmission, which is particularly expensive
and most likely not a practical solution. However, by using a UART controller, data can be
translated between serial and parallel forms. The UART takes all the bytes of data and
sequentially transmits it one bit at a time. At the destination, an additional UART controller will
receive the individual bits and finally reassemble the transmission into its complete form. Due to
its success over the years, many modern microcontrollers such as the LM3S8962 by Texas
Instruments have multiple native UARTs on a board. The following pages will discuss proper
programming of registers, explanation of terms, and different methods of operation for this
microcontroller.
Objectives
Provide details on how the UART works and various applications of use
Baud-Rate
The SI unit Baud was named after Emile Baudot and is synonymous with pulses per
second or symbols per second. Baud rate is expressed as the number of times a signal can
change logical states per second, meaning the higher the baud rate the faster the communication
channel is. In order for proper communication between sender and receiver, the baud-rate should
be programmed at each location to the same value. This is easily achieved with modern UARTs
on microcontrollers due to Baud-rate divisors. In the LM328962, Baud-Rate generation is done
through a 22-bit number that serves as the divisor. 16 of the bits are an integer, and the last six
bits are for fractional adjustment. Having the six fractional bits allows for generation of all
standard baud rates. Knowledge of the entire 22 bit number will allow the Baud-Rate generator
to determine the bit period.
The baud-rate divisor can be defined by the following equation in the LM3S8962:
BRD = BRD_I + BRD_F = UARTSysClk / (16*Baud Rate)
Formula 1: Baud-Rate Divisor
where BRD_I is the 16-bit integer, BRD_F is the 6-bit fraction, and UARTSysClk is the system
clock connected to the UART. The system clock is divided by 16 to generate the transmit clock
which will serve as error detection during receive operations. Both BRD_I and BRD_F are
stored in the UART register UARTFBRD, while the baud-rate divisor is located in register
UARTIBRD. A list of all the UART registers in the LM3S8962 is located in the Appendix.
Data Transmission
All data received or transmitted must be temporarily stored so that only one bit at a time
is handled. To accommodate for this, the LM3S8962 utilizes two 16-byte First in First Out
(FIFO) buffers (typically a receiving FIFO may contain extra bits per character for status
information). Both FIFOs can be accessed via the UARTDR register. The transmit logic
performs all parallel-to-serial conversion on the data read in from the transmit FIFO.
Conversely, the receive logic performs all serial-to-parallel conversion on the received bit
stream. The control logic outputs the serial stream of bits beginning with a defined start bit
followed by the least significant bit (LSB) of the data stream, the parity bit (if error checking is
enabled) and finally stop bits. Figure 1 demonstrates this process and the typical number of bits
where FIrLPBaud16 is the internally generated baud clock. To operate in low-power IrDA
mode, the divisor should be in the range of: 1.42 MHz < FIrLPBaud16 < 2.12 MHz. Functioning
in this range results in a pulse width of 1.41 2.11 s which is three times the period of
FIrLPBaud16. Figure 2 illustrates the difference between data signals transmitted/received using
UART with and without IrDA data modulation.
Interrupts
Interrupts in a UART are very critical due to high probability of transmission errors in a
communication system. The LM3S8962s UARTs can generate the following interrupts:
Overrun Error
Break Error
Parity Error
Framing Error
Receive Timeout
Since the possibility of multiple interrupts occurring at one given time exists, all UART interrupt
events are connected to an OR gate so that only a single interrupt event is sent to the interrupt
controller at a time. The UART interrupt mask UARTIM defines all interrupt events that can
trigger a controller-level interrupt request. When an interrupt event is handled, the event can be
cleared by placing the correct bit in the UARTICR interrupt clear register.
Initialization/Configuration
In order to use the UARTs in the LM3S8962, the peripheral clock must be enabled by
either setting the UART0 or UART1 bits in the Run Mode Clock Gating Control Register 1
(RCGC1). After we have set the peripheral clock, the baud-rate divisor must be programmed
next. This is critical as both the UARTIBRD and UARTFBRD registers require initialization
prior to the UARTLCRH register. Using the baud-rate generation formula (Formula 1) with a
target baud-rate of 115,200, the baud-rate divisor (BRD) can be calculated to be approximately
10.8507. Using this value, we can then calculate value to be stored in the UARTFBRD register
as:
UARTFBRD[DIVFRAC] = integer(0.8507 * 64 + 0.5) = 54
Formula 3
where .8507 is the BRD_F and .5 is used to account for rounding error. Now that we have the
BRD values calculated, the UART configuration is completed in the following sequential order:
1. Disabling the UART
2. Write integer portion of BRD to UARTIBRD
3. Write fractional portion of BRD to UARTIFBRD
4. Write desired serial parameters to UARTLCRH (0x0000.0060 in above case)
5. Enabling UART by setting UARTEN bit in UARTCTL
Sample Code
The following fragment of code demonstrates basic communication between the
LM3S8962 and Texas Instruments MAX232 Driver/Receiver chip. In order for communication
to be read in or sent from a computer, a DB9 connector can be used to connect a serial cable to
the breadboard containing the MAX232 chip.
7
//***************************************************************************
**
//
// Send a string to the UART.
//
//***************************************************************************
**
void
UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
{
//
// Loop while there are more characters to send.
//
while(ulCount--)
{
//
// Write the next character to the UART.
//
UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);
}
}
//***************************************************************************
**
//
// This example demonstrates how to send a string of data to the UART.
//
//***************************************************************************
**
int
main(void)
{
//
// Set the clocking to run directly from the crystal.
//
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
//
// Initialize the OLED display and write status.
//
RIT128x96x4Init(1000000);
//
// Enable the peripherals used by this example.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable processor interrupts.
//
IntMasterEnable();
//
// Set GPIO A0 and A1 as UART pins.
//
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Configure the UART for 115,200, 8-N-1 operation.
//
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
//
// Enable the UART interrupt.
//
IntEnable(INT_UART0);
UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
//
// Prompt for text to be entered.
//
// UARTSend((unsigned char *)"T", 1);
while(1)
{
while(!UARTCharsAvail(UART0_BASE))
{
}
while(UARTCharsAvail(UART0_BASE))
{
char tmp = UARTCharGet(UART0_BASE);
RIT128x96x4StringDraw("M:",
12, 58, 15);
RIT128x96x4StringDraw(&tmp,
20, 58, 15);
UARTCharPut(UART0_BASE, 'h');
}
//
// Loop forever echoing data through the UART.
//
}
}
As you can see in the last set of while loops, you can continuously check to see if a character
becomes available on the FIFO. When a character is found and the UART detects transmission,
we can draw the data onto the LM3S8962s built-in OLED.
Appendix
Terminology
RC: Software can read this field. The bit or field is cleared by hardware after reading the
bit/field.
RO : Software can read field and write chip reset.
10
11
References
[1] Luminary Micro Technical Staff, LM3S8962 Evaluation Board, User's Manual, Texas
Instruments, 2009. Available at:
http://www.luminarymicro.com/index.php?option=com_remository&func=download
&id=523&chk=222579d07d3e13fde74ae411749ae30e&Itemid=591
[2] A. Liakot and S. Rosalina and A. Ishak, "Design of a micro-UART for SoC application
," Computer & Electrical Engineering, vol. 30, no. 4, p. 257-268, June 2004. [Abstract].
Available: ScienceDirect, http://www.sciencedirect.com/. [Accessed Nov 11, 2009].
[3] Texas Instruments Technical Staff, MAX232 Dual EIA-232 Drivers/Receivers, Texas
Instruments, 2009. Available at: http://focus.ti.com/lit/ds/symlink/max232.pdf
[4] Lammert Bies, Serial UART Information, Lammert Bies 2008. Available:
http://www.lammertbies.nl/comm/info/serial-uart.html
[5] PCCom Technical Staff, Baud Rate, PCCom. Available:
http://www.pccompci.com/Baud_Rate.html
12