Project Report Embedded

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 73

Training on

Embedded System & AVR Microcontroller


Submitted in partial fulfillment of the requirement for the award of the degree

of

Bachelor of Technology

In

Electronic & Communication Engg.

Submitted By

Name: Ishan Sharma

Roll No.:8512021

Batch:2012-2016

Department of Electronic & Communication Engg.

Jai Parkash Mukand Lal Innovativev Engg. & Technology Institute,

Radaur-135133(Yamuna Nagar)

(Affiliated to Kurukshetra University,Kurukshetra,Haryana,India)


Embedded System
&
AVR Microcontroller
Acknowledgement

It is my pleasure to be indebted to various people, who directly or indirectly contributed in the


development of this work and who influenced my thinking, behavior, and acts during the course
of study. I express my sincere gratitude to worthy Mr.Vikas Dhawan Principal for providing me
an opportunity to undergo summer training at Sofcon India Pvt. Ltd.I am thankful to Mr.Peeyush
for his support, cooperation, and motivation provided to me during the training for constant
inspiration, presence and blessings. I also extend my sincere appreciation to Ms.Parul who
provided her valuable suggestions and precious time in accomplishing my project report. Lastly,
I would like to thank the almighty and my parents for their moral support and my friends with
whom I shared my day-to-day experience and received lots of suggestions that improved my
quality of work.
Abstract

This project has been developed as a part of Industrial Training, which Kururkshetra University
requires its students to undergo, during their 6-week Training in partial fulfillment of their Four
Year Bachelor of Technology Curriculum. The purpose of the Industrial Training is to
familiarize the students of B.Tech course with the present working environment in the country
and how to utilize the personal skills in different types of jobs. This training makes a person
more confident of how he can use his skills in the computer field.

There are tremendous job in Electronic & Communication Field. One can get a good job after the
B.Tech course and this training is helpful to him in every way.

With the help of this training, the student has an opportunity to study the latest technical trends
those have been established as well as those that are still developing.
Table Of Content

SR.NO. TOPIC PAGE


1. AVR Microcontroller Basics: Basics, Architecture & Pin
Description
2. How To Interface LED with AVR Microcontroller
3. How To interface LCD with AVR Microcontroller
4. How to Display Text on 2x16 LCD with AVR microcontroller
5. Display Custom Characters on LCD with AVR microcontroller
6. How to use inbuilt ADC of AVR microcontroller
7. Serial Communication (Data Receive) using AVR Microcontroller
8. How to interface AVR microcontroller with PC using USART
9. How to use External Hardware Interrupts of AVR microcontroller
10. Serial Communication with AVR microcontroller using interrupts
11. How to use Internal ADC of AVR microcontroller using Interrupts
12. Dtmf Based Wireless System
13. Conclusion
14. References
CHAPTER 1
AVR MICROCONTROLLER: BASICS, ARCHITECTURE & PIN
DESCRIPTION
Microcontroller can be termed as a single on chip computer which includes number of
peripherals like RAM, EEPROM, Timers etc., required to perform some predefined task.

Does this mean that the microcontroller is another name for a computer…? The answer is NO!
The computer on one hand is designed to perform all the general purpose tasks on a single
machine like you can use a computer to run a software to perform calculations or you can use a
computer to store some multimedia file or to access internet through the browser, whereas the
microcontrollers are meant to perform only the specific tasks,

For eg: switching the AC off automatically when room temperature drops to a certain defined
limit and again turning it ON when temperature rises above the defined limit.

There are number of popular families of microcontrollers which are used in different applications
as per their capability and feasibility to perform the desired task, most common of these are
8051, AVR and PIC microcontrollers. In this article we will introduce you with AVR family of
microcontrollers.
History of AVR
AVR was developed in the year 1996 by Atmel Corporation. The architecture of AVR was
developed by Alf-Egil Bogen and Vegard Wollan. AVR derives its name from its developers and
stands for Alf-Egil Bogen Vegard Wollan RISC microcontroller, also known as Advanced
Virtual RISC. The AT90S8515 was the first microcontroller which was based on AVR
architecture however the first microcontroller to hit the commercial market was AT90S1200 in
the year 1997.

AVR microcontrollers are available in three categories:


1. TinyAVR – Less memory, small size, suitable only for simpler applications
2. MegaAVR – These are the most popular ones having good amount of memory (upto 256
KB), higher number of inbuilt peripherals and suitable for moderate to complex applications.

3. XmegaAVR – Used commercially for complex applications, which require large program
memory and high speed. The following table compares the above mentioned AVR series of
microcontrollers:

Series Name Pins Flash Memory Special Features


Tiny AVR 6-32 0.5 - 8KB Small in Size
Mega AVR 28-100 4 – 256KB Extended Peripherals
XMEGA AVR 44-100 16 – 384KB DMA, Event System Included

What’s special about AVR?


They are fast: AVR microcontroller executes most of the instructions in single execution cycle.
AVRs are about 4 times faster than PICs, they consume less power and can be operated in
different power saving modes. Let’s do the comparison between the three most commonly used
families of microcontrollers.

8051 PIC AVR

SPEED Slow Moderate Fast


MEMORY Small Large Large
ARCHITECTURE CISC RISC RISC
ADC Not Present Inbuilt Inbuilt
Timers Inbuilt Inbuilt Inbuilt
PWM Channels Not Present Inbuilt Inbuilt

AVR is an 8-bit microcontroller belonging to the family of Reduced Instruction Set Computer
(RISC). In RISC architecture the instruction set of the computer are not only fewer in number
but also simpler and faster in operation. The other type of categorization is CISC (Complex
Instruction Set Computers). We will explore more on this when we will learn about the
architecture of AVR microcontrollers in following section.

Let’s see what all this means. What is 8-bit? This means that the microcontroller is capable of
transmitting and receiving 8-bit data. The input/output registers available are of 8-bits. The AVR
family controllers have register based architecture which means that both the operands for an
operation are stored in a register and the result of the operation is also stored in a register.
Following figure shows a simple example performing OR operation between two input registers
and storing the value in Output Register.

The CPU takes values from two input registers INPUT-1 and INPUT-2, performs the logical
operation and stores the value into the OUTPUT register. All this happens in 1 execution cycle.

In our journey with the AVR we will be working on Atmega16 microcontroller, which is a 40-
pin IC and belongs to the megaAVR category of AVR family.
Some of the features of Atmega16 are:

1. 16KB of Flash memory


2. 1KB of SRAM
3. 512 Bytes of EEPROM
4. Available in 40-Pin DIP
5. 8-Channel 10-bit ADC
6. Two 8-bit Timers/Counters
7. One 16-bit Timer/Counter
8. 4 PWM Channels
9. In System Programmer (ISP)
10. Serial USART
11. SPI Interface
12. Digital to Analog Comparator.

Architecture of AVR
The AVR microcontrollers are based on the advanced RISC architecture and consist of 32 x 8-bit
general purpose working registers. Within one single clock cycle, AVR can take inputs from two
general purpose registers and put them to ALU for carrying out the requested operation, and
transfer back the result to an arbitrary register. The ALU can perform arithmetic as well as
logical operations
over the inputs from the register or between the register and a constant. Single register operations
like taking a complement can also be executed in ALU. We can see that AVR does not have any
register like accumulator as in 8051 family of microcontrollers; the operations can be performed
between any of the registers and can be stored in either of them.

AVR follows Harvard Architecture format in which the processor is equipped with separate
memories and buses for Program and the Data information. Here while an instruction is being
executed, the next instruction is pre-fetched from the program memory.
Since AVR can perform single cycle execution, it means that AVR can execute 1 million
instructions per second if cycle frequency is 1MHz. The higher is the operating frequency of the
controller, the higher will be its processing speed. We need to optimize the power consumption
with processing speed and hence need to select the operating frequency accordingly.

