You are on page 1of 44

Atmega16 Interrupts

AVR Lecture 3
Interrupts
Atmega16 has 3 external interrupts and 17 internal
interrupts

Interrupt Vector Table


For every interrupt there is a Interrupt service routine or
Interrupt Handler
For every interrupt there is a fixed location in memory
that holds the address of its ISR
The group of memory locations set aside to hold the
addresses of ISR is called interrupt vector table
The complete list of vectors is shown in a table on next
slide

More Details on Page 11 and Page 42 of Datasheet


@ Dr Javaid, M.H Fidai 2 / 50
3 / 50
Atmega16 Interrupt Pins

@ Dr Javaid, M.H Fidai 4 / 50


Interrupt Enabling
Enable global interrupt bit
Enable local interrupt bit
Mode selection, edge trigger etc
Interrupt Flags

@ Dr Javaid, M.H Fidai 5 / 50


Registers Associated with Interrupts
Status Register - (SREG) [Enable global int]
General Interrupt Control Register GICR [Enable local int]
MCU Control Register - (MCUCR) [Interrupt Sense Control
0,1 (mode selection, edge trigger etc)]

@ Dr Javaid, M.H Fidai 6 / 50


Registers Associated with Interrupts
MCU Control and Status Register MCUCSR
[ Int Sense control 2, (mode selection, edge trigger etc)]

General Interrupt Flag Register GIFR

@ Dr Javaid, M.H Fidai 7 / 50


Programming Steps:
For programming an interrupt, the following steps must
be followed:
Initialize the interrupt by appropriately configuring
the MCUCR, MCUCSR and GICR registers.
Clear Interrupt Flags in GIFR register

Set Global Interrupt Enable bit in SREG register.

Define the appropriate Interrupt Service Routine


(ISR) for the interrupt. e.g. ISR for INT0 can be
written as follows:
ISR (INT0_vect)
{
}
@ Dr Javaid, M.H Fidai 8 / 50
Steps in Executing an interrupt
It finishes the instruction it is currently executing and
saves the address of the next instruction on the stack
It jumps to the fix location in memory called the interrupt
vector table. The interrupt vector table directs
microcontroller to the address of interrupt service routine
(ISR).
The microcontroller starts to execute the interrupt service
routine until it reaches the last instruction of the
subroutine, which is return from interrupt
Upon execution of return from interrupt instruction, the
microcontroller returns to the place where it was
interrupted. First it gets the program address from the
stack. Then it starts to execute that address
More Details on Page 11 and Page 42 of Datasheet
@ Dr Javaid, M.H Fidai 9 / 50
Role of Status Register (SREG)
Upon reset, all interrupts are disabled (masked)
The interrupts will be enabled (unmasked) by the software.
The bit D7(I-bit) of the SREG (Status Register) register is
responsible for enabling and disabling the interrupts
globally.
If I-bit = 1, each interrupt is enabled by setting to HIGH the
interrupt enable bit for that interrupt

@ Dr Javaid, M.H Fidai 10 / 50


Interrupt Priority (interrupts occur in same cycle)
If the two interrupts occur at the same time (same cycle)
than the one with the higher priority (as per polling
sequence) is served first
The priority of each interrupt is related to its address in
interrupt vector table
The interrupt which has a lower address has a higher
priority

More Details on Page 11 and Page 42 of Datasheet


@ Dr Javaid, M.H Fidai 11 / 50
Polling Sequence

12 / 50
External Interrupts
The External Interrupts are triggered by the INT0 (PD2),
INT1(PD3), and INT2 (PB2) pins

INT0 and INT1


The external interrupts can be triggered by a falling or
rising edge or any logical change or a low level

INT2
It is only edge triggered

More Details on Page 64 of Datasheet


@ Dr Javaid, M.H Fidai 13 / 50
External Interrupts Registers
MCU Control Register (MCUCR)
Last four bits of this register controls the mode of external interrupt 0
and 1

Bit 3, 2 ISC11, ISC10: Interrupt Sense Control 1 Bit 1 and


Bit 0 (Interrupt 1 Sense control)

More Details on Page 64 of Datasheet


@ Dr Javaid, M.H Fidai 17 / 50
External Interrupts Registers
Bit 1, 0 ISC01, ISC00: Interrupt Sense Control 0 Bit
1 and Bit 0 (Interrupt 0 sense control)

