|
The Universal Synchronous and Asynchronous serial Receiver and Transmitter (USAR) is powerful and useful interface in many projects. It is usually used for code debugging and other user interaction while sending and receiving data form PC. Lets analyse how USART works on Atmega8. The main features of Atmega8 USART are: Full Duplex Operation with Independent Serial Receive and Transmit Registers); Asynchronous or Synchronous Operation; Master or Slave Clocked Synchronous Operation; High Resolution Baud Rate Generator; Data OverRun Detection; Framing Error Detection; Supports Serial Frames with 5, 6, 7, 8, or 9 Databits and 1 or 2 Stop Bits; Odd or Even Parity Generation and Parity Check Supported by Hardware; Multi-processor Communication Mode; Double Speed Asynchronous Communication Mode; 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; As USART is pretty complex peripheral I will just go through it. Detailed information may be found on data-sheets! USART is separated in three modules: Clock generator, Transmitter and Receiver. 
USART Clock generator Depending on data transfer mode there can be four different clock generation modes: Most commons asynchronous internal clock generation. There Baud Rate Register (UBRR) is used where is value stored for down counter. Each time the down-counter value reaches zero a clock is generated. You can calculate what UBRR value you need to write depending on desired baudrate and MCU clock speed by formula: BAUD= fck / (16(UBRR+1)). Using the value above (8 MHz and 9600 baud) we get the value of 51.08333333 for UBRR. So it's 51. The actual baud rate is 9615 baud, dividing this by 9600 gives 1.0016 and therefore an error of 0.16%. This will work, but it's not perfect. That's why you can you usually has to use crystals as 7.3728 MHz: Using that one for 9600 baud gives UBRR = 47 and no error. Tables with various clock/baud combinations you will find in the AVR datasheets. Synchronous mode and external clocking is don via XCK pin (refer to datasheet). USART Transmission USART transmitter is enabled by setting TXEN bit in UCSRB register. Normal port operations is overridden by USART (XCK pin in synchronous operations will be overridden too). Simple transmission is very simple operation: void USART_SendByte(uint8_t Data) { // Wait if a byte is being transmitted while((UCSRA&(1<<UDRE)) == 0); // Transmit data UDR = Data; } USART Reception The USART Receiver is enabled by writing the Receive Enable (RXEN) bit in the UCSRB Register to one. When the Receiver is enabled, the normal pin operation of the RxD 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 before any transfer operations. uint8_t USART_vReceiveByte() { // Wait until a byte has been received while((UCSRA&(1<<RXC)) == 0) ; // Return received data return UDR; } Data frame of USART usually starts with START bit, then follows bait (D to D7) then follows STOP bit. Between byte and stop bit there may be CB bit. The whole frame is 10 or 11 bit length:  In asynchronous transfer operation each bit is synchronized and recovered using following model: sampling is 16 times baud rate in normal mode. When clock recovery logic detects a high to low transition (start bit), sequence is initiated and in normal mode logic uses 8,9,10 samples to validate reception of start bit and further bits:  There is a lot material to talk about USART and its modes. Bat what is written in datasheet isn't necessary to repeat. We better concentrate to practical approach. And at the end one example of using USART in normal mode: #include <stdint.h> #include <avr/io.h> // Define baud rate #define USART_BAUD 115200ul #define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1) void USART_vInit(void) { // Set baud rate UBRRH = (uint8_t)(USART_UBBR_VALUE>>8); UBRRL = (uint8_t)USART_UBBR_VALUE; // Set frame format to 8 data bits, no parity, 1 stop bit UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0); // Enable receiver and transmitter UCSRB = (1<<RXEN)|(1<<TXEN); } void USART_vSendByte(uint8_t u8Data) { // Wait if a byte is being transmitted while((UCSRA&(1<<UDRE)) == 0); // Transmit data UDR = u8Data; } uint8_t USART_vReceiveByte() { // Wait until a byte has been received while((UCSRA&(1<<RXC)) == 0); // Return received data return UDR; } int main(void) { uint8_t u8Data; // Initialise USART USART_vInit(); // Send string USART_vSendByte('A'); // Repeat indefinitely for(;;) { // Echo received characters u8Data = USART_vReceiveByte(); USART_vSendByte(u8Data); } }
Related Items:
|