There are two flavors for Atmega16 microcontroller:


1. Atmega16:- Operating frequency range is 0 – 16 MHz.
2. Atmega16L:- Operating frequency range is 0 – 8 MHz.
If we are using a crystal of 8 MHz = 8 x 106 Hertz = 8 Million cycles, then AVR can execute 8
million instructions.

Naming Convention.!
The AT refers to Atmel the manufacturer, Mega means that the microcontroller belong to
MegaAVR category, 16 signifies the memory of the controller, which is 16KB.

Architecture Diagram: Atmega16


Following points explain the building blocks of Atmega16 architecture:
I/O Ports: Atmega16 has four (PORTA, PORTB, PORTC and PORTD) 8-bit input-output ports.

Internal Calibrated Oscillator: Atmega16 is equipped with an internal oscillator for driving its
clock. By default Atmega16 is set to operate at internal calibrated oscillator of 1 MHz. The maximum
frequency of internal oscillator is 8Mhz. Alternatively, ATmega16 can be operated using an external
crystal oscillator with a maximum frequency of 16MHz. In this case you need to modify the fuse bits.
(Fuse Bits will be explained in a separate tutorial).
1. ADC Interface: Atmega16 is equipped with an 8 channel ADC (Analog to Digital Converter)
with a resolution of 10-bits. ADC reads the analog input for e.g., a sensor input and converts
it into digital information which is understandable by the microcontroller.

2. Timers/Counters: Atmega16 consists of two 8-bit and one 16-bit timer/counter. Timers are
useful for generating precision actions for e.g., creating time delays between two operations.

a. Watchdog Timer: Watchdog timer is present with internal oscillator. Watchdog timer
continuously monitors and resets the controller if the code gets stuck at any execution
action for more than a defined time interval.

3. Interrupts: Atmega16 consists of 21 interrupt sources out of which four are external. The
remaining are internal interrupts which support the peripherals like USART, ADC, Timers
etc.

4. USART: Universal Synchronous and Asynchronous Receiver and Transmitter interface is


available for interfacing with external device capable of communicating serially (data
transmission bit by bit).

ATmega16 is an 8-bit high performance microcontroller of Atmel’s Mega AVR family with low
power consumption. Atmega16 is based on enhanced RISC (Reduced Instruction Set
Computing) architecture with 131 powerful instructions. Most of the instructions execute in one
machine cycle. Atmega16 can work on a maximum frequency of 16MHz.

ATmega16 has 16 KB programmable flash memory, static RAM of 1 KB and EEPROM of 512
Bytes. The endurance cycle of flash memory and EEPROM is 10,000 and 100,000, respectively.
ATmega16 is a 40 pin microcontroller. There are 32 I/O (input/output) lines which are divided
into four 8-bit ports designated as PORTA, PORTB, PORTC and PORTD.

ATmega16 has various in-built peripherals like USART, ADC, Analog Comparator, SPI, JTAG
etc. Each I/O pin has an alternative task related to in-built peripherals. The following table shows
the pin description of ATmega16.
Ports A, B, C, D, and E
As shown in Figure 8-1 (and discussed in Chapter 4), the Ports A, B, C, and
D use a total of 32 pins. Tables 8-2 through 8-5 provide summaries of features of
Ports A-D and their alternative functions. We will study the alternative functions
of these pins in future chapters, as we discuss the AVR features.

Table 8-2: Port A Alternate Table 8-3: Port B. Alternate


Functions Functions

Bit Function Bit Function


PAO ADCO PBO XCK/TO
PA 1 ADC 1 PB1 Ti
PA2 ADC2 PB2 INT2/AINO
PA3 ADC3 PB3 OCO/AIN1
PA4 ADC4 PB4 SS
PA5 ADC5 PB5 MOSI
PA6 ADC6 PB6 MISO
PA7 ADC7 PB7 SCK

Table 8-4: Port C Alternate Table 8-5: Port D Alternate


Functions Functions
Bit Function Bit Function
PCO SCL PDO RXD
PCI SDA PD1 TXD
PC2 TCK PD2 INTO
PC3 TMS PD3 INT 1
PC4 TDO PD4 OCIB
PC5 TDI PD5 OC1A
PC6 TOSC1 PD6 ICP
PC7 TOSC2 PD7 OC2
CHAPTER 2
HOW TO INTERFACE LED WITH AVR MICROCONTROLLER

All the four ports can be configured to read an input from some external device or to give output
to any external device as per the application. For e.g., a switch is connected to a particular pin,
that pin should be configured as input to read the values from the switch (external Device in this
case) and if you are connecting a LED to any pin of the port then that particular pin should be
configured as output to transmit the signal to the LED (external device in this case). A single port
can be configured such that some of the pins of the same port are input and some are output.

Configuring IO Ports:
Every port (PORTx, x = A or B or C or D) of AVR microcontrollers have three registers
associated with it:
1. DDRx: Data direction Register, to set the direction of each pin of PORTx and configuring
it to be as input or output.
2. PORTx: The values which are to be supplied at the output of the port are written in this
register. These values acts as input to the device connected at output port of the microcontroller
(through PORTx output configured pins).
3. PINx: This register stores the input value from the external connected hardware, when the
port is configured as input port. The input data is read from PINx register.

So the first step in configuring or initializing any of the IO port is to set its direction in data
direction register (DDRx) to define the behavior of individual pins as input or output. A high (1)
in any bit of the DDRx register means the corresponding pin is set as output and vice versa.

Example: Considering switch-LED scenario, suppose a switch is connected to Pin5 (PORTD.4)


of PORTD and LED is connected to Pin8 (PORTD.7) of PORTD. Now we need to initialize the
pins accordingly. The other pins of PORTD are not used in this case so they can be ignored as of
now.

Step-1: In order to configure PORTD.4 as input the value of Pin-5 (DDRD.5) in DDRD register
is made 0.
DDRD.7 DDRD.6 DDRD.5 DDRD.4 DDRD.3 DDRD.2 DDRD.1 DDRD.0
- - 0 - - - - -

Step-2: To initialize PORTD.7 as output the value of Pin-8 (DDRD.7) in DDRD register is made
1.
DDRD.7 DDRD.6 DDRD.5 DDRD.4 DDRD.3 DDRD.2 DDRD.1 DDRD.0
1 - 0 - - - - -
Step-3: Rest of the pins can have any value as they are not being used in this case. The default
values of DDRx register is 0 for each pin i.e., all the ports of AVR microcontrollers are
initialized as input.
DDRD.7 DDRD.6 DDRD.5 DDRD.4 DDRD.3 DDRD.2 DDRD.1 DDRD.0
1 0 0 0 0 0 0 0

So the value of DDRD will be initialized as 0x80.

The above command can also be written in this form:

Where, 0b is symbol used to represent binary numbers and following it is the actual 8-bit value.

Setting the pull up value:


All the four ports of Atmega16 are equipped with internal software controlled pull up resistors.
Every pin of the ports can be pulled up by setting the values into the register PORTx. Following
table illustrates the actual state of the pin with different combination of DDRx and PORTx
values.
DDRx PORTx I/O State Pull Up Description
0 0 Input No PORTx pins set as input and pull-ups
disabled.
0 1 Input Yes PORTx pins set as input with pull up
enabled
1 0 Output No PORTx pins set as output and pull-ups
disabled.
1 1 Output Yes PORTx pins set as output with pull ups
enabled.

Example: Following commands can be used to disable and enable pull-ups on PORTD.
PORTD = 0xFF; //PORTD pins pulled high.
PORTD = 0x00; //Disable pull up registers.

