UART (Universal Asynchronous Receiver-Transmitter)


The objective of this lesson is to understand UART, and use two boards and setup UART communication between them.



Figure 1. UART connection between two devices.

For Universal Asynchronous Receiver Transmitter. There is one wire for transmitting data (TX), and one wire to receive data (RX).


A common parameter is the baud rate known as "bps" which stands for bits per second. If a transmitter is configured with 9600bps, then the receiver must be listening on the other end at the same speed.

UART Frame

UART is a serial communication, so bits must travel on a single wire. If you wish to send a 8-bit byte (uint8_t) over UART, the byte is enclosed within a start and a stop bit. To send a byte, it would require 2-bits of overhead; this 10-bit of information is called a UART frame. Let's take a look at how the character 'A' is sent over UART. In ASCII table, the character 'A' has the value of 65, which in binary is: 0100_0001. If you inform your UART hardware that you wish to send this data at 9600bps, here is how the frame would appear on an oscilloscope :


Figure 2. UART Frame sending letter 'A' 

UART Ports

A micrcontroller can have multiple UARTs. Typically, the first uart port, sometimes denoted as UART0, is interfaced to with a USB to serial port converter which allows users to communicate between the computer and microcontroller. This port can also be used to program your microcontroller.


  • Hardware complexity is low.
  • No clock signal needed
  • Has a parity bit to allow for error checking
  • As this is one to one connection between two devices, software addressing is not required.


  • The size of the data frame is limited to a maximum of 8 bits
  • Doesn’t support multiple slave or multiple master systems
  • The baud rates of each UART must be within 10% (or lower, depending on device tolerance) of each other

Hardware Design


Figure 3. Simplified UART peripheral design for the STM32F429. SCLK is used for USART.

WARNING: The above is missing a common ground connection

Software Driver

The UART chapter on LPC17xx has a really good summary page on how to write a UART driver. 

Read the register description of each UART register to understand how to write a driver. 

Memory Shadowing in UART driver


Figure 4. Memory Shadowing using DLAB Bit Register

In figure 4, you will see that registers RBR/THR and DLM have the same address 0x4000C000. These registers are shadowed using the DLAB control bit. Setting DLAB bit to 1 allows the user to manipulate DLL and DLM, and clearing DLAB to 0 will allow you to manipulate the THR and RBR registers.

Control Space Divergence (CSD) in UART driver

In figure 4, you will see that register RBR and THR have the same address 0x4000C000. But also notice that access to each respective register is only from read or write operations. For example, if you read from memory location 0x4000C000, you will get the information from receive buffer and if you write to memory location 0x4000C000, you will write to a separate register which the transmit holding register. We call this Control Space Diverence since access of two separate registers or devices is done on a single address using the read/write control signal is used to multiplex between them. That address is considered to be Control Space Diverent. Typically, the control space aligns with its respective memory or io space.

Note that Control Space Divergence does not have a name outside of this course. It is Khalil Estell's phrase for this phenomenon. (Its my word... mine!)

BAUD Rate Formula

Figure 5. Baud rate formula  

To set the baud rate you will need to manipulate the DLM and DLL registers. Notice the 256*UnDLM in the equation. That is merely another way to write the following (DLM << 8). Shifting a number is akin to multiplying it by 2 to the power of the number of shifts. DLM and DLL are the lower and higher 8-bits of a 16 bit number that divides the UART baudrate clock. DivAddVal and MulVal are used to fine tune the BAUD rate, but for this class, you can simple get close enough and ignore this value. Take these into consideration when you need an extremely close baudrate.

Advanced Design

If you used 9600bps, and sent 1000 characters, your processor would basically enter a "busy-wait" loop and spend 1040ms to send 1000 bytes of data. You can enhance this behavior by allowing your uart send function to enter data to a queue, and return immediately, and you can use the THRE or "Transmitter Holding Register Empty" interrupt indicator to remove your busy-wait loop while you wait for a character to be sent.

Back to top