@ Dr Javaid, M.H Fidai 18 / 50


External Interrupts Registers
MCU Control and Status Register MCUCSR
Bit-6 of this register controls the mode of interrupt 2

If ISC2 is written to zero, a falling edge on INT2 activates the


interrupt
If ISC2 is written to one, a rising edge on INT2 activates the
interrupt

@ Dr Javaid, M.H Fidai 19 / 50


External Interrupts Registers
For Interrupt 0
Set the SREG bit-I
Set the INT0 pin of GICR
Select its mode by setting bits ICS01 and ICS00
of MCUCR accordingly
For Interrupt 1
Set the SREG bit-I
Set the INT1 pin of GICR
Select its mode by setting bits ICS11 and ICS10
of MCUCR accordingly

@ Dr Javaid, M.H Fidai 20 / 50


External Interrupts Registers
For Interrupt 2
Set the SREG bit-I
Set the INT2 pin of GICR
Select its mode by setting bit ISC2 of MCUCSR
accordingly

@ Dr Javaid, M.H Fidai 21 / 50


External Interrupts Flags Register
General Interrupt Flag Register GIFR

Bit 7 INTF1: External Interrupt Flag 1


When an edge or logic change 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

@ Dr Javaid, M.H Fidai 22 / 50


External Interrupts Flags Register
Bit 6 INTF0: External Interrupt Flag 0
When an edge or logic change on the INT0 pin triggers an interrupt
request, INTF0 becomes set (one)
If the I-bit in SREG and the INT0 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

@ Dr Javaid, M.H Fidai 23 / 50


External Interrupts Flags Register
Bit 5 INTF2: External Interrupt Flag 2
When a rising or falling edge on the INT2 pin triggers an interrupt
request, INTF2 becomes set (one)
If the I-bit in SREG and the INT2 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

@ Dr Javaid, M.H Fidai 24 / 50


Important
The interrupts will trigger even if the interrupt pins are
configured as OUTPUT (This feature provides a way of
generating a software interrupt)

The Flag of an interrupt can be cleared by writing


Logic One to it.

@ Dr Javaid, M.H Fidai 25 / 50


Interrupt Flag Bit
Flag Bit (GIFR) Value to be written Result
0 1 0
1 1 0
0 0 0
1 0 1

@ Dr Javaid, M.H Fidai 26 / 50


Interrupts Programming in C
Interrupt Include file
Interrupt header file should be included if we want to
use an interrupt in our program. Following command is
used
#include<avr/interrupt.h>

cli() and sei() clearint() setupint()


Since for enabling an interrupt we need to enable I-bit
in SREG. And AVR GCC/WinAVR does not allow us to
access a bit, so to clear or set I-bit either we have to use
bit wise AND(&) or (|) operator or we can use the cli() and
sei() macros to do the same task

@ Dr Javaid, M.H Fidai 27 / 50


Interrupts Programming in C
Defining ISR
To write an ISR for an interrupt we use the following
structure:
ISR(interrupt vector name)
{
// user code here
}

For interrupt vector name use the ISR names given in the
table on next slides; for example for external interrupt0
ISR(INT0_vect)
{
}
@ Dr Javaid, M.H Fidai 28 / 50
Vector Names for WinAVR(AVR GCC)
External interrupt 0 INT0_vect
External interrupt 1 INT1_vect
External interrupt 2 INT2_vect
ADC Conversion Complete ADC_vect
Analog Comparator ANA_COMP_vect
Serial Transfer Complete SPI_STC_vect
Store Program Memory Ready SPM_RDY_vect
Timer/Counter0 Compare Match TIMER0_COMP_vect
Timer/Counter0 Overflow TIMER0_OVF_vect
Timer/Counter Capture Event TIMER1_CAPT_vect
Timer/Counter1 Compare Match A TIMER1_COMPA_vect
Timer/Counter1 Compare MatchB TIMER1_COMPB_vect
Timer/Counter1 Overflow TIMER1_OVF_vect

Complete table available at : http://www.nongnu.org/avr-libc/user-


manual/group__avr__interrupts.html
@ Dr Javaid, M.H Fidai 29 / 50
Example
Write a program which
Displays the value of a variable x on PORT A,

