Working with External Interrupts in AVR micro controller

Mathew Kevin July 10, 2017 3 Comments

Introduction to Interrupts

                Although micro controllers can accept inputs from Digital I/O Ports,interrupts are preferred for accepting inputs generated by external events. This is mainly because of the less attention required for an interrupt based program. An Interrupt Event directs the flow of program execution to a totally independent piece of code, known as “Interrupt Sub-Routine”. There are many sources of Interrupts that are available for a micro controller. Most of them are generated by the internal modules and are known as internal interrupts. And there are two pins that accept external signals directly and allows external sources to generate interrupts.

Note:- You can read a detailed article about Interrupts in 8051 microcontroller here:-

                For an interrupt subroutine to be executed, following requirements are necessary

  • The particular interrupt source must be activated by setting the corresponding Interrupt Mask/Interrupt Enable Bit.
  • The Interrupt sub routine must exist. If there are no codes to be executed, then an Empty Subroutine must occur at the particular memory space allocated to that Interrupt.
  • The Interrupt Enable flag bit in the AVR Status register (SREG) must be set (=1). For this, there is an instruction named ‘sei’ (Set Interrupt Enable). In AVR Studio, there is a function named “sei()”. This function must be called in order to enable the Execution of interrupt sub routine.
  • Finally the event must occur, so that the execution of the routine gets triggered.

There is another instruction called “cli” (AVR studio includes a C Function [cli()]) that disables the execution of any subroutine by resetting the Interrupt Enable Flag.

AVR Studio includes “avr/interrupt.h” header file that takes care of the interrupt sub routines and makes it simpler to integrate into the C code. You can Find more about the Header file at its online documentation available at the GNU website.

Writing an Interrupt Sub Routine in AVR Studio

                It’s a bit tricky to include an interrupt subroutine into the C code of a micro controller, a bit complex for beginners. So the AVR GCC developers has declared a few symbols to represent interrupts and macros that shortened the code size in many programs. The Symbol lists and macros are listed in the online document. Here we are supposed to write the Interrupt subroutine for External Interrupt 0 and external interrupt 1. The code will look  something like this:

// Interrupt sub routine code starts
ISR(INT0_vect)
{
// Code for interrupt 0
}
ISR(INT1_vect)
{
// Code for interrupt 1
}
// Interrupt Subroutine Code Ends


                And for the part of the code that would enable interrupts, we would be using “sei()” function.

Registers Associated with External Interrupts

MCU Control Register– MCUCR

Bit

7

6

5

4

3

2

1

0

Bit Name SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00
Read/Write

RW

RW

RW

RW

RW

RW

RW

RW

Initial value

0

0

0

0

0

0

0

0


ISC11, ISC10, ISC01, ISC00: Interrupt Sense Control Bit 1 and Bit 0 for interrupt 1 and interrupt 0

The External Interrupt 1 is activated by the external pin INT1, if the SREG I-bit and the corresponding interrupt mask in the GICR are set. The level and edges on the external INT1 pin that activate the interrupt are defined in table below. The value at the INT1 pin is sampled before detecting edges. If edge or toggle interrupt is selected, pulses that last longer than one clock period will generate an interrupt. Shorter pulses are not guaranteed to generate an interrupt. If low level interrupt is selected, the low level must be held until the completion of the currently executing instruction to generate an interrupt.

Interrupt Sense Control

ISCx1

ISCx0

Interrupt Generated Upon

0

0

The low Level of INTx pin

0

1

Any logical change in INTx pin

1

0

Falling edge of INTx

1

1

Rising edge of INTx
x- Interrupt number, either 0 or 1

The other bit’s in this register is irrelevant to this discussion. The upper four bits of this register is used for CPU sleep mode control.

General Interrupt Control Register – GICR

Bit

7

6

5

4

3

2

1

0

Bit Name

INT1

INT0

IVSEL

IVCE

Read/Write

RW

RW

RW

RW

RW

RW

RW

RW

Initial value

0

0

0

0

0

0

0

0

Bit 7 – INTF1: External Interrupt Flag 1
When an event on the INT1 pin triggers an interrupt request, INTF1 becomes set (one). If the I-bit in SREG and the INT1 bit in GICR are set (one), the MCU will jump to the corresponding Interrupt Vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared when INT1 is configured as a level interrupt.

Bit 6– INTF1: External Interrupt Flag 0

The function of this bit is similar to that o the previous. But it is associated with INT0.

Code

#include
#include

ISR(INT0_vect)
{
PORTB &=0xfe;
}

ISR(INT1_vect)
{
PORTB |=0x01;
}

void initInterrupt()
{
GICR =(1≪INT1)|(1≪INT0);
MCUCR() =(1≪ISC01)|(1≪ISC11);
sei();
}

int main()
{
DDRB=0xff;
initInterrupt();
while(1);
return 1;
}

Circuit Diagram

View PDF Working With External Interrupts
Picture: Circuit Diagram

 

Comments
  • rakesh
    August 7, 2012

    typo, bugs, critics, suggestion…. don’t hesitate. Express your opinion…

    • Shajahan
      June 26, 2013

      I want the source in Assembler.

      I am trying to write the ISRs using .ORG directive, but i am getting some errors in Proteus Simulator

Leave a Reply to rakesh Cancel reply

Your email address will not be published. Required fields are marked *