The USART of the AVR
USART stands for Universal Synchronous Asynchronous Receiver/Transmitter. UART stands for Universal Asynchronous Receiver Transmitter. They are just a piece of hardware that converts parallel data into serial data. The difference between USART and UART are that UART supports only asynchronous mode, whereas USART supports both asynchronous and synchronous modes. In asynchronous transmission, start and stop bits are used to identify data bits, while in synchronous transmission, bits are synchronized with a clock pulse. Some of the features of AVR USART is given below.
- Full Duplex Operation (Independent Serial Receive and Transmit Registers)
- Asynchronous or Synchronous Operation
- Master or Slave Clocked Synchronous Operation
- High Resolution Baud Rate Generator
- Supports Serial Frames with 5, 6, 7, 8, or 9 data bits and 1 or 2 stop bits
- Odd or Even Parity Generation and Parity Check Supported by Hardware
- Data OverRun Detection
- Framing Error Detection
- Noise Filtering Includes False Start Bit Detection and Digital Low Pass Filter
- Three Separate Interrupts on TX Complete, TX Data Register Empty and RX Complete
- Multi-processor Communication Mode
- Double Speed Asynchronous Communication Mode
Before dig into technical details, there two more things you have to be familiar with.
- Baud rate - Baud rate referes to the number of symbols/characters transmitted per second.
- Asynchronous communication - Transmission of data, generally without the use of an external clock signal. In asynchronous transmission, data is sent one byte at a time and each byte is preceded by a start bit and stop bit.
To read more about this, please refer Wikipedia page Asynchronous Serial Communication.
Registers
-
UDR (USART I/O Data Register) - 16 bit
-
UCSRA (USART Control and Status Register A) - 8 bit
- Bit 7: RxC (USART Receive Complete Flag) - This flag bit is set by the CPU when there are unread data in the Receive buffer, and the bit is cleared by the CPU when the receive buffer is empty. This can also be used to generate a Receive Complete Interrupt
- Bit 6: TxC (USART Transmit Complete Flag) - This flag bit is set by the CPU when the entire frame in the Transmit Shift Register has been shifted out and there is no new data currently present in the transmit buffer (UDR). The TXC Flag bit is automatically cleared when a Transmit Complete Interrupt is executed.
- Bit 5 (UDRE – USART Data Register Empty) - If UDRE is one, the buffer is empty, and therefore ready to be received new data.
- Bit 4: FE (Frame Error) - This bit is set if the next character in the receive buffer had a Frame Error when received.
- Bit 3: DOR (Data Overrun Error) - This bit is set if a Data OverRun condition is detected. A Data OverRun occurs when the receive buffer is full (two characters), and a new start bit is detected.
- Bit 2: PE (Parity Error) - This bit is set if the next character in the receive buffer had a Parity Error when received and the parity checking was enabled at that point (UPM1 = 1).
- Bit 1: U2X (Double Transmission Speed) - This bit only has effect for the asynchronous operation. Write this bit to zero when using synchronous operation. Writing this bit to one will reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the transfer rate for asynchronous communication.
- Bit 0: MPCM (Multi-Processor Communication Mode) - This bit enables the Multi-processor Communication mode.
-
UCSRB (USART Control and Status Register B) - 8 bit
- Bit 7: RXCIE (RX Complete Interrupt Enable) - Writing this bit to one enables interrupt on the RXC Flag.
- Bit 6: TXCIE (TX Complete Interrupt Enable) - Writing this bit to one enables interrupt on the TXC Flag.
- Bit 5: UDRIE (USART Data Register Empty Interrupt Enable) - Writing this bit to one enables interrupt on the UDRE Flag (Data Register Empty Interrupt).
- Bit 4: RXEN (Receiver Enable) - Writing this bit to one enables the USART Receiver.
- Bit 3: TXEN (Transmitter Enable) - Writing this bit to one enables the USART Transmitter.
- Bit 2: UCSZ2 (Character Size) - The UCSZ2 bits combined with the UCSZ1:0 bits in UCSRC register sets the number of data bits (Character Size) in a frame the Receiver and Transmitter use.
- Bit 1: RXB8 (Receive Data Bit 8) - RXB8 is the ninth data bit of the received character when operating with serial frames with nine data bits. It must be read before reading the low bits from UDR.
- Bit 0: TXB8 (Transmit Data Bit 8) - TXB8 is the ninth data bit in the character to be transmitted when operating with serial frames with nine data bits. It must be written before writing the low bits to UDR.
-
UCSRC (USART Control and Status Register C) - 8 bit
- Bit 7: URSEL (USART Register Select) - This bit selects between accessing the UCSRC or the UBRRH Register.
-
Bit 6: UMSEL (USART Mode Select) - This bit selects between Asynchronous and Synchronous mode of operation.
UMSEL Mode 0 Asynchronous operation 1 Synchronous operation
-
Bit 5:4: UPM1:0 (Parity Mode) - This bit helps you enable/disable/choose the type of parity.
UPM1 UPM0 Parity mode 0 0 Disabled 0 1 Reserved 1 0 Enabled, Even parity 1 1 Enabled, Odd parity
-
Bit 3: USBS (Stop Bit Select) - This bit helps you choose the number of stop bits for your frame.
USBS Stop bit(s) 0 1 bit 1 2 bits
-
Bit 2:1: UCSZ1:0 (Character Size) - These two bits in combination with the UCSZ2 bit in UCSRB register
helps choosing the number of data bits in your frame.
UCSZ2 UCSZ1 UCSZ0 Character size 0 0 0 5 bit 0 0 1 6 bit 0 1 0 7 bit 0 1 1 8 bit 1 0 0 Reserved 1 0 1 Reserved 1 1 0 Reserved 1 1 1 9 bit
-
Bit 0: UCPOL (Clock Polarity) - This bit is used for Synchronous mode only.
UCPOL Transmitted Data Changed
(Output of TxD pin)Received Data Changed
(Output of RxD pin)0 Rising XCK Edge Falling XCK Edge 1 Falling XCK Edge Rising XCK Edge
-
UBRR (USART Baud Rate Register) - 12 bit
The USART Transmit Data Buffer Register and USART Receive Data Buffer Registers share the same I/O address referred to as USART Data Register or UDR. The Transmit Data Buffer Register (TXB) will be the destination for data written to the UDR Register location. Reading the UDR Register location will return the contents of the Receive Data Buffer Register (RXB). The transmit buffer can only be written when the UDRE Flag in the UCSRA Register is set. When data is written to the transmit buffer, and the Transmitter is enabled, the Transmitter will load the data into the Transmit Shift Register when the Shift Register is empty. Then the data will be serially transmitted on the TxD pin.
This is a 12 bit register which contains the USART baud rate. The UBRRH contains the four most significant bits, and the UBRRL contains the eight least significant bits of the USART baud rate. USART baud rate value for UBRR is calculated using the equation ((F_CPU / (BAUD_RATE * 16)) - 1).
Baud Rate [bps] | fosc = 1.0000MHz | |||
---|---|---|---|---|
U2X = 0 | U2X = 1 | |||
UBRR | Error | UBRR | Error | |
2400 | 25 | 0.2% | 51 | 0.2% |
4800 | 12 | 0.2% | 25 | 0.2% |
9600 | 6 | -7.0% | 12 | 0.2% |
14.4k | 3 | 8.5% | 8 | -3.5% |
19.2k | 2 | 8.5% | 6 | -7.0% |
Sample Code
-
Without Interrupts
Following example shows how received data is echoed back to the sender.
#include <avr/io.h> // function to initialize UART communication void uart_init (){ UBRRH |= (12 >> 8); // set UBBR value for 9600 baud rate UBRRL |= 12; UCSRB |= (1 << TXEN) | (1 << RXEN); // enable receiver and transmitter UCSRC &= ~(1 << UMSEL); // enable asynchronous mode UCSRC|= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 8 bit data format UCSRA = 1 << U2X; // double speed mode } // function to receive character char uart_receivec () { while(!(UCSRA & (1 << RXC))); // wait while data is being received return UDR; // return 8 bit data } // function to transmit character void uart_transmitc (char c) { while (!(UCSRA & (1 << UDRE))); // wait while register is free UDR = c; // load data in the register } int main(void) { uart_init(); // initialize UART device while (1) { char c = uart_receivec(); // read data from UDR uart_transmitc(c); // echo back the read data } }
With Interrupts
To use USART interrupt feature, you have to complete following steps.
- Enable USART receive complete interrupts by writing 1 to RXCIE bit of UCSRB.
- Implement ISR for USART_RXC vector.
- Enable global interrupts.
#include <avr/io.h> #include <avr/interrupt.h> ISR(USART_RXC_vect){ char c = UDR; // read received byte UDR = c; // echo back received byte } // function to initialize UART communication void uart_init (){ UBRRH |= (12 >> 8); // set UBBR value for 9600 baud rate UBRRL |= 12; UCSRB |= (1 << TXEN) | (1 << RXEN); // enable receiver and transmitter UCSRC &= ~(1 << UMSEL); // enable asynchronous mode UCSRC|= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 8 bit data format UCSRA = 1 << U2X; // double speed mode UCSRB |= (1 << RXCIE); // enable receive complete interrupt } int main(void) { uart_init(); // initialize UART device sei(); // enable global interrupts while (1); // wait forever }
Comments
Post a Comment