Initial value of x=0

Value of variable x increments whenever there is a high to


low pulse on pin INT1

@ Dr Javaid, M.H Fidai 30 / 50


Example
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char x=0;
void main()
{ DDRA =0xFF; //Configures port A as output
DDRD &=0b11110111; //configure bit4 of port D as input
MCUCR |=(0<<ISC10 | 1<<ISC11); //selecting mode of interrupt 1
GIFR |=0b10000000; // Clear Int Flag
GICR |=0b10000000; //Enabling Interrupt 1 Either one of
sei(); //or these could be
//SREG=SREG|0b10000000; //Enabling Global Interrupt used to
while(1) enable I-bit
{
PORTA=x; //continuously outputs x
}
}
ISR(INT1_vect)
{ x++;
Int_inc_x.c
}
Int.isis
@ Dr Javaid, M.H Fidai 31 / 50
Example
Assume that the INT0 pin is connected to a switch that is
normally high. Write a program that toggles PORTC.3,
whenever there is any change in INT0. Use the external
Interrupt pin in any logical change.
int main(void)
{
DDRC=1<<3; //Configures port C.3 as output
MCUCR|=(1<<ISC00 | 0<<ISC01); //selecting mode ; Any logical Change
GICR|=1<<INT0; //Enabling Interrupt 0
GIFR|=1<<6; //Clearing flags of INT0
sei();
while(1);
}

ISR(INT0_vect)
{ PORTC ^=1<<3;
}
AVR_ex_10.9.c
Int. isis
@ Dr Javaid, M.H Fidai 32 / 50
Interrupt within Interrupt
When an interrupt occurs, the Global Interrupt Enable
I-bit is cleared hence no other interrupt will interrupt this
ISR.
The I-bit is automatically set when a Return from
Interrupt instruction is executed
While executing an ISR if any interrupt occurs it will be
latched since I-bit is disabled and will be served after
completion of current ISR
If more than one interrupt occurs during an ISR, they will
be served according to the Polling sequence.

Int_nested.c
More Details on Page 11 and Page 42 of Datasheet Case 1
@ Dr Javaid, M.H Fidai 33 / 50
Nested Interrupts
What will happen if we set I bit of SREG in ISR ?
This will allow all enabled interrupts to interrupt this ISR.
If the I bit of SREG is set in an ISR and another interrupt
occurs, the controller will finish the currently executing
instruction and then serve the interrupt that occurs. After
serving that interrupt it will return to this ISR.
Since this ISR can be interrupted by all other enabled
interrupts, this interrupt has lower priority in comparison
to the other interrupts. But this priority is user defined and
depends on the users preferences.

Int_nested.c
More Details on Page 11 and Page 42 of Datasheet Case 2
@ Dr Javaid, M.H Fidai 34 / 50
Can interrupts occur while I bit of SREG
is disabled?
Interrupts events (that is, noticing the event) can occur at
any time, and most are remembered by setting an "interrupt
event" flag (GICR, local int enable) inside the processor. If
interrupts are disabled (SREG, global int enable), then that
interrupt will be handled when they are enabled again, in
priority order (polling sequence).
while(1)
{ PORTB=0;
PORTD=0;
cli(); // Disables Interrupt
PORTD=0x04; // calling INT 0
x++;
x++;
sei(); // Enables Interrupt
x++;
Int_nested.c
} Case 3
@ Dr Javaid, M.H Fidai 38 / 50
Arduino Interrupt Functions
External Interrupts
attachInterrupt()
detachInterrupt()
Interrupts
interrupts() -> sei() [SEt Interrupt ]
noInterrupts() -> cli() [CLear Interrupt]

@ Dr Javaid, M.H Fidai 39 / 50


Arduino - Interrupt
attachInterrupt (interrupt, ISR_name, mode)

interrupt The number of the interrupt (int) (0 1 2 )


ISR_name The ISR to call when the interrupt occurs; this function must take
no parameters and return nothing. This function is sometimes
referred to as an interrupt service routine.

Mode Defines when the interrupt should be triggered. Four constants are
predefined as valid values:
LOW to trigger the interrupt whenever the pin is low,
CHANGE to trigger the interrupt whenever the pin changes value
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.