To understand above commands a simple LED blinking experiment is explained below.

Circuit description:
Connect the circuit as shown in the circuit diagram. There is no crystal in the circuit. This project
uses the inbuilt crystal of AVR microcontroller, thereby avoiding the need of external crystal.
The value of the internal crystal varies from 1MHz to 8MHz, which can be set using the fuse
bits. (Readers may connect the external crystal but modify your fuse bits accordingly. Fuse bits
are explained in later articles).

Explanation of code:
#include<avr/io.h>
To include all the input output files for avr microcontroller.

#include<util/delay.h>
WinAvr has in built function for providing delay. To use the delay functions include the above
header file.

DDRA=0xFF;
To make port A as output port

PORTA=~PORTA;
Whatever was the value of PORTA compliment it and send back to PORTA.

_delay_ms(1000);
A delay function, gives a delay of 1000 millisecond.
To understand the compilation and execution of the above program, please refer the tutorial
Working with AVRstudio.

What is to be observed?
Similarly, a code can be for blinking of LED on all four PORTS. It is observed that all pins are
working properly except PC2, PC3, PC4 and PC5 pins. The reason is that the AVR
microcontrollers has inbuilt JTAG, which needs to be disabled for using these pins as I/O pins.
JTAG disabling is explained in a separate article.

// Program to blink LED using AVR Microcontroller (ATmega16)


#include<avr/io.h>
#include<util/delay.h>
int main(void)
{
DDRA=0xFF;
while(1)
{
PORTA=~PORTA;
_delay_ms(1000);
}
}
CHAPTER 3
HOW TO INTERFACE LCD WITH AVR MICROCONTROLLER

In this project LCD is working in 8-bit mode i.e., the data transferred to the LCD must be in 8-bit
data form. The PortA of ATmega16 is connected to data pins of LCD and is defined as
LCD_DATA. PortB is defined as control pins (Rs, R/W and En).

Conceptually, interfacing LCD with AVR microcontroller is similar to that of interfacing it with
any other microcontroller.
The following steps explain in detail how LCD can be interfaced with ATMEGA 16:

Step1: To initialize LCD


The following instructions are used to initialize LCD.
1. 0x38 to initialize LCD in 8-bit mode
2. 0x01 to clear LCD
3. 0x0E to make cursor ON
4. 0x80 to go to first line and 0th position in LCD
Delay of around 50 micro second is necessary b/w two commands for execution of instructions.

void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in 8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 is for 0th position


delay_ms(1);
return;
}

Step2: Define command function


To send any command to LCD
1. Transfer the command to LCD_DATA port
2. Set RS and RW bit to go LOW and enable as HIGH
3. Give a small delay
4. Set enable to LOW

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en); // RS and RW as LOW and EN as HIGH
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en); // RS, RW , LOW and EN as LOW
_delay_ms(50);
return;
}

Step3: Define write function


To display any data on LCD
1. Transfer the data (Ascii value of the character to be sent) to LCD_DATA port.
2. Make RW as LOW and set RS and enable as HIGH.
3. Give a small delay.
4. Make enable pin LOW

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en); // EN and RW as LOW and RS HIGH
_delay_ms(50); // delay to get things executed
return ;
}
// Program to display a single alphabet ‘A’ on LCD
/*
LCD data transfer through 8 bit mode
Writing a single letter A on LCD

LCD DATA port----PORT A


ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
*/

#include<avr/io.h>
#include<util/delay.h>
#define LCD_DATA PORTA // LCD data port
#define ctrl PORTB
#define en PB2 // enable signal
#define rw PB1 // read/write signal
#define rs PB0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);

int main()
{
DDRA=0xff; // making LCD_DATA port as output port
DDRB=0x07; // making signal as out put
init_LCD(); // initialization of LCD
_delay_ms(50); // delay of 50 milli seconds
LCD_write('A'); // call a function to write A on LCD
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); //initialization of 16X2 LCD in 8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80);
delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}
CHAPTER 4
DISPLAYING TEXT ON 2x16 LCD USING AVR
MICROCONTROLLER

The connection of the LCD with the AVR microcontroller (ATmega16) is shown in the circuit
diagram. A string is nothing but a sequence of characters. The following steps explain how to
display a string on the LCD.

To send string on LCD:


1. Make a string pointer variable
2. Pass the starting address of string to that pointer variable
3. Pass the string pointer value to the LCD_write function
4. Increment the pointer value and go to step (iii.) till the value of pointer reaches
NULL character.
void LCD_write_string(unsigned char *str) //store address value of the string in pointer *str
{
int i=0;
while(str[i]!='\0') // loop will go on till the NULL
character in the string
{
LCD_write(str[i]); // sending data on LCD byte
by byte
i++;
}
return;
}

//Program to Display string on LCD using AVR Microcontroller (ATmega16)


/*
LCD DATA port----PORT B
signal port------PORT D
rs-------PD0
rw-------PD1
en-------PD2
*/

#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTB //LCD data port

#define ctrl PORTD


#define en PD2 // enable signal
#define rw PD1 // read/write signal
#define rs PD0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);

