INTERRUPT
An external / internal signal appearing at some
pins of Processor / Controller
INTERRUPT
An external / internal signal appearing at some
pins of Processor / Controller
Processor / Controller suspends execution of
main program temporarily after completing the
execution of current instruction
INTERRUPT
An external / internal signal appearing at some
pins of Processor / Controller
Processor / Controller suspends execution of
main program temporarily after completing the
execution of current instruction
Processor / Controller attends the signal by
executing a subroutine.
INTERRUPT
An external / internal signal appearing at some
pins of Processor / Controller
Processor / Controller suspends execution of
main program temporarily after completing the
execution of current instruction
Processor / Controller attends the signal by
executing a subroutine.
After executing the subroutine program control
returns to main program to execute rest of the
program.
INTERRUPT
Attending signals…
By status-check method
By interrupt-driven method
INTERRUPT
Attending signals…
By status-check method
Controller checks status signal continuously
Controller is tied in a loop primarily for
checking status
INTERRUPT
Attending signals…
By status-check method
Controller checks status signal continuously
Controller is tied in a loop primarily for
checking status
May execute main program intermittently
Significant Time wasted for checking status
Writing program is relatively easy
INTERRUPT
Attending signals…
By interrupt-driven method
Controller continues executing main program
‘freely’
It goes to execute a subroutine after being
interrupted
A time-efficient program
Sometimes memory-efficient too
INTERRUPT
Interrupt signals …
Timer / Counter overflow interrupts
Timer / Counter compare match interrupts
External hardware interrupts
USART interrupts
SPI interrupts
ADC interrupts
Watchdog timer interrupt
Other interrupt types
INTERRUPT
Activation of Interrupts
Two conditions for activation…
When Interrupt signal is present
When interrupt system is enabled
INTERRUPT
Activation of Interrupts
When Interrupt signal is present:
When Interrupt Flag bits are set, μC assumes that
Interrupt signal is present.
Mode Selector bits
Oscillator
Prescaler
clock
Control
Timer Overflow Flag
External Unit
(TOV)
pulse Edge detector
Timer / Counter
Select
Timer / Counter
Control Register
Count up / down Output Compare
(TCCR)
Register (TCNT) Register (OCR)
Comparator =
Output Compare Flag
(OCF)
8-bit Timer interrupts: Timer0
OCR0A
= OCF0A
TCNT0 TOV0
= OCF0B
OCR0B
8-bit Timer interrupts: Timer2
OCR2A
= OCF2A
TCNT2 TOV2
= OCF2B
OCR2B
OCRnA 8-bit Timer interrupts: Timer0 & Timer2
= OCFnA
TCNTn TOVn
= OCFnB
n = 0, 2
OCRnB
… In general.
OCRnA 8-bit Timer interrupts: Timer0 & Timer2
Condition for enabling interrupts
= OCFnA OCIEnA = 1 I=1 OCFnA = 1
TCNTn TOVn TOIEn = 1 I=1 TOVn = 1
= OCFnB OCIEnB = 1 I=1 OCFnB = 1
n = 0, 2
OCRnB Assert through program
Global Interrupt Enable bit
SREG
I – – – – – – –
TIFRn
– – – – – OCFnB OCFnA TOVn
TIMSKn
– – – – – OCIEnB OCIEnA TOIEn
16-bit Timer interrupts: Timer 1, 3, 4, 5
TCNTnH TCNTnL TOVnA
OCRnAH OCRnAL
= OCFnA
OCRnBH OCRnBL
= OCFnB
OCRnCH OCRnCL
= OCFnC
n = 1, 3, 4, 5
16-bit Timer interrupts: Timer 1, 3, 4, 5
Condition for enabling interrupts
OCIEnA = 1 I=1 OCFnA = 1
OCIEnB = 1 I=1 OCFnB = 1 TOIEn = 1 I=1 TOVn = 1
OCIEnC = 1 I=1 OCFnC = 1
Assert through program n = 1, 3, 4, 5
Global Interrupt Enable bit
SREG
I – – – – – – –
TIFRn
– – ICFn – OCFnC OCFnB OCFnA TOVn
TIMSKn
– – ICIEn – OCIEnC OCIEnB OCIEnA TOIEn
In the main program, LED connected to PORTA.7 blinks
continuously with TON = TOFF = 300ms.
When the main program continues to run, an interrupt is
generated by Timer3 at every 1s interval. This interrupt
appears when Timer3 overflows in its normal mode. On
appearance of the interrupt PORTA.3 pin toggles and a
second LED connected to the pin blinks.
In the main program, LED connected to PORTA.7 blinks
continuously with TON = TOFF = 300ms.
When the main program continues to run, an interrupt is
generated by Timer3 at every 1s interval. This interrupt
appears when Timer3 overflows in its normal mode. On
appearance of the interrupt PORTA.3 pin toggles and a
second LED connected to the pin blinks.
White LED Red LED blinks
blinks in main in interrupt
program. routine (ISR).
In the main program, LED connected to PORTA.7 blinks
continuously with TON = TOFF = 300ms.
When the main program continues to run, an interrupt is
generated by Timer3 at every 1s interval. This interrupt
appears when Timer3 overflows in its normal mode. On
appearance of the interrupt PORTA.3 pin toggles and a
second LED connected to the pin blinks.
Loading timer with an appropriate count value to
overflow at 1s has been illustrated in the chapter of
timer-programming.
TCNT3H = 0xC2; // load timer3 with apt. count value
TCNT3L = 0xF7; // for a 1s width of astable pulse
TCCR3A = 0x00; // Timer3, Normal mode
TCCR3B = 0x05; // Timer3, 1:1024 prescalar
tutorial_16.ino
#define PA7pin 7 // PORTA.7 (pin-29 of mega 2560)
#define PA3pin 3 // PORTA.3 (pin-25 OF mega 2560)
void setup() {
DDRA |= (1<<PA7pin)|(1<<PA3pin); // PORTA.7 and PORTA.3 are
//output pins
TCNT3H = 0xC2; // load timer3 with apt. count value
TCNT3L = 0xF7; // for a 1s width of astable pulse
TCCR3A = 0x00; // Timer3, Normal mode
TCCR3B = 0x05; // Timer3, 1:1024 prescalar
TIMSK3 = (1<<TOIE3); // enable timer3 interrupt
sei(); // enable interrupts globally
}
tutorial_16.ino
void loop()
{
delay(300);
PORTA |= (1<<PA7pin); // set PA.7 pin as part of main program
delay(300);
PORTA &= ~(1<<PA7pin); // reset PA.7 pin as part of main program
}
ISR(TIMER3_OVF_vect)
{
TCNT3H = 0xC2; // again load timer3 with apt. count value
TCNT3L = 0xF7; // for a 1s width of astable pulse
PORTA ^= (1<<PA3pin); // toggle PORTA.3 pin as part of ISR
}
On board LED connected to pin-13 (PORTB.7) blinks
every 1s. This is controlled by Timer3 at interrupt driven,
normal mode with 1024 prescaler.
Another LED connected to PORTA.7 (pin-29) blinks
also. This is controlled by Timer5 at interrupt driven,
counter mode.
The counter5 receives its external pulse at its T5 pin
(pin-47). The ‘external pulse’ is generated by another pin-30
of the board (PORTC.7) in the main program.
On board LED connected to pin-13 (PORTB.7) blinks
every 1s. This is controlled by Timer3 at interrupt driven,
normal mode with 1024 prescaler.
Another LED connected to PORTA.7 (pin-29) blinks
also. This is controlled by Timer5 at interrupt driven,
counter mode.
The counter5 receives its external pulse at its T5 pin
(pin-47). The ‘external pulse’ is generated by another pin-30
of the board (PORTC.7) in the main program.
13 29 47 30
PORTC.7
PORTB.7
PORTA.7
T5
Timer3 Counter5 Main
ISR ISR Program
On board External
LED LED
13 29 47 30
PORTC.7
PORTB.7
PORTA.7
T5
Timer3 Counter5 Main
ISR ISR Program
tutorial_17.ino
#define PB7pin 7 // PORTB.7 (pin-13, in-built led) thro’ ISR of
// timer3 interrupt
#define pulsepin 7 // PORTC.7 (pin-30) to generate pulse train
// for T5 pin
#define PL2pin 2 // PORTL.2 (pin-47) as input(T5) for accepting
// counter pulse
#define PA7pin 7 // PORTA.7 (pin-29) for blinking led thro' ISR of
// timer5 interrupt
tutorial_17.ino
void setup() {
DDRB |= (1<<PB7pin); // PORTB.7 is output pin
DDRL &= ~(1<<PL2pin); // PORTL.2 pin is input
DDRA |= (1<<PA7pin); // PORTA.7 pin is output
DDRC |= (1<<pulsepin); // PORTC.7 is output
TCNT3H = (-15625)>>8; // load timer3 with apt. count value
TCNT3L = -15625; // for a 1s width of astable pulse
TCCR3A = 0x00; // Timer3, Normal mode
TCCR3B = 0x05; // Timer3, 1:1024 prescalar
TCNT5H = 0xFD; // set count for overflow after that much count
TCNT5L = 0x44; //
TCCR5A = 0x00; // Timer5, output clock source
TCCR5B = 0x06; // Timer5, counter mode on T5 pin
tutorial_17.ino
TIMSK3 = (1<<TOIE3); // enable timer3 interrupt
TIMSK5 = (1<<TOIE5); // enable timer5 interrupt
sei(); // enable interrupts globally
delay(1);
}
tutorial_17.ino
void loop()
{
delay(1);
PORTC |= (1<<pulsepin); // set PC.7 pin as part of main program
delay(1);
PORTC &= ~(1<<pulsepin); // reset PC.7 pin as part of main program
}
tutorial_17.ino
ISR(TIMER3_OVF_vect)
{
TCNT3H = (-15625)>>8; // again load timer3 with apt. count value
TCNT3L = -15625; // for a 1s width of astable pulse
PORTB ^= (1<<PB7pin); // toggle PORTB.7 pin as part of ISR
}
ISR(TIMER5_OVF_vect)
{
TCNT5H = 0xFD; // set count for overflow after that much count
TCNT5L = 0x44;
PORTA ^= (1<<PA7pin); // toggle PORTA.7 pin as part of ISR
}
External Interrupt can be received through 8-pins:
External Interrupt can be enabled by use of External
Interrupt Mask (EIMSK) register and I-bit.
Global Interrupt Enable bit
SREG
I – – – – – – –
EIMSK
INT7 INT6 INT5 INT4 INT3 INT2 INT1 INT0
INTn = 1 : Ext. Interrupt Enabled.
n = 0 to 7
INTn = 0 : Ext. Interrupt Masked.
Type of interrupt signal is decided by EICRA and
EICRB.
(External Interrupt Control Register)
EICRA
ISC31 ISC30 ISC21 ISC20 ISC11 ISC10 ISC01 ISC00
Pulses longer than one clock period will generate an interrupt
asynchronously. For low level interrupt, the low level must be held
until the completion of the currently executing instruction to
generate an interrupt.
Type of interrupt is decided by EICRA and
EICRB.
(External Interrupt Control Register)
EICRB
ISC71 ISC70 ISC61 ISC60 ISC51 ISC50 ISC41 ISC40
Pulses longer than one clock period will generate an interrupt. For
low level interrupt, the low level must be held until the completion
of the currently executing instruction to generate an interrupt.
On reception of a valid interrupt request, corresponding
flag in EIFR is set.
(External Interrupt Flag Register)
EIFR
INTF7 INTF6 INTF5 INTF4 INTF3 INTF2 INTF1 INTF0
The flag is cleared automatically when the interrupt routine for
edge-triggered or change-triggered interrupt is executed.
The flag must be cleared by writing a 1 to it for level-triggered
interrupt.
Arduino
Signal ATmega Mega 2560
name 2560 pin pin
INT0 – PD0 – 21 (SCL)
INT1 – PD1 – 20 (SDA)
INT2 – PD2 – 19 (RX1)
INT3 – PD3 – 18 (TX1)
INT4 – PE4 – 2 (PWM)
INT5 – PE5 – 3 (PWM)
INT6 – PE6 –
INT7 – PE7 –
Within main program, LED at pin-13 blinks.
After detecting an external interrupt at INT4 on any edge,
the LEDs connected to PORTA blinks.
Within main program, LED at pin-13 blinks.
After detecting an external interrupt at INT4 on any edge,
the LEDs connected to PORTA blinks.
Board-1: Pin-
PL6
Mega 2560 43
GND
13 2
PORTB.7
PE.4 (INT4)
(Pins- 22 to 29)
Main Main PORTA
GND Program Program pins
Board-2:
Mega 2560
Within main program, LED at pin-13 blinks.
After detecting an external interrupt at INT4 on any edge,
the LEDs connected to PORTA blinks.
Board-1: Pin-
PL6
Mega 2560 43
GND
13 2
PORTB.7
PE.4 (INT4)
(Pins- 22 to 29)
Main Main PORTA
GND Program Program pins
Board-2:
Mega 2560
tutorial_15A.ino
#define PL6pin 6 // PORTL.6 (pin-43 OF MEGA 2560) is used to
// generate pulse train
void setup() {
DDRL |= (1<<PL6pin); // PORTL.6 pin (pin-43 of mega 2560) as
output
}
Sketch for board-1
void loop()
{
delay(250);
PORTL |= (1<<PL6pin); // set PL.6 pin
delay(250);
PORTL &= ~(1<<PL6pin); // reset PL.6 pin
}
Sketch for board-2
tutorial_18.ino
#define togpin 7 // PORTB.7 (pin-13 of board, in-built led)
#define INT4pin 4 // PORTE.4, i.e., INT2 pin (pin-2 of board)
void setup() {
DDRB |= (1<<togpin); // PORTB.7 is output pin
DDRA |= 0xFF; // PORTA is output
DDRE |= ~(1<<INT4pin); // PORTE.4, i.e., INT4 (pin-2) as input
EICRB = 0x01; // INT4, triggered on any edge
EIMSK = (1<<INT4); // enable only INT4
}
Sketch for board-2
tutorial_18.ino
void loop()
{
delay(500);
PORTB |= (1<<togpin); // set PB.7 (DIGITAL PIN-13) as part of
main program
delay(500);
PORTB &= ~(1<<togpin); // reset PB.7 as part of main program
}
ISR(INT4_vect)
{
PORTA ^= 0xFF; // toggle all the pins of PORTA
}
Register: ADC interrupt enable
(1) When a ‘1’ is written to this bit and the I-bit in SREG is set, the ADC
Conversion Complete Interrupt is activated.
10 ADCH:ADCL
Conversion
ADEN ADIF complete
ADSC IRQ
ADIE
ADC interrupt flag
(2) This bit is set when an ADC conversion completes and the Data Registers
are updated.
(3) ADIF is cleared by hardware on execution of the corresponding interrupt
handling vector.
10 ADCH:ADCL
Conversion
ADEN ADIF complete
ADSC IRQ
ADIE
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
ADC prescaler select bits
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
ADC prescaler select bits
On-board clock, XTAL = 16MHz.
XTAL/prescaler = 16MHz/prescaler = 125kHz.
Hence, prescaler = 16MHz/125kHz = 128.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1:
Step-2:
ADC prescaler select bits
1 1 1
Hence, prescaler = 16MHz/125kHz = 128.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
0 0 0 0 0
0
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Step-4: For right-justified data output, ADLAR = 0.
0
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Step-4: For right-justified data output, ADLAR = 0.
Step-5: Use 5V as reference.
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-4:
Step-3: Select input channel, here ADC0.
For right-justified data output, ADLAR = 0.
Step-5: Use 5V as reference.
0 1
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Step-4: For right-justified data output, ADLAR = 0.
Step-5: Use 5V as reference.
Step-6: To enable ADC, ADEN =1. To start conversion, ADSC = 1.
1 1/0
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Step-1: Make PF0 pin as input pin since it acts as ADC0.
Step-2: Configure ADC clock at 125kHz.
Step-3: Select input channel, here ADC0.
Step-4: For right-justified data output, ADLAR = 0.
Step-5: Use 5V as reference.
Step-6: To enable ADC, ADEN =1. To start conversion, ADSC = 1.
Step-7: To enable ADC interrupt, assert ADIE = 1.
1
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
Finally:
1 0 0 0 1 1 1 1 = 0x8F
0 0 0 0 0 0 0 0 = 0x00
0 1 0 0 0 0 0 0 = 0x40
Use channel-0 of ATmega2560 to receive analog data and
send it continuously to serial monitor. The data should be
right-justified. Use 5V as reference and configure ADC clock
at 125kHz. ADC needs to be set in interrupt driven mode.
Estimate conversion time using appropriate in-built
functions as available.
To activate ADC conversion complete interrupt,
make I = 1 in SREG
by using a compiler-supported command:
sei();
volatile int adc_val; tutorial_21.ino
volatile uint8_t low, high;
volatile unsigned char ti = 0;
volatile unsigned char tc;
void setup() { tutorial_21.ino
DDRF = 0; // ADC0(PF0) is input for ADC pins to receive data
ADCSRA = 0;
sei(); // enable interrupts
ADCSRA = 0x8F; // ADC clock = XTAL/128 = 16MHz/128 =
// 125KHz, ADIE = 1.
ADCSRB = 0x00;
ADMUX = 0x40; // VCC (5V) as Vref., ADC0 as single-ended input
// data will be right-justified
ADCSRA |= (1<<ADSC); // start conversion
Serial.begin(9600);
}
void loop()
{
}
tutorial_21.ino
ISR(ADC_vect)
{
low = ADCL;
high = ADCH; // ADCH(1) and ADCH(0) are the 9th and
// 10th bits of adc value, that are
adc_val = (high << 8)|low; // combined with the lower byte of adc
// value stored in ADCL
ADCSRA |= (1<<ADSC); // start conversion
tc = micros()-ti; // conversion time of adc
Serial.print("ADC value = ");
Serial.print(adc_val);
Serial.print(", conversion time = ");
Serial.print(tc);
Serial.println("us");
ti = micros();
}
tutorial_21.ino
ISR(ADC_vect)
{
low = ADCL;
high = ADCH; // ADCH(1) and ADCH(0) are the 9th and
// 10th bits of adc value, that are
adc_val = (high << 8)|low; // combined with the lower byte of adc
// value stored in ADCL
ADCSRA |= (1<<ADSC); // start conversion
tc = micros()-ti; // conversion time of adc
Serial.print("ADC value = ");
Serial.print(adc_val);
Serial.print(", conversion time = ");
Serial.print(tc);
Serial.println("us");
ti = micros();
}
tutorial_21.ino
NOTE:
Conversion time of
ADC is only 16μs.
This is much less
than the previous
program where
conversion time was
about 110μs.
Same program in an
alternate (compact) way …
void setup() { tutorial_21.ino
DDRF = 0; // PORTF is input for ADC pins to receive data
// although all the pins are not used here
ADCSRA = 0x8F; // ADC clock = XTAL/128 = 16MHz/128 =
// 125KHz, ADIE =1
sei();
ADCSRB = 0x00;
ADMUX |= 0x40; // VCC (5V) as Vref., ADC0 as single-ended input
// data will be right-justified
Serial.begin(9600);
}
void setup() { tutorial_22.ino
DDRF = 0;
ADCSRA = 0;
sei();
ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADIE);
// this is equivalent to 0x87
ADCSRB = 0x00;
ADMUX |= (1<<REFS0); // this is equivalent to 0x40
Serial.begin(9600);
}