@ Dr Javaid, M.H Fidai 40 / 50


Example

@ Dr Javaid, M.H Fidai 41 / 50


Example
int pin = 13;
volatile int state = LOW;

void setup()
{ pinMode ( pin, OUTPUT);
attachInterrupt (0, blink, CHANGE);
}

void loop()
{ digitalWrite (pin, state);
}

void blink()
{ state = !state;
}

@ Dr Javaid, M.H Fidai 42 / 50


Volatile Keyword
Volatile is a keyword known as a variable qualifier, it is usually used
before the datatype of a variable, to modify the way in which the
compiler and subsequent program treats the variable.
Declaring a variable volatile is a directive to the compiler. The
compiler is software which translates your C/C++ code into the
machine code, which are the real instructions for the Atmega chip in
the Arduino.
Specifically, it directs the compiler to load the variable from RAM
and not from a storage register, which is a temporary memory
location where program variables are stored and manipulated.
Under certain conditions, the value for a variable stored in registers
can be inaccurate.
A variable should be declared volatile whenever its value can be
changed by something beyond the control of the code section in
which it appears, such as a concurrently executing thread. In the
Arduino, the only place that this is likely to occur is in sections of
code associated with interrupts, called an interrupt service routine.

@ Dr Javaid, M.H Fidai 43 / 50


Volatile
The volatile keyword acts as a data type qualifier.
The qualifier alters the default way in which the compiler
handles the variable and does not attempt to optimize
the storage referenced by it.
Example:
lsb = *handle->baseAddr;
middle = *handle->baseAddr;

msb = *handle->baseAddr;
Between reads, the bytes are changed in the latch.
Without the volatile, the compiler optimizes this to a
single assignment:

lsb = middle = msb = *handle->baseAddr;

@ Dr Javaid, M.H Fidai 44 / 50


Example

Optimized + without volatile

@ Dr Javaid, M.H Fidai Optimized + volatile 46 / 50


Volatile
A variable should be declared volatile whenever its value
could change unexpectedly:
Memory-mapped peripheral registers

The above is an example where the user waits for the status register to
become non-zero. To the right is the code, that is produced by the
compiler with optimization turned on. The logic of the optimizer is simple:
having already read the variable's value into the accumulator (on the
second line of assembly), there is no need to reread it, since the value
will always be the same. Thus, in the third line, we end up with an infinite
loop. To force the compiler to do what we want, we modify the
declaration as follows:

@ Dr Javaid, M.H Fidai 47 / 50


Volatile
Global variables modified by
an interrupt service routine
The problem is that the compiler has
no idea that etx_rcvd can be changed
within an ISR. As far as the compiler
is concerned, the expression
!ext_rcvd is always true, and,
therefore, you can never exit the while
loop. Consequently, all the code after
the while loop may simply be removed
by the optimizer. If you are lucky, your
compiler will warn you about this.

@ Dr Javaid, M.H Fidai 48 / 50


Volatile: Example
#include <avr/io.h> ISR(INT1_vect)
#include<avr/interrupt.h> {
volatile int timer = 0; timer++; // add 1 to timer
uint32_t endtime;
}
int main(void)
{ void delay_ms(int ms)
GICR=0b10000000; {
//Enabling Interrupt 1 endtime = timer + ms;
MCUCR=(1<<ISC10|0<<ISC11);
//selecting mode of interrupt 1 while(timer < endtime)
SREG=SREG|0b10000000; { DDRA=0xff;
//Enabling Global Interrupt PORTA=timer;
while(1) PORTA=timer;
{ PORTA=timer;
delay_ms(1); // wait for 10ms
} PORTA=timer;
} }
}
Volatile_var.c
@ Dr Javaid, M.H Fidai 49 / 50
detachInterrupt()
Description
Turns off the given interrupt.

Syntax
detachInterrupt (interrupt)

Parameters
Interrupt:- The number of the interrupt to disable

@ Dr Javaid, M.H Fidai 50 / 50


noInterrupts() and interrupt()
noInterrupt() -> Disables interrupts (you can re-
enable them with interrupts()).

void setup() {}

void loop()
{ noInterrupts();
// critical, time-sensitive code here
interrupts();
// other code here
}

@ Dr Javaid, M.H Fidai 51 / 50