int main()
{
DDRB=0xff;
DDRD=0x07;
init_LCD(); // initialization of LCD
_delay_ms(50); // delay of 50 mili seconds
LCD_write_string("Embedded System"); // function to print
//string on LCD
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in //8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 //is for 0th position
_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}
void LCD_write(unsigned char data)
{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void LCD_write_string(unsigned char *str) //store address //value of the string in pointer *str
{
int i=0;
while(str[i]!='\0') // loop will go on //till the NULL character in the string
{
LCD_write(str[i]); // sending //data on LCD byte by byte
i++;
}
return;
}
CHAPTER 5
DISPLAYING CUSTOM CHARACTERS ON LCD USING AVR
MICROCONTROLLER

This article assumes that the readers are aware of the concepts of interfacing LCD with AVR
microcontroller (ATMEGA 16). For more information about interfacing LCD with AVR, refer
How to display string on LCD using AVR. In order to create a custom character its configuration
is first defined in the CGRAM of the LCD. A maximum of eight characters can be stored at a
time in the 16 x 2 LCD. Every character is assigned eight bytes in the CGRAM and by
configuring these bytes any character can be generated. The size of the CGRAM is 64 bytes.

For detailed description about configuring the CGRAM, refer to creating custom characters on
LCD using 8051. The concepts of generating a custom character remain the same. The
connection of LCD with the AVR is shown in the circuit diagram.

//Program to display special Characters on LCD using AVR Microcontroller (ATmega16)


/*
To display special character on LCD data
LCD DATA port----PORT B
ctrl port------PORT D
rs-------PD0
rw-------PD1
en-------PD2

using internal clock frequency 1MHz

*/
#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTB //LCD data port

#define signal PORTD


#define en PD2 // enable signal
#define rw PD1 // read/write signal
#define rs PD0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_character();

int main()
{
DDRB=0xff;
DDRD=0x07;
init_LCD();
_delay_ms(50); // delay of 50 mili seconds
LCD_character();
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in //8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 //is for 0th position
_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}
void LCD_write(unsigned char data)
{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void LCD_character()
{
LCD_cmd(64); // Address where customized character is to //be stored
LCD_write(0);
LCD_write(14);
LCD_write(17);
LCD_write(2);
LCD_write(4);
LCD_write(4);
LCD_write(0);
LCD_write(4);
LCD_cmd(0x80); // Location of LCD where the character is //to be displayed
LCD_write(0); // Displaying the character created at //address 0x64
_delay_ms(10);

LCD_cmd(72); // Address where customized character is to //be stored


LCD_write(0);
LCD_write(10);
LCD_write(21);
LCD_write(17);
LCD_write(18);
LCD_write(4);
LCD_write(0);
LCD_write(0);
LCD_cmd(0x82); // Location of LCD where the character is //to be displayed
LCD_write(1); // Displaying the character created at //address 0x72
_delay_ms(10);

LCD_cmd(80); //Address where customized character is to //be stored


LCD_write(0);
LCD_write(0);
LCD_write(10);
LCD_write(0);
LCD_write(4);
LCD_write(0);
LCD_write(14);
LCD_write(17);
LCD_cmd(0x84); // Location of LCD where the character is //to be displayed
LCD_write(2); // Displaying the character created at //address 0x80
_delay_ms(10);

LCD_cmd(88); //Address where customized character is to //be stored


LCD_write(1);
LCD_write(3);
LCD_write(5);
LCD_write(9);
LCD_write(9);
LCD_write(11);
LCD_write(27);
LCD_write(24);
LCD_cmd(0x86); // Location of LCD where the character is //to be displayed
LCD_write(3); // Displaying the character created at //address 0x88
_delay_ms(10);

LCD_cmd(96); // Address where customized character is to //be stored


CD_write(0);
LCD_write(0);
LCD_write(0);
LCD_write(4);
LCD_write(0);
LCD_write(31);
LCD_write(0);
LCD_cmd(0xC0); // location where the character is to be //displayed
LCD_write(4); // Display the character created at address //0x96
_delay_ms(10);

LCD_cmd(104); //Address where customized character is //stored


LCD_write(0);
LCD_write(17);
LCD_write(10);
LCD_write(17);
LCD_write(4);
LCD_write(0);
LCD_write(14);
LCD_write(17);
LCD_cmd(0xC2); // Location of LCD where the character is //to be displayed
LCD_write(5); // Display the character created at address //0x104
_delay_ms(10);

LCD_cmd(112); // Address where customized character is to //be stored


LCD_write(0);
LCD_write(14);
LCD_write(17);
LCD_write(2);
LCD_write(4);
LCD_write(4);
LCD_write(0);
LCD_write(4);
LCD_cmd(0xC4); // Location of LCD where the character is //to be displayed
LCD_write(6); // Display the character created at //address 0x112
_delay_ms(10);

LCD_cmd(120); // Address where customized character is to //be stored


LCD_write(10);
LCD_write(0);
LCD_write(4);
LCD_write(0);
LCD_write(14);
LCD_write(17);
LCD_write(17);
LCD_write(14);
LCD_cmd(0xC6); // Location of LCD where the character is //to be displayed
LCD_write(7); // Display the character created at //address 0x120
_delay_ms(10);
}
CHAPTER 6
CONFIGURING INBUILT ADC OF AVR MICROCONTROLLER

ATmega16 has an inbuilt 10 bit, 8-channel ADC system. Some of the basic features of
Armega16 ADC are:
1. 8 Channels.
2. 10-bit Resolution.
3. Input voltage range of 0 to Vcc.
4. Selectable 2.56V of internal Reference voltage source.
5. AREF pin for External Reference voltage.
6. ADC Conversion Complete Interrupt.

ADC channels in Atmega16 are multiplexed with PORTA and use the common pins (pin33 to
pin40) with PORTA. ADC system of Atmega16 microcontroller consists of following pins:
1. ADC0-ADC7: 8 Channels from Pin 40 to Pin 33 of Atmega16 ADC peripheral.
2. AREF: Pin32 of Atmega16 microcontroller, the voltage on AREF pin acts as the
reference voltage for ADC conversion, reference voltage is always less than or
equal to the supply voltage, i.e., Vcc.
3. AVCC: Pin30, this pin is the supply voltage pin for using PORTA and the ADC;
AVCC pin must be connected to Vcc (microcontroller supply voltage) to use
PORTA and ADC.

Note: External reference voltage source can be used at AREF pin. However, Atmega16 also has
internal reference voltage options of 2.56V and Vref = Vcc.

The figure below shows the pin configuration for ADC system of Atmega16 microcontroller.
ADC Registers
To use the ADC peripheral of Atmega16, certain registers need to be configured.

i. ADMUX (ADC Multiplexer And Selection Register)

REFS[0:1] bits determine the source of reference voltage whether it is internal or the external
voltage source connected to AREF pin. MUX[4:0] bits are used to select between the channels
which will provide data to ADC for conversion. ADLAR bit when set to 1 gives the left adjusted
result in data registers ADCH and ADCL.

ii. ADCSRA (ADC Control and Status Register)

ADEN: ADC Enable bit, this bit must be set to 1 for turning ADC on.
ADSC: ADC Start Conversion bit, this bit is set to 1 to start ADC conversion, as soon as
conversion is completed this bit is set back to 0 by the hardware.
ADATE: ADC Auto Trigger Enable, this bit is set to 1 to enable auto triggering of ADC
conversion.
ADIF: ADC Interrupt Flag, this bit is set to 1 when ADC conversion gets complete.
ADIE: ADC Interrupt Enable, this bit is set to 1 if we want to activate the ADC conversion
complete interrupt.
ADPS[0:2]: ADC Prescaler bits, these bits are used to set the ADC clock frequency, the
configuration of these bits determine the division factor by which the microcontroller clock
frequency is divided to get the ADC clock frequency. The figure above shows the prescaler bit
values for respective division factor.

The ADC clock frequency must lie somewhere between 50 KHz to 200 KHz.

iii. ADCH & ADCL (ADC Data Registers)


When the ADC conversion is complete the data is stored in these two registers. The data
configuration depends on the ADLAR bit value of ADMUX register. If ADLAR=0, data is right
adjusted and if ADLAR=1, data is left adjusted. Always read ADCL first and then ADCH. In
cases where the 8-bit precision is enough set the ADLAR bit to 1 to left adjust the data and read
only the ADCH data register.

When ADLAR = 0,

When ADLAR = 1,

Circuit description
Connect the circuit as shown in the circuit diagram. A ceramic capacitor 104 is connected in
between AVcc (pin 30) and Aref (pin 32). AVcc (pin 30) is connected to external supply +5V.
Code explanation
To interface analog device with AVR microcontroller, follow the following steps for
programming it.

Step1: To initialize ADC


1. Set the value in ADMUX register according to the ADC channel and the
reference voltage.
2. Set the Prescaler bits accordingly in ADCSRA register.
3. Set the ADEN bit to enable the ADC.
void ADC_init(void) // Initialization of ADC
{
ADMUX=(1<<REFS0); // AVcc with external capacitor at AREF
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
// Enable ADC and set Prescaler
division factor as 128
}

Step2: To read the analog value


1. Put the channel value in ADMUX
2. Start the conversion by setting the ADSC bit.
3. Monitor the ADIF bit for conversion complete.
4. Clear the conversion bit ADIF. By writing it 1.
5. Digital converted result is now available in ADCH and ADCL registers.
unsigned int ADC_read(unsigned char ch)
{
ch= ch & 0b00000111; // channel must be b/w 0 to 7
ADMUX |= ch; // selecting channel

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


while(!(ADCSRA & (1<<ADIF))); // waiting for ADIF, conversion complete
ADCSRA|=(1<<ADIF); // clearing of ADIF, it is done by
writing 1 to it

return (ADC);
}
//Program for ADC to read from channel 0 and show the 8 bit o/p on PORTB

#include<avr/io.h>
#include<util/delay.h>
void ADC_init(void);
unsigned int ADC_read(unsigned char);

int main(void)
{
unsigned int value;
DDRB=0xFF;
DDRD=0x03;
ADC_init(); // Initialization of ADC
// ch=0;
while(1)
{
value=ADC_read(0);
PORTB=value;
_delay_ms(500);
}
}

void ADC_init(void) // Initialization of ADC


{
ADMUX=(1<<REFS0); // AVcc with external capacitor at AREF
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
// Enable ADC and set //Prescaler division factor as 128
}
unsigned int ADC_read(unsigned char ch)
{
ch= ch & 0b00000111; // channel must be b/w 0 to 7
ADMUX |= ch; // selecting channel

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


while(!(ADCSRA & (1<<ADIF))); // waiting for ADIF, //conversion complete
ADCSRA|=(1<<ADIF); // clearing of ADIF, it is //done by
writing 1 to it

return (ADC);
}
CHAPTER 7
SERIAL COMMUNICATION (DATA RECEIVE) USING USART

There are two methods for serial data communication (i) Synchronous and (ii) Asynchronous
communication. In Synchronous communication method complete block (characters) is sent at a
time. It doesn’t require any additional bits (start, stop or parity) to be added for the
synchronization of frame. The devices are synchronized by clock. And in asynchronous
communication data transmission is done byte by byte i.e., one byte at a time. The additional bits
are added to complete a frame.

In synchronous communication the frame consists of data bits while in asynchronous


communication the total number of bits in a frame may be more than the data bits.

There are three ways in which serial communication can be done


i. Simplex: Transmission is done in one direction.

ii. Half duplex: Transmission can be done in both the direction but one side at a time.

iii. Full duplex: Transmission can be done in both the direction simultaneously.
Atmega16 is equipped with three different kinds of serial communication peripheral systems:
i. Serial USART
ii. SPI (Serial Peripheral Interface)
iii. TWI (Two wire Interface)

SERIAL USART (universal synchronous asynchronous receiver and transmission/ transmitter):


Serial USART provides full-duplex communication between the transmitter and receiver.
Atmega16 is equipped with independent hardware for serial USART communication. Pin-14
(RXD) and Pin-15 (TXD) provide receive and transmit interface to the microcontroller.

Atmega16 USART provides asynchronous mode of communication and do not have a dedicated
clock line between the transmitting and receiving end. The synchronization is achieved by
properly setting the baud rate, start and stop bits in a transmission sequence.
Start bit and stop bit: These bits are use to synchronize the data frame. Start bit is one single low
bit and is always given at the starting of the frame, indicating the next bits are data bits. Stop bit
can be one or two high bits at the end of frame, indicating the completion of frame.

Baud Rate: In simple words baud rate is the rate at which serial data is being transferred.
Atmega16 USART has following features:
1. Different Baud Rates.
2. Variable data size with options ranging from 5bits to 9bits.
3. One or two stop bits.
4. Hardware generated parity check.
5. USART can be configured to operate in synchronous mode.
6. Three separate interrupts for RX Complete, TX complete and TX data register empty.

USART Registers

To use the USART of Atmega16, certain registers need to be configured.

UCSR: USART control and status register. It’s is basically divided into three parts UCSRA,
UCSRB and UCSRC. These registers are basically used to configure the USART.

UBRR: USART Baud Rate Registers. Basically use to set the baud rate of USART
UDR: USART data register

i. UCSRA: (USART Control and Status Register A)

RXC (USART Receive Complete): RXC flag is set to 1 if unread data exists in receive buffer,
and set to 0 if receive buffer is empty.
TXC (USART Transmit complete): TXC flag is set to 1 when data is completely transmitted to
Transmit shift register and no data is present in the buffer register UDR.
UDRE (USART Data Register Empty): This flag is set to logic 1 when the transmit buffer is
empty, indicating it is ready to receive new data. UDRE bit is cleared by writing to the UDR
register.

ii. UCSRB: (USART Control and Status Register B)


RXCIE: RX Complete Interrupt Enable,
When 1 -> RX complete interrupt is enabled.
When 0 -> RX complete interrupt is disabled.

TXCIE: TX Complete Interrupt Enable,


When 1 -> TX complete interrupt is enabled
When 0-> TX complete interrupt is disabled
UDRIE: USART Data Register Empty Interrupt Enable,
When 1 -> UDRE flag interrupt is enabled.
When 0 -> UDRE flag interrupt is disabled.
RXEN: Receiver Enabled,
When 1 -> USART Receiver is enabled.
When 0 -> USART Receiver is disabled.
TXEN: Transmitter Enabled,
When 1 -> USART Transmitter is enabled.
When 0 -> USART Transmitter is disabled.

iii. UCSRC: (USART Control and Status Register C)


The transmitter and receiver are configured with the same data features as configured in this
register for proper data transmission.

URSEL: USART Register select. This bit must be set due to sharing of I/O location by UBRRH
and UCSRC
UMSEL: USART Mode Select,
When 1 -> Synchronous Operation
When 0 -> Asynchronous Operation
UPM[0:1]: USART Parity Mode, Parity mode selection bits.
USBS: USART Stop Select Bit,
When 0-> 1 Stop Bit
When 1 -> 2 Stop Bits
UCSZ[0:1]: The UCSZ[1:0] bits combined with the UCSZ2 bit in UCSRB sets size of data
frame i.e., the number of data bits. The table shows the bit combinations with
respective character size.

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

iv. UDR: (USART Data Register)

The USART Data receive and data transmit buffer registers share the same address referred as
USART UDR register, when data is written to the register it is written in transmit data buffer
register (TXB). Received data is read from the Receive data buffer register (RXB).

v. UBRRH & UBRRL (USART Baud Rate Registers)

The UBRRH register shares the same I/O address with the UCSRC register, The differentiation
is done on the basis of value of URSEL bit.
When URSEL=0; write operation is done on UBRRH register.

When URSEL=1; write operation is done on UCSRC register.

The UBRRH and UBRRL register together stores the 12-bit value of baud rate, UBRRH contains
the 4 most significant bits and UBRRL contains the other 8 least significant bits. Baud rates of
the transmitting and receiving bodies must match for successful communication to take place.

UBRR register value is calculated by the following formula:

The Connection of MAX232 and ATmega16 is shown in the circuit diagram. The MAX232 is
used for level conversion. The reader can refer the component section for further details on MAX
232.The T1IN (pin11) of Max232 is connected to Tx (pin15) of AVR and R1IN(pin12) is
connected to Rx(pin14) of AVR. The HyperTerminal software is used to send data to
microcontroller via COM port.
Step 1: First step is to select the Baud rate. Baud rate of two devices must match or else they will
not be able to synchronize with each other.
#define USART_BAUDRATE 9600
Step2: To set a particular Baud Rate in ATmega16, write the corresponding UDRR value. The
UDRR value is calculated by using the formula
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

Step3: To initialize the USART


1. Turn on transmission and reception circuitry.
2. Select the number of stop bits.
3. Set the size of data.
4. Load the value of UBRR to set the baud rate.
void usart_init()

UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);

UBRRL = BAUD_PRESCALE;
// Load lower 8-bits of the baud rate value into the low byte of the
UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the
high byte of the UBRR register
}

