How does UART work under the hood?

This is a short summary about how UART works as the serial terminal server project focuses on UART devices. First of all, UART means Universal Asynchronous Receiver Transmitter. This tells us that receiving and transmitting data all happens without a clock.

The protocol

When the UART is idle the output is HIGH. So when there is no data transmitted you will always read HIGH from the UART pins. Then, when a signal is transmitted, the pin is pulled down to LOW to indicate that data is transmitted. This is our start bit. Then we can transmit 8 data bits followed by a stop bit. Its value is HIGH. In total, there are 10bits which are sent in one package. Also note that transmitted values are passed less significant bit first.

In order to read the transmitted data you need to know the baud rate as UART is baud rate based. Transmitter and receiver use the baud rate for synchronization: Having a baud rate of 9600 corresponds to 9600 bits per second. As one package consists of 10 bits we thus receive 960 data bytes per second (or 960 packages per second). For one message, we thus have 1042µs. If we divide this number by 10, we know that one bit takes 104.2µs This timing can now be used to decode each message transmitted via UART.

Let’s look at an example: With a baud rate of 115200 we have 1/115200 = 8.68µs per bit. If we transfer the number 0x03 which is 0b00000011 in binary we get the following time chart:


         ^
         |
         |
.........X  XXXXXXX                 XXXX......
   HIGH  X  X     X                 X
         X  X     X                 X
         X  X     X                 X
         X  X     X                 X
         X  X     X                 X
         X  X     X                 X
   LOW   X  X     X                 X
         XXXX     XXXXXXXXXXXXXXXXXXX
         |
         +--|--|--|--|--|--|--|--|--|--|------>
*idle* start 1  1  0  0  0  0  0  0  end *idle*
       bit                           bit

In reality

When it comes to communication between two micro controllers you have also pay attention to exact timing. If data transmitted is off too much from the specified baud rate you won’t be able to read the message. If you have a 2MHz oscillator (FOSC) and transmit messages using high speed you surely have already seen the formula

FOSC / (16*(SPBRG + 1))

Here, SPBRG is a value saved in the corresponding register which ultimately determines which baud rate is used. With SPBRG=51in the current example we get a baud rate of 9615.38 out of the formula above. So our controller is off by 15.38 bits per second, the amount of error is 0.16%. Of course, you want this error to be as small as possible.

Error detection

If you like to have a parity bit you can reduce the 8 data bits to 7 data bits and use the MSB as parity bit. That way, you can notice one bit errors.

After all, UART is a technology which is existing now for a long time. You won’t get a very large transfer rate but there are still many devices which use this protocol as it is duplex, asynchronous and easy to integrate.

How does UART work under the hood?