In this section, we will cover basic coding steps required to configure/use the USART module in a megaAVR® MCU, with a focus on the ATmega328PB device.
Overview
The USART module consists of three main sections as shown in the following diagram: Clock Generator, Transmitter, and Receiver.
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.
"n" in the register/bit name identifies the specific USART hardware instance (0, 1, 2) the register/bit is associated to. For example UCSR0A refers to USART0 Control & Status Register A
Using the USART (Summary)
For basic polled operation, the following minimum steps need to be performed:
- Choose a baud rate and program the UBRRn[H:L] registers accordingly.
- Enable the USART serial transmit and receive sections.
- If transmitting, wait until the transmit shift register is empty (poll on UCSRnA.UDREn), then load your data byte into UDRn.
- 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.
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.
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):
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:
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.
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 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 mode set by the state of the UMSEL, U2Xn and DDR_XCK bits.
The table below 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.
- BAUD: Baud rate (in bits per second, bps)
- fOSC : System oscillator clock frequency
- UBRRn: Contents of the UBRRnH and UBRRnL Registers, (0-4095).
The AVR-LIBC Setbaud library contains useful macros for calculating the correct values to write to UBRRnH and UBRRnL registers. See initialization code example below.
Tables are also provided in the device data sheet containing UBRRn values for common Baud rates, given several oscillator frequencies:
For baud frequency calculations, it is generally accepted that error percentages of less than ± 2% are acceptable.
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
Enabling the Transmitter
The USART Transmitter is enabled by setting the Transmit Enable (TXEN) bit in the UCSRnB Register:
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.
Enabling the Receiver
The USART Receiver is enabled by writing the Receive Enable (RXEN) bit in the UCSRnB Register to ‘1':
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.
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 macro UBRR_VALUE 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 to 0 if U2Xn is not needed.
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.
Data Communications
Transmit
A 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 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.
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.
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.
Learn More
Table of Contents
|