Step4: Get the data from USART


Monitor the status of RXC (receiver complete) flag . RXC becomes high when it receives the
stop bit signal. So if RXC is high it means that the data is loaded into UDR register. Collect the
data from UDR or else it might get lost or overwritten with the next incoming data.
unsigned int usart_getch()

while ((UCSRA & (1 << RXC)) == 0);


// Do nothing until data has been received and is ready to be read from UDR
return(UDR); // return the byte
}
// Program to receive data from USART and displaying it on LCD

/*
Receive data from serial port and display it on LCD
LCD DATA port----PORT A
ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
using external clock frequency 12MHz
*/

#define F_CPU 12000000UL


#define USART_BAUDRATE 9600 // Baud Rate value
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTA //LCD data port

#define ctrl PORTB


#define en PB2 // enable signal
#define rw PB1 // read/write signal
#define rs PB0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_clear();

void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();

int main()
{
unsigned char value;
DDRA=0xff; // LCD_DATA port as output port
DDRB=0x07; // signal as out put
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 milli seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // Call a function to get
//data from serial port
LCD_cmd(0xC0); // to go in second line and //zeroth position on LCD
LCD_write(value); // write data to LCD
}
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in //8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 //is for 0th position
_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the //transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes

UBRRL = BAUD_PRESCALE;
// Load lower 8-bits of the baud rate value //into the low byte of the
UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the //baud rate value..
// into //the
high byte of the UBRR register
}

