megaAVR® USART Configuration

Last modified by Microchip on 2023/11/10 11:09

Overview

In this section, we will cover the basic coding steps required to configure/use the USART module in a megaAVR® MCU, with a focus on the ATmega328PB device.

The USART module consists of three main sections, Clock Generator, Transmitter, and Receiver, as shown in the following diagram:

AVR USART Block Diagram

Key registers (highlighted in grey) include: 

  • Control-and-Status Registers (UCSRnA, UCSRnB, UCSRnC) shared by all three sections.
  • Data register UDRn shared by both Transmitter and Receiver sections. 
  • Baud rate control registers UBRRn[H:L] used by the Clock Generator.

The "n" in the register/bit name identifies the specific USART hardware instance (0, 1, 2) the register/bit is associated with. For example, UCSR0A refers to USART0 Control & Status Register A.

Back to top

Using the USART (Summary)

For basic polled operation, the following minimum steps need to be performed:

  1. Choose a baud rate and program the UBRRn[H:L] registers accordingly.
  2. Enable the USART serial transmit and receive sections.
  3. If transmitting, wait until the transmit shift register is empty (poll on UCSRnA.UDREn), then load your data byte into UDRn.
  4. If receiving, wait until the receiver data-received bit is set (poll on UCSRnA.RXCn), then read the data out of UDRn. Reading UDRn auto-clears the bit, and prepares the hardware to receive the next byte.

Back to top

Initialization

The USART has to be initialized before any communication can take place. The initialization process normally consists of:

  • Setting the baud rate,
  • Setting frame format and
  • Enabling the Transmitter or the Receiver depending on the usage.

Back to top

Setting the Baud Rate

Internal clock generation is used for the Asynchronous mode of operation. The Clock Generation logic generates the base clock for the Transmitter and Receiver (key registers and control bits are highlighted):

Setting the Baud Rate

Back to top

USART Mode Select (UMSELn)

The baud rate equation used by the module is set based on the operating mode. For asynchronous mode operation, the USART Mode Select bits in the USART Control and Status Register C (UCSRnC.UMSELn[1:0]) are used to select asynchronous operation (UMSEL[1:0] = 00) as shown:

USART Mode Select Bits

Back to top

Double-Speed Mode (U2Xn)

For asynchronous mode, the USART TX rate can be doubled by setting the U2Xn bit in the UCSRnA register (UCSRnA.U2Xn = 1).

With double-speed mode set, the Receiver will only use half the number of samples (reduced from 16 to 8) for data sampling and clock recovery, and therefore a more accurate baud rate setting and system clock are required when this mode is used.

Back to top

Baud Rate Register (UBRRn)

The USART Baud Rate Register (UBRRn) and the down-counter connected to it function as a programmable prescaler or baud rate generator. The down-counter, running at system clock (fosc), is loaded with the UBRRn value each time the counter has counted down to zero or when the UBRRnL Register is written. A clock is generated each time the counter reaches zero. This clock is the baud rate generator clock output (= fosc/(UBRRn+1)). The Transmitter divides the baud rate generator clock output by 2, 8, or 16 depending on the mode. The baud rate generator output is used directly by the Receiver’s clock and data recovery units. However, the recovery units use a state machine that uses 2, 8, or 16 states depending on the mode set by the state of the UMSEL, U2Xn, and DDR_XCK bits.

Table 24-1 contains equations for calculating the baud rate (in bits per second) and for calculating the UBRRn value for each mode of operation using an internally generated clock source.

USART Baud Equations

  • BAUD: Baud rate (in bits per second, bps)
  • fOSC : System oscillator clock frequency
  • UBRRn: Contents of the UBRRnH and UBRRnL Registers, (0-4095).

Tables are also provided in the device data sheet containing UBRRn values for common Baud rates, given several oscillator frequencies:

USART Common Ubrrn Values

For baud frequency calculations, it is generally accepted that error percentages of less than ± 2% are acceptable.

Back to top

Setting the Frame Format

USART Control and Status Register C (UCSRnC) is used to configure the UART communication frame format—parity, number of stop bits, and number of data bits. Settings for the typical “8N1” frame format are as follows:

  • UPM[1:0] = 00 for No Parity
  • USBS = 0 for 1 Stop Bit
  • UCSZ1[1:0] = 11 for 8 Bits

USART Frame Format

Back to top

Enabling the Transmitter

The USART Transmitter is enabled by setting the Transmit Enable (TXEN) bit in the UCSRnB register:

Enabling the Transmitter

When the Transmitter is enabled, the normal port operation of the TxDn pin is overridden by the USART and given the function as the Transmitter’s serial output.

The baud rate, mode of operation, and frame format must be set up once before doing any transmissions.

Back to top

Enabling the Receiver

The USART Receiver is enabled by writing the Receive Enable (RXEN) bit in the UCSRnB Register to ‘1':

Enabling the Receiver

When the Receiver is enabled, the normal port operation of the RxDn pin is overridden by the USART and given the function as the Receiver's serial input.

The baud rate, mode of operation, and frame format must be set up once before doing any transmissions.

Back to top

Code Example

The following USART initialization code example uses the setbaud utility library in AVR-LIBC. This library provides macros that use the c-preprocessor to calculate appropriate values for UBBRn.

Inputs

This header file requires that on-entry values are already defined for F_CPU and BAUD. In addition, the macro BAUD_TOL will define the baud rate tolerance (in percent) that is acceptable during the calculations. The value of BAUD_TOL will default to +/- 2%.

Outputs

Assuming that the requested BAUD is valid for the given F_CPU then the UBRR_VALUE macro is set to the required prescaler value. Two additional macros are provided for the low and high bytes of the prescaler, respectively; UBRRL_VALUE is set to the lower byte of the UBRR_VALUE, and UBRRH_VALUE is set to the upper byte. An additional macro, USE_2X, will be defined. Its value is set to 1 if the desired BAUD rate within the given tolerance could only be achieved by setting the U2Xn bit in the UART configuration. It will be defined as 0 if U2Xn is not needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define F_CPU 16000000UL             required for setbaud & other libraries
#define BAUD 38400UL                 desired baud
#define BAUD_TOL 2                   desired baud rate tolerance (+/- %)

#include <avr/io.h>
#include
<util/setbaud.h>

void USART0_Init(void){

     Set the BAUD rate

    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    #if USE_2X                        USE_2X defined by setbaud.h based on inputs
    UCSR0A |= (1 << U2X0);
    #else
    UCSR0A &= (1 << U2X0);
    #endif

     Set the Mode & Frame Parameters

    UCSR0C = 0x06;                    Asynchronous, 8-data, No parity, 1-stop

     Enable USART0 Transmitter and Receiver

    UCSR0B = (1 << TXEN0) | (1 << RXEN0);

}

The setbaud library generates warning messages during compilation if the input parameters generate a BAUD rate setting which will produce a baud rate outside of the desired BAUD_TOL.

Back to top

Data Communications

Transmit

Data transmission is initiated by loading the transmit buffer with the data to be transmitted. The CPU can load the transmit buffer by writing to the UDRn register. For polled operation, firmware should monitor the data-register-empty flag (UCSRnA.UDREn) before loading UDRn.

The buffered data in the transmit buffer will be moved to the Shift Register when the Shift Register is ready to send a new frame. The Shift Register is loaded with new data if it is in an  Idle state (no ongoing transmission) or immediately after the last stop bit of the previous frame is transmitted. When the Shift Register is loaded with new data, it will transfer one complete frame at the rate given by the Baud Register.

UDRn Register

The transmit complete interrupt flag (USCRnA.TXCn) is set and an optional TX interrupt may be generated (if enabled) when the entire frame in the shift register has been shifted out. The UCSRnA.TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location.

Back to top

Receive

The Receiver starts data reception when it detects a valid start bit. Each bit that follows the start bit will be sampled at the baud rate or XCKn clock, and shifted into the Receive Shift Register until the first stop bit of a frame is received. The receive buffer can then be read by reading the UDRn register. The complete reception of a byte can be checked by polling the RXCn bit in UCSRnA register.

The receive complete interrupt flag (RXCn) is set and an optional RX interrupt may be generated (if enabled) when the entire frame in the shift register has been copied to the UDRn register. This is a persistent interrupt, i.e., firmware must read the received data from UDRn in order to clear the RXCn Flag

Code Example

The following simple blocking APIs send and receive a byte of data via USART0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void USART0_Transmit(unsigned char data){

    Wait for empty transmit buffer
    while(!(UCSR0A & (1 << UDRE0)));

     Put data into buffer, sends the data
    UDR0 = data;

}

unsigned char USART0_Receive(void){

    Wait for data to be received
    while(!(UCSR0A & (1 << RXC0)));

     Get and return received data from buffer
    return UDR0;

}

Back to top

Learn More

Back to top