Implementing UART Using AVR

UART

Summary

UART is one of the most fundamental types of communication protocol. It transmits and receive the data digitally bit by bit. Let's have a in-depth knowledge to discover more about UART

What is Communication Protocol

The communication protocol is a set of rules which has the main purpose to exchange digital messages between devices. These protocols have certain syntax and they ensure detection of error if any and its correction, signal transmission and authentication.

There are two types of communication protocol:

  1. Inter System Protocol
  2. Intra System Protocol

UART is a type of Inter System protocol and is mainly used for communication between two different devices.

Introduction to UART

UART stands for Universal Asynchronous Receive Transmit. It is one of the most fundamental types of communication protocol. Both the devices are connected with two wires, one is used for transmission and the other is used for receiving. In UART, the data is transferred digitally bit by bit. It is a half-duplex protocol which means either transferring or receiving will occur at a time.

Transmitting and Receiving

In the device which is transmitting, data is taken in the form of bytes and each byte is transmitted bit by bit sequentially. In the receiving end, bits received are assembled in the form of bytes. An algorithm is used at both ends to perform this task

Structure

  • A clock generator for setting bit rate.
  • Input and output shift registers.
  • Transmission and receiving lines.
  • Read and write algorithms.

How do two devices communicate?

Two UART’s are directly connected via two cables. On the transmitting end, the data in byte form is transmitted bit by bit and at the receiving end, it is again converted into a byte. The transmitting bit first sends the start bit so that the receiving end starts reading and after the data is transmitted, a stop bit is transferred so that the receiving end stops reading.

A specific frequency is set for defining the no. of bits being transferred per second. This is known as the baud rate. For a successful data transmission, the baud rate must be the same at both ends.

Explore Arduino Collection

Explaining the Data Packets in UART

The data transmitted by the UART is organized into packets with one start bit, 5 to 9 data bits (with the lowest bit first and the highest bit last), an optional parity bit finally followed by 1 or 2 stop bits.

Start Bit

The start bit is marked by a low voltage in the normally high voltage transmitting line for one clock cycle. This tells the receiving UART to start reading the bits at an accurate baud rate, thus marking the start of a data packet.

Parity Bit

Parity Bit is used to inform the receiving UART for changes caused to the data by electromagnetism, different baud rates, or by the long-distance transmission of data. If the parity bit is set to even it ensures that the number of 1’s in the data including parity is even, that is if there are even numbers of 1’s in the data, the parity bit will be 0 and if there are odd numbers of 1’s in the data, the parity bit will be 1. Similarly, if it is set to odd parity it will ensure that the number of 1’s in the data is odd including parity. If the parity bit matches the data then we can be sure that the data was free of error.

Stop Bit

This marks the end of data by driving the transmission line to a high voltage for one or two clock cycles.

uart protocol

Baud Rate 

The time interval between two bits is known as baud rate, which is calculated as bits per second. Both the devices must have the same baud rate so that the receiver can interpret the data at the right intervals of time as sent by the transmitter. Higher baud rates have higher chances of corruption of data, thus lower baud rates are used to decrease the chances of error in the transmitted data

How the data packets are transmitted

UART receives data in the form of a data bus from devices such as microcontrollers, memory or CPU. A data package is made by adding a start bit, a parity bit (optional) and a stop bit to the data. The data packets are then transmitted using serial communication as follows:

  • At the start, the receiver device is informed to start logging in data by sending the start bit first which as explained above is active low.
  • After the start bit, the data ( 5 to 9 bit) is sent through the wire bit by bit from lowest bit first to a highest bit last whose time is dependent on their baud rate
  • Parity bit, which is optional, is sent after the data byte. It helps to check the corruption of the received data
  • According to its working described above the parity bit is encoded in the data packet and transmitted
  • At the receiver side, the parity bit is used to confirm the credibility of the data received by counting the number of high bits and matching it with the parity. If the data is corrupted it is discarded and the error counter is incremented. If the error counter exceeds a certain value it is advised to reduce the baud rate which sacrifices speed for quality
  • The parity bit is followed by one or two stop bits. 2 stop bits are generally used to give enough time in between consecutive data packets and which makes the transmission a bit slower and decreases the error rate
uart protocol

Errors in UART

Overrun Error

Such an error is caused when the receiver UART is unable to process the incoming data before the next data. For the buffer to not be filled the CPU or controller must service the UART quickly. Overrun error is caused by the filling of the buffer which in turn leads to loss of incoming data.

Parity Error

This error is caused when the parity bit does not match the data. This error can only take place if a parity bit is used in the data packet.

Framing Error

In the absence of a stop bit at the expected interval, a UART can trigger this error. A framing error will be signaled if the data packet does not arrive at the expected state and expected time. A break condition between the data packet can also cause this error.

Explore Audio Components

Overrun Error

In asynchronous mode, an empty buffer is treated as a sign that no data has remained transmitted. Thus, an empty buffer while transferring the data will give an underrun error.

Pros of UART

  • Less power consumption
  • Lower hardware complexity
  • The clock is not required
  • Less power consumption
  • No need for software addressing
  • It has a parity bit to check the quality

Cons of UART

  • Has a limited data frame size
  • Speed of data transfer is less
  • The baud rates of both devices must be in a 10% range

read more : Implementation of ADC in AVR

Sample of an AVR code in which a microcontroller takes in analog input and sends it to another microcontroller to make a PWM

Transmitter

#ifndef F_CPU

#define F_CPU 1000000UL

#endif

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

//These are the basic functions we will be using throughout the programming

#define SET_BIT(byte, bit) (byte |= (1 << bit))

#define CLEAR_BIT(byte, bit) (byte &= ~(1 << bit))

#define TOGGLE_BIT(byte, bit) (byte ^= (1 << bit))

#define BIT_IS_SET(byte, bit) (byte & (1 << bit))

#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))

unsigned int Val;

int main(void){

        //Enable a pre-scalar (needed cause ADC gives max output for 50kHz to 200kHz whereas the in made clock works at 1MHz)(for 10bit input or more)

        SET_BIT(ADCSRA,ADPS2);

        //8-bit or 10-bit results || here we have shifted the result to left thus only requiring us to read ADCH for 8-bit

        SET_BIT(ADMUX,ADLAR);

        //The reference of the highest voltage

        SET_BIT(ADMUX,REFS0);

        //Turn on the ADC (analog to DC converter) feature

        SET_BIT(ADCSRA,ADEN);

        int UBRR_Value = 25;//for 2400 baud rate

        UBRR0H = (unsigned char) (UBRR_Value >> 8);

        UBRR0L = (unsigned char) UBRR_Value;

        UCSR0B = (1 << TXEN0);                        //Set the TX pin for sending data using UART

        UCSR0C = (1 << USBS0) | (3 << UCSZ00);                //Set 2 stop bits || Alternative code for 8-bit length

        while (1)

        {        

                ADCSRA |= (1 << ADSC);                        // start ADC conversion

                while(BIT_IS_SET(ADCSRA, ADSC)) {}        // wait here until the chip clears the ADSC bit for us, which means the ADC is complete

                Val = (ADCH);                                //Gets the value from ADC

                while(!(UCSR0A & (1 << UDRE0)));                // To check if TX is free for more data

                UDR0 = Val;                                //Send the value through to another microcontroller

                

        }

        return(0);

}

 

Receiver

#ifndef F_CPU

#define F_CPU 1000000UL

#endif

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

//These are the basic functions we will be using throughout the programming

#define SET_BIT(byte, bit) (byte |= (1 << bit))

#define CLEAR_BIT(byte, bit) (byte &= ~(1 << bit))

#define TOGGLE_BIT(byte, bit) (byte ^= (1 << bit))

#define BIT_IS_SET(byte, bit) (byte & (1 << bit))

#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))

/*DDRx is used to declare type in which the Pin is to be used

        PORTx is used to take in value or give out value based on DDRx

        PINx is used to check the value of a pin*/

unsigned int Val;

int main(void){

        SET_BIT(DDRB,PINB1);

        SET_BIT(PORTD,PINB1);        

                //Set the wave form generation and time pre-scaling

        TCCR1A |= 1<<WGM11 | 1<<COM1A1; // WGM is to determine the type of counter || sets the mode of the PWM

        TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10; //CS is for prescalling

                //Set upper limit for time || Defines the TOP value

        ICR1 = 255;

        int UBRR_Value = 25;//for 2400 baud rate

        UBRR0H = (unsigned char) (UBRR_Value >> 8);

        UBRR0L = (unsigned char) UBRR_Value;

        UCSR0B = (1 << RXEN0);

        UCSR0C = (1 << USBS0) | (3 << UCSZ00);

        while (1){        

                while(!(UCSR0A & (1 << RXC0)));

                Val = UDR0;

                OCR1A = Val;

        }

        return(0);

}

 

 

This blog has been submitted by KRSSG under the Robocraze Club Outreach Program.

Author: Vishesh & Vrihad

Components and Supplies

    You may also like to read

    Frequently Asked Questions

    Back to blog

    Leave a comment

    Please note, comments need to be approved before they are published.

    Components and Supplies

      You may also like to read