unsigned int usart_getch()


{
while ((UCSRA & (1 << RXC)) == 0);
// Do nothing until data has been received and is //ready to be read from UDR
return(UDR); // return the byte
}
CHAPTER 8
HOW TO INTERFACE AVR MICROCONTROLLER WITH PC
USING USART (RS232 PROTOCOL)

The registers of USART system are already explained in previous article. Before transmitting the
data, it must be stored in UDR register. The HyperTerminal software is used to show received
data. The following steps can be followed to transmit the data to COM port of computer.
i. Monitor the status of UDRE (USART Data register Empty) flag.
ii. A high on the UDRE indicates that the UDR register is empty and ready to accept new
data to be sent.

void usart_putch(unsigned char send)


{
while ((UCSRA & (1 << UDRE)) == 0); // Do nothing until UDR is ready..
//
for more data to be written to it
UDR = send; // Send the byte
}
// Program to receive data from USART and displaying that..
// data on LCD and sending the same data on HyperTerminal.
/*
get data from serial port and displaying it on LCD and send back to the HyperTerminal
LCD DATA port----PORT A
ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
@ external clock frequency 12MHz
*/
#define F_CPU 12000000UL

#define USART_BAUDRATE 9600


#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTA // LCD data port


#define ctrl PORTB
#define en PB2 // enable signal
#define rw PB1 // read/write signal
#define rs PB0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_clear();

void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();

int main()
{
unsigned char value;
DDRA=0xff;
DDRB=0x07;
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 mili seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // get data from serial //port
LCD_cmd(0xC0);
LCD_write(value); // write data to LCD
usart_putch(value); // send data back to the //PC
(HyperTerminal)
}
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); //initialization of 16X2 LCD in //8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 //is for 0th position
_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and //reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud //rate value..


// into the low byte //of the
UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the //baud rate value..
// into //the
high byte of the UBRR register
}

void usart_putch(unsigned char send)


{
while ((UCSRA & (1 << UDRE)) == 0); // Do nothing until //UDR is ready..
// for more data to //be written
to it
UDR = send; // Send the byte
}

unsigned int usart_getch()


{
while ((UCSRA & (1 << RXC)) == 0);
// Do nothing until data have been //received and is ready
to be read from UDR
return(UDR); // return the byte
}
CHAPTER 9
HOW TO USE EXTERNAL (HARDWARE) INTERRUPTS OF AVR

When an interrupt occurs, the normal flow of instructions is suspended by the microcontroller
and the code corresponding to the interrupt, which has occurred, is executed. Once the code
corresponding to the interrupt is executed completely the execution again begins from the same
instruction where it was stopped.

Following is what happens when an interrupt occurs:


1. Microcontroller normally completes the instruction which is being executed.
2. The program control transfers to Interrupt Service Routine (ISR). Each interrupt have an
associated ISR which is a piece of code which tells the microcontroller what to do when an
interrupt has occurred.
3. Execution of ISR is performed by loading the beginning address of the corresponding ISR
into program counter.
4. Execution of ISR continues until the return from the interrupt instruction (RETI) is
encountered.
5. When ISR is complete, the microcontroller resumes processing where it left off before the
interrupt occurred, i.e., program control is reverted back to the main program.

The whole process can be visualized by the following flow diagram:

Atmega16 Interrupts
Number of available interrupts varies with different microcontrollers of AVR family. Atmega16
in total has twenty one (21) interrupts available. The available interrupts are categorized in two
classes:

1. External Interrupts- Out of the twenty one interrupts available, four interrupts are directly
present on controller pins to handle the interrupts generated by external sources, so they are
called as external interrupts. The four available interrupts and their respective pins are shown in
the figure below in their order of priority:

2. Internal Interrupts- The remaining seventeen (17) interrupts are available for internal use
and support the precise and efficient operation of various peripherals like ADC, Timers, and
USARTs etc. The table below describes the available internal interrupts in the order of their
priority:
S. No. INTERRUPT DEFINITION
1 TIMER2 COMP Timer/Counter2 Compare match interrupt
2. TIMER2 OVF Timer2 Overflow interrupt
3. TIMER1 CAPT Timer/Counter1 Capture Event interrupt
4. TIMER COMPA Timer/Counter1 Compare Match A interrupt
5. TIMER COMPB Timer/Counter Compare Match B interrupt
6. TIMER1 OVF Timer/Counter1 Overflow interrupt
7. TIMER0 OVF Timer/Counter0 Overflow interrupt
8. SPI, STC Serial Transfer Complete interrupt
9. USART,RXC USART Receive Complete interrupt
10. USART, UDRE USART Data Register Empty interrupt
11. USART, TXC USART Transmit Complete interrupt
12. ADC ADC Conversion Complete interrupt
13. EE_RDY EEPROM Ready interrupt
14. ANA_COMP Analog Comparator interrupt
15. TWI Two-wire serial interface interrupt
16. TIMER0 COMP Timer/Countrt0 Compare Match interrupt
17. SPM_RDY Store Program Memory Read interrupt

The internal interrupts will be discussed with their respective peripherals. The external interrupts
are mainly focused in this article.

External Interrupts Configuration Registers:


To configure an external interrupt INT0, INT1 or INT2,it is required to initialize the respective
interrupt by doing appropriate bit settings of following 4 registers. The scope of this document is
limited to the explanation of the bits corresponding to interrupts only, the detailed description
about other bits of these register can be found in the datasheet of Atmega16.

1. MCUCR (MCU Control register)

The Bit0, Bit1, Bit2 and Bit3 of MCUCR register determines the nature of signal at which the
interrupt 0 (INT0) and interrupt 1 (INT1) should occur.
2. MCUCSR (MCU Control and Status Register)

The Bit6 of MCUCSR register determines the nature of signal at which the external interrupt 2
(INT2) should occur. INT2 is edge triggered only, it cannot be used for level triggering like
INT0 and INT1.

3. GICR (General Interrupt Control Register)

The GICR register Bit5, Bit6 and Bit7 called the interrupt masks are used to disable/enable the
respective interrupt. Interrupt is disabled when bit value is set to 0 and enabled when bit value is
set to 1. By default all the interrupts are disabled.
Above mentioned three registers have to be configured accordingly to initialize a particular
interrupt. Also note that in addition to the above mentioned registers, the I-bit (Bit7, Global
Interrupt Enable) of SREG register must also be set to 1. If Global Interrupt enable bit is set to 0,
none of the interrupts will work irrespective of the other register settings. The set and clear of I-
bit is done by SEI and CLI instructions.

