Wednesday, June 10, 2015

AVR serial communication

Overview:
The Universal Synchronous and Asynchronous serial Receiver and Transmitter (USART) is a highly-flexible serial communication device. In this tutorial we will see Serial communication in AVR microcontroller. It is also called USART (Universal Synchronous/Asynchronous Receiver/Transmitter) Serial communication is widely used for interfacing of GSM modem, GPS, and communicating between PC and microcontroller. Lets Start with basics of serial communication present in AVR microcontroller it is also known as USART.

You get answers to these questions :
1. How to set BAUD rate ?
2. How to send single byte serially ?
3. How to send string type data ?
4. How to send integer data ? (integer to ASCII conversion) useful for ADC/Measurement
5. How to put line break ?

Features of USART present in AVR microcontroller:
• 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 Databits 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

Any serial communication requires to set the baud rate:
Lets see how we can calculate baud rate in AVR microcontroler

The Baud Rate Generator:
     The USART Baud Rate Register (UBRR) 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 UBRR value each time the counter has counted down to zero or when the UBRRL Register is written. A clock is generated each time the counter reaches zero. This clock is the baud rate generator clock output (= fosc/(UBRR+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, U2X and DDR_XCK bits.


ATmega8 BAUD rate calcations

Double Speed Operation (U2X): 
    The transfer rate can be doubled by setting the U2X bit in UCSRA.
1=Double baud rate
0=Normal baud rate

USART 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. For interrupt driven USART operation, the Global Interrupt Flag should be cleared (and interrupts globally disabled) when doing the initialization.
Before doing a re-initialization with changed baud rate or frame format, be sure that there are no ongoing transmissions during the period the registers are changed.

C Code Example For Serial Initialization:

#define FOSC 1843200// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
void main( void )
{
   USART_Init (MYUBRR);
}
void USART_Init( unsigned int ubrr)
{
    /* Set baud rate */
     UBRRH = (unsigned char)(ubrr>>8);
     UBRRL = (unsigned char)ubrr;
    /* Enable receiver and transmitter */
     UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data, 2stop bit */
     UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}


Data Transmission – The USART Transmitter
The USART Transmitter is enabled by setting the Transmit Enable (TXEN) bit in the UCSRB
Register. When the Transmitter is enabled, the normal port operation of the TxD pin is overridden by the USART and given the function as the Transmitter’s serial output.

C Code Example for Serial Transmission: 

void USART_Transmit( unsigned char data )
{
   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1<<UDRE)) );
  /* Put data into buffer, sends the data */
   UDR = data;
}


Data Reception – The USART Receiver:
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 once before any serial reception can be done.
C Code Example for serial Reception:
unsigned char USART_Receive( void )
{
   /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) );
   /* Get and return received data from buffer */
   return UDR;
}
Lets Make it Practical:
We are going to read serial data and display it on LEDs, And we are transmitting "Testing 123..." Continuously.

Sample C Code:

#include <avr/io.h>

#define FOSC 8000000// 8Mhz Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

void USART_Transmit( unsigned char data );
void USART_Init( unsigned int ubrr);
unsigned char USART_Receive( void );
void SendString(char mydata[20]);
/*******************************************************/
void main( void )
{
   char mychar[5];       //variable to hold ASCII values
   int value;
   DDRB =0xFF;           //Set PORT B direction output
   USART_Init (MYUBRR);

   USART_Transmit('A');  //This is single byte transmission

   SendString(" Testing 123..."); //Sends string of data serially useful for GSM Modem
   
   USART_Transmit(13); //Line break
  

   value=123;       //Sending of integer

//What is sprintf and %04d? 
//sprintf is string conversion function, used for integer to ASCII conversion
//zero indicates zero padding, 
//4 indicates make it 4 digit fixed width,
//d indicates its an integer


   sprintf(mychar,"%04d",value);  //This will convert integer into ASCII array
   SendString(" MyValue:");
   SendString(mychar);            //Send it
   
   USART_Transmit(13); //Line break

   SendString(" What if I send Value Directly?: ");  //This will show a garbage value 
   USART_Transmit(value);                            //or ASCII equivalent of 123

   USART_Transmit(13); //Line break   
    
   while(1)             //Get serial Data and send it to PORTB
   {
      PORTB=USART_Receive();
   }
}

/*******************************************************/
void USART_Init( unsigned int ubrr)
{
    /* Set baud rate */
     UBRRH = (unsigned char)(ubrr>>8);
     UBRRL = (unsigned char)ubrr;
    /* Enable receiver and transmitter */
     UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data, 2stop bit */
     UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

/*******************************************************/
void USART_Transmit( unsigned char data )
{
   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1<<UDRE)) );
  /* Put data into buffer, sends the data */
   UDR = data;
}
/*******************************************************/
unsigned char USART_Receive( void )
{
   /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) );
   /* Get and return received data from buffer */
   return UDR;
}
/*******************************************************/
void SendString(char mydata[20])
{
  int i;
   for(i=0;i<strlen(mydata);i++)
   {
     USART_Transmit(mydata[i]);
   }
}
/*******************************************************/


Circuit and Testing Results: 
1. Set Oscillator frequency to 8MHz internal oscillator


ATmega8 Serial Communication circuit diagram

1. How to send single byte serially ?
USART_Transmit('A');  //This is single byte transmission
USART_Transmit(0x31);  //This is single hex byte transmission
USART_Transmit(64);  //This is single decimal byte transmission

2. How to send string type data ?
void SendString(char mydata[20])
{
  int i;
//strlen function allows us to get the length of string
for(i=0;i<strlen(mydata);i++) { USART_Transmit(mydata[i]); } }

3. How to send integer data ? (integer to ASCII conversion) useful for ADC/Measurement
      sprintf(mychar,"%04d",value); //This will convert integer into ASCII array
   SendString(" Voltage:");
   SendString(mychar);            //Send it
4. How to put line break ?
   USART_Transmit(13); //Line break  

We done it, put your questions in comments, share like us on facebook, Google+

No comments:

Post a Comment