Programming Steps:
For programming an interrupt, the following steps must be followed:
1. Clear Global Interrupt enable bit in SREG register.
2. Initialize the interrupt by appropriately configuring the MCUCR, MCUCSR and GICR
registers.
3. Set Global Interrupt Enable bit in SREG register.
4. Define the appropriate Interrupt service routine (ISR) for the interrupt.
There are two ways of writing ISR, for e.g. ISR for INT0 can be written in following two ways:
A. ISR (INT0_vect)
B. SIGNAL (SIG_INTERRUPT0)
Example: Let’s write a simple code to get an interrupt working. Initialize INT0 to generate
interrupt at rising edge trigger. The interrupt is generated by using push button which toggle the
LEDs status connected to PORTA. The connections of LEDs with controller is shown in circuit
diagram.
So for enabling INT0, it is needed to set Bit6 of GICR register, i.e.,
GICR= (1<<INT0);
For Rising Edge trigger of INT0 the Bit0 and Bit1 status will be-
ISC00 (Bit0) = 1
ISC01 (Bit1) = 1

So, MCUCR=(3<<ISC00);

// Program to use External (Hardware) Interrupts of AVR Microcontroller (ATmega16)


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

/***** Function To Initialize Ports*****/


void init_ports()
{
DDRA = 0xFF;
PORTA = 0x55;
}

/***** Function To Initialize Interrupts*****/


void init_interrupts()
{
cli(); //Disable Global Interrupts
GICR =(1<<INT0); //Set Bit6 of GICR to unmask INT0 //interrupt.
MCUCR =(3<<ISC00); //Configuring MCUCR for Rising Edge //interrupt for
INT0
sei(); //Enable Global Interrupts

/***** Interrupt Service Routine For INT0*****/


ISR (INT0_vect)
{
PORTA = ~PORTA;
_delay_ms(100);
}

/***** Main Function *****/


int main(void)
{
init_ports();
while(1)
{
init_interrupts();
}
}
CHAPTER 10
SERIAL COMMUNICATION WITH AVR MICROCONTROLLER
USING INTERRUPTS

The UCSRB register has RXCIE (Reception Complete Interrupt Enable) bit, which is used to
enable the serial reception interrupt. The I-bit of SREG register is must be set to enable global
interrupt of ATmega16. The circuit diagram is same as used in previous article of USART.

Code Explanation
Step1: In order to use serial interrupts, the first step will be to initialize USART. In this case we
need to add one more step to the initialization done in the polling method. The RXCIE (Receiver
Complete Interrupt Enable) bit in UCSRB register is also set high to enable the serial receive
interrupt. Every time one byte of the data is received serially, a serial receive interrupt is
generated and the control transfers to the corresponding ISR. The RXC flag will go high to
indicate the serial receive interrupt.
void usart_init()
{
UCSRB |= (1<<RXCIE) | (1 << RXEN) | (1 << TXEN); // Turn on the
transmission reception ..
// circuitry and
receiver interrupt
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value..


// into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value..
// into the high byte of the UBRR register
}

Step2: Now define its ISR


When the serial receive interrupt comes, the serial data is present in UDR (no need monitor RXC
flag) and needs to be read in a variable. (In this program the data which is received is sent back
serially. The controller is connected to PC and the data which is sent is received on the
HyperTerminal).
ISR (USART_RXC_vect)
{
unsigned char value;
value = UDR; // Fetch the received byte value into the variable "value"
UDR = value; //Put the value to UDR

Things to be noted:
i. Whenever the interrupts are to be used, interrupt.h header file must be included.
#include<avr/interrupt.h>
ii. Global interrupt can be activate by using
sei(); // Enable global interrupt
For more details about interrupt refer to AVR interrupts.
iii. Do not use any key words like interrupt, signal or port while making any function or
while defining any pin/ port, etc.
//Program to get a serial data from RS232 (using HyperTerminal)..
// and sending it back to the RS232 (to HyperTerminal).
#include<avr/io.h>
#include<avr/interrupt.h>

#define USART_BAUDRATE 9600


#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void usart_init();
int main()
{
usart_init(); // initialization of USART

sei(); // Enable global interrupt


for (;;) // infinite loop
{
// Do Nothing
}
}

void usart_init()
{
UCSRB |= (1<<RXCIE) | (1 << RXEN) | (1 << TXEN); // Turn on the //transmission
reception ..
// circuitry //and //receiver interrupt
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // //Use 8-bit //character sizes

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud //rate value..


// into the low byte of the UBRR //register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of //the baud //rate
value..
// into the high byte of the UBRR //register
}
ISR (USART_RXC_vect)
{
unsigned char value;
value = UDR; // Fetch the received byte value //into the variable //"value"
UDR = value; //Put the value to UDR

}
CHAPTER 11

SPI (SERIAL PERIPHERAL INTERFACE) USING AVR


MICROCONTROLLER

Serial Peripheral Interface is a synchronous, full-duplex protocol. SPI is also known as “3-wire
interface” protocol because it needs 3 communication lines named MISO, MOSI and SCK. SPI
protocol needs two devices for communication. One of them is considered as a MASTER and
another one as a SLAVE. AVR microcontrollers contain both MASTER and SLAVE interface
on single chip. Thus, a microcontroller can work as both master and slave device.

SPI interface:
Besides the MISO, MOSI and SCK pins, the SS is also included in SPI system. This pin is used
to select slave device. Following table explains functionality of these pins:

How SPI works:


The SPI is synchronous data transfer protocol, so clock pulse is needed to synchronize both
master and slave device. The clock pulse is generated from master side. The SCK pin of master
provides clock pulse to slave device.

To make any device as master, the SS pin must be set as high. If it is configured as an output pin,
then it made high using the software. If the SS is considered as input pin, it should make high
externally. In slave mode SS is always an input pin, which should be connected to ground (to
make it slave device).

The “MOSI” stands for “master output slave input”. So, the MOSI pin works as output pin for
master device and input pin for salve device. Both master and slave devices contain a buffer
register, called SPDR. Master transfers one bit from its SPDR to slave device in every clock
cycle. It means to send one byte data, 8 clock pulses are needed.

Registers of SPI System:


The SPI system consists three register which are described below:
1. SPCR (SPI control register):

SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0

SPIE (SPI Interrupt Enable) - To enable SPI interrupt this is set as high.
SPE (SPI Enable) - SPI system is enabled when this bit is set.
DORD (Data Order) – For DORD=1, LSB will be transmitted first.
For DORD=0, MSB will be transmitted first.
MSTR (Master/Slave Select) – For MSTR=1, to select device as master.
For MSTR=0, to select device as slave.
SPR [1:0] (SPI clock Rate) - This SPR [1:0] and SPI2X bit of SPSR register decides frequency
of SCK. The combination of these three bits to select SCK frequency are shown in following
table:

2. SPSR (SPI Status REGISTER) :


SPIF WCOL - - - - - SPI2X

SPIF (SPI Interrupt Flag) – This bit become set automatically after completion of serial transfer.
WCOL (Write Collision Flag) – This bit is set if SPDR is written during data transfer.
SPI2X (Double SPI Bit) – By setting 1 to this bit SCK frequency become double.

3. SPDR (SPI Data Register) – This is 8-bit data register used to store receive data and
transmitting data.

Objective: To interface ATmega32 and Atmega16 microcontroller using SPI protocol. Consider
ATmega32 as master and Atmega16 as slave.
Circuit description:
The connection of both master and slave microcontrollers are shown in circuit diagram. MOSI
pins (pin no.6) of both master and slave are connected. The SCK (pin no 8) pins of both master
and slave are connected. SS pin of slave is grounded.

Programming steps:
For Master mode:
1. Set SS, MOSI and SCK pin as output pins.
2. Enable MSTR bit to make it master device.
3. Program SPR [1:0] bits to select SCK frequency.
4. Set SPE bit to enable SPI.
5. Copy data in SPDR register to send.
6. Wait until SPI interrupt flag get set.

For slave mode:


1. Select MOSI pin as output and rest pins as input pins.
2. Set SPE to activate SPI.
3. Wait until SPI interrupt flag get set.
4. Receive data from SPDR register.
// Program to SPI (serial peripheral interface) using AVR microcontroller (ATmega16)
#include<avr/io.h>
#include<util/delay.h>

#define MOSI PB5

void SPI_init();
unsigned char SPI_RX(void);

int main()
{

DDRD=0xFF;
PORTD=0x00;

SPI_init();
while(1)
{
PORTD=SPI_RX(); // move SPDR value to POTRD
}

void SPI_init() //SPI initialization


{
DDRB=(1<<MOSI); // set MOSI as output pin, rest as input
SPCR=(1<<SPE); // Enable SPI
}

unsigned char SPI_RX()


{
while(!(SPSR &(1<<SPIF))); //wait until SPIF get high
return SPDR; // return SPDR value
}
DTMF BASED
WIRELESS ROBOT
INTRODUCTION

DTMF Mobile ROBO is a machine that can be controlled with a mobile . In this project, the
robot is controlled by a mobile phone that makes a call to the mobile phone attached to the robot.
In the course of a call, if any button is pressed, a tone corresponding to the button pressed is
heard at the other end of the call. This tone is called "Dual Tone Multiple-Frequency" (DTMF)
tone. The robot perceives this DTMF tone with the help of the phone stacked on the robot. The
received tone is processed by the microcontroller with the help of DTMF decoder. The
microcontroller then transmits the signal to the motor driver ICs to operate the motors & our
robot starts moving Conventionally, Wireless-controlled robots use rf circuits, which have the
drawbacks of limited working range, limited frequency range and the limited control. Use of a
mobile phone for robotic control can overcome these limitations. It provides the advantage of
robust control, working range as large as the coverage area of the service provider, no
interference with other controllers and up to twelve controls. Although the appearance and the
capabilities of robots vary vastly, all robots share the feature of a mechanical, movable structure
under some form of control. The Control of robot involves three distinct phases: perception,
processing and action. Generally, the preceptors are sensors mounted on the robot , processing is
done by the on-board microcontroller or processor, and the task is performed using motors or
with some other actuators. In this project the robot, is controlled by a mobile phone that makes
call to the mobile phone attached to the robot in the course of the call, if any button is pressed
control corresponding to the button pressed is heard at the other end of the call. This tone is
called dual tone multi frequency tome (DTMF) robot receives this DTMF tone with the help of
phone stacked in the robot The received tone is processed by the atmega16 microcontroller with
the help of DTMF decoder MT8870 the decoder decodes the DTMF tone in to its equivalent
binary digit and this binary number is send to the microcontroller, the microcontroller is
preprogrammed to take a decision for any give input and outputs
its decision to motor drivers in order to drive the motors for forward or backward motion or a
turn. The mobile that makes a call to the mobile phone stacked in the robot acts as a remote. So
this simple robotic project does not require the construction of receiver and transmitter units.
DTMF signaling is used for telephone signaling over the line in the voice frequency band to the
call switching center. The version of DTMF used for telephone dialing is known as touch tone.
DTMF assigns a specific frequency (consisting of two separate tones) to each key s that it can
easily be identified by the electronic circuit. The signal generated by the DTMF encoder is the
direct algebraic submission, in real time of the amplitudes of two sine (cosine) waves of different
frequencies, i.e., pressing 5 will send a tone made by adding 1336 Hz and 770 Hz to the other
end of the mobile. The important components of this robot are DTMF decoder, Microcontroller
and motor driver. An MT8870 series DTMF decoder is used here. All types of the mt8870 series
use digital counting techniques to detect and decode all the sixteen DTMF tone pairs in to a four
bit code output. The built -in dial tone rejection circuit eliminated the
need for pre- filtering. When the input signal given at pin2 (IN-) single ended input configuration
is recognized to be effective, the correct four bit decode signal of the DTMF tone is transferred
to Q1 (pin11) through Q4(pin14) outputs.

BLOCK DIAGRAM:
CIRCUIT DIAGRAM:
COMPONENT LIST:

Sr. No. Equipment Quantity

1. IC AVR ATmega16 1
2. MT 8870 DTMF IC 1
3. CRYSTAL(3.579545mhz) 1
4. VOLTAGE REGULATOR 1
5. 2 LINE LCD DISPLAY 1
6. CRYSTAL OSCILLATOR(11.0592mhz) 1
7. DIODE 1
8. PUSH BUTTON 1
9. LEDS 1
10. RESISTER(220Ω,4.7kΩ,10kΩ) BOX 4
11. CAPACITORS(10uf,1000uf) 5
12. MOTORS 2
13. L293D 1

CONSTRUCTION AND TESTING


CONSTRUCTION
In the process of realizing this project, the construction was initially carried out on a breadboard
to allow for checking and to ascertain that it is functioning effectively. All irregularities were
checked then tested and found to have a satisfactory output. The component were then removed
and transferred to a Vero board strip and soldered into place and all discontinuous point were cut
out to avoid short-circuiting.
PRECAUTIONS
SOLDERING PRECAUTIONS
The construction was carried out with care. The precautions taken during the soldering were:
1. The tip of soldering iron was kept clean with the help of a file from time to time.

2. The solder wire was of smaller thickness.

3. Extra solder was not used in order to avoid a cause of short circuit in the conductive path.

4. The overheating of components was avoided to prevent component damage as a result of


excessive heat on the components due to the heat from the soldering iron.

5. The leads of the components were kept clean before soldering, with the use of sand
paper.

COMPONENTS PRECAUTION:
a. IR sensor used should be sensitive. Before using in the circuit it should be tested
with a multi-meter.

b. I.C should not be heated much while soldering; too much heat can destroy the I.C.
For safety and ease of replacement, the use of I.C socket is suggested.

c. While placing the I.C pin no 1 should be made sure at right hole.

d. Opposite polarity of battery can destroy I.C so please check the polarity before
switching ON the circuit.

e. One should use diode in series with switch for safety since diode allows flowing
current in one direction only.

f. Each component was soldered neatly and clean.

g. We should use insulated wires.

TESTING OF PROJECT
With the knowledge of operation of the system was tested step by step to the transistor output
and the load was connected across the collector terminal of the transistor.
ASSEMBLING
The whole system was packed in a plastic casing and provision was made for the IR to sense
light from the outside
Conclusion

We have successfully implemented the entire circuit on the PCB with obstacle detection
feature. Since all we need is a mobile call establishment to instruct the robot due to the
cell phone’s unending and cheap availability, this is highly feasible. The level of
sophistication is quite low and hence its working is user friendly. Project can also be
subjected to standardization and hence has a good future scope.
Reference

1. Schenker, L, "Pushbutton Calling with a Two-Group Voice- Frequency Code” The Bell system
technical journal, vol 14,no. 2, Jan 2006.
2. M. Ali Yousuf, R. Montúfar Chaveznava, and V. de la Cueva Cueva Hernández, "Robotic projects
to enhance student participation,motivation and learning", Hernández Current Developments in
Technology-Assisted Education ,pp 922-952, July 2008.
3. Robert Siwy, "Generation and Recognition of DTMF Signals with the Microcontroller MSP430",
Texas Instruments Deutschland,October 2005.
4. “Cell phone based land rover” Liu, Simon & Silverman, Mark. November 2009 [online] Available:
http://www.instructables.com/id/Cellphone-operated-Robot/ [accessed:Jan 2013].
5. http://www.datasheetcatalog.com/datasheets_pdf/M/T/8/8/MT8870.shtml
6. http://www.alldatasheet.com/datasheetpdf/pdf/STMICROELECTRONICS/L298.html
7. http://robosapiensindia.com/robomart/index.php?product_id=218&page=shop

You might also like