0% found this document useful (0 votes)
4 views

5. Interrupt Programming in C

interrupts in C

Uploaded by

Schwarz Chimunhu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

5. Interrupt Programming in C

interrupts in C

Uploaded by

Schwarz Chimunhu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Interrupt Programming in

1
1. Enabling and Disabling Interrupts
• Upon microcontroller reset, all interrupts are disabled (masked) – no interrupt will
be responded to even if it is activated
• Interrupts must be enabled (unmasked) by software for the microcontroller to
respond to them
• The D7 (Global Interrupt Enable) bit of SREG (Status Register) (0x005F data memory
address or 0x003F standard I/O register address), shown below, is responsible for
globally enabling/disabling interrupts:

• D7 (I) bit of SREG must be HIGH to enable interrupts


• If I = 1, a specific interrupt can be enabled by setting HIGH its Interrupt Enable (IE)
bit
• There are some I/O registers holding Interrupt Enable (IE) bits
2
2. Interrupt Programming in C
• Include the interrupt header file in order to use interrupts in a program, i.e.,
#include <avr/interrupt.h>
• Use cli() and sei() to clear and set the I bit of SREG, respectively
• To write an ISR for an interrupt, use:
ISR (interrupt vector name)
{
//program
}

3
• Interrupt vector names for ATmega328P in Atmel Studio are shown below:
Interrupt Vector Name in Atmel Studio
External Interrupt Request 0 INT0_vect
External Interrupt Request 1 INT1_vect
Pin Change Interrupt Request 0 PCINT0_vect
Pin Change Interrupt Request 1 PCINT1_vect
Pin Change Interrupt Request 2 PCINT2_vect
Watchdog Time-out Interrupt WDT_vect
Timer2/Counter2 Compare Match A TIMER2_COMPA_vect
Timer2/Counter2 Compare Match B TIMER2_COMPB_vect
Timer2/Counter2 Overflow TIMER2_OVF_vect
Timer1/Counter1 Capture Event TIMER1_CAPT_vect
Timer1/Counter1 Compare Match A TIMER1_COMPA_vect
Timer1/Counter1 Compare Match B TIMER1_COMPB_vect
Timer1/Counter1 Overflow TIMER1_OVF_vect
Timer0/Counter0 Compare Match A TIMER0_COMPA_vect
Timer0/Counter0 Compare Match B TIMER0_COMPB_vect
Timer0/Counter0 Overflow TIMER0_OVF_vect
SPI Transfer Complete SPI_STC_vect
USART Receive Complete USART_RX_vect
USART Data Register Empty USART_UDRE_vect
USART Transmit Complete USART_TX_vect
ADC Conversion Complete ADC_vect
EEPROM Ready EE_READY_vect
Analog Comparator ANALOG_COMP_vect
Two-wire Serial Interface TWI_vect
Store Program Memory Ready SPM_READY_vect 4
3. External Interrupts INT0 and INT1
• The Atmega328P has two external hardware interrupts: pins PD2 (INT0) and PD3
(INT1)
• An external hardware interrupt is enabled by a 1 and disabled by a 0 on INTx bit
in External Interrupt Mask Register (EIMSK) (0x003D data memory address or
0x001D standard I/O register address), shown below:

• When I-bit in SREG and INTx-bit in EIMSK register are set, activity on the INTx pin
(even if configured as an output) will cause an interrupt request and the
microcontroller will jump to INTx interrupt vector to perform the ISR
• The interrupt vectors for INT0 and INT1 are located in ROM location addresses
0002 and 0004, respectively

5
Level-triggered vs. Edge-triggered Interrupts
• There are two types of activation for external hardware interrupts: (1) level-
triggered and (2) edge-triggered
• The bits of the External Interrupt Control Register A (EICRA) (0x0069 Extended I/O
memory address), shown below, indicate the trigger options of INT0 and INT1:

• EICRA contains control bits for interrupt sense control (ISC)


INT0 Interrupt Sense Control

6
INT1 Interrupt Sense Control

External Interrupt Flags


• When INTx is configured as an edge-triggered interrupt (falling edge, rising edge
or level change), when an interrupt is triggered, a related INTFx bit is set in
External Interrupt Flag Register (EIFR) (0x003C data memory address or 0x001C
standard I/O register address), shown below:

7
• The INTFx flag is automatically cleared when the interrupt service routine is
executed
• When INTx is configured as a level-triggered interrupt, the interrupt flag INTFx is
always cleared (it remains unchanged when an interrupt occurs)

Example 1
Assume that INT0 pin is connected to a switch that is normally high. Write a
program that toggles PORTB.5 whenever the INT0 pin goes low. Use the interrupt in
level-triggered mode.

8
Solution:
#include <avr/io.h>
#include <avr/interrupt.h>
int main()
{
DDRB = 1 << 5; //set PB5 as an output pin
PORTD = 1 << 2; //activate pull-up resistor
EIMSK = 1 << INT0; //enable external hardware interrupt INT0
sei(); //enable global interrupts
while(1); //wait here or you could be doing some other activity
}
ISR (INT0_vect)
{
PORTB ^= 1 << 5;
}
9
Example 2
Rewrite Example 1 so that whenever INT0 goes low, it toggles PORTB.5 only once.
Solution:
#include <avr/io.h>
#include <avr/interrupt.h>
int main()
{
DDRB = 1 << 5; //set PB5 as an output pin
PORTD = 1 << 2; //activate pull-up resistor
EICRA = 0x02; //Make INT0 falling edge-triggered
EIMSK = 1 << INT0; //enable external hardware interrupt INT0
sei(); //enable global interrupts
while(1); //wait here or you could be doing some other activity
}
ISR (INT0_vect)
{
PORTB ^= 1 << 5;
}
10
4. Pin Change Interrupts
• In ATmega328P, there is a pin change interrupt for each port
• If the pin change interrupt of a port is enabled, any change on any pin of that port
raises an interrupt
• The Pin Change Interrupt Controller Register (PCICR) (0x0068 data memory
address), shown below, contains enable bits for the ports:

• PCIE0: Pin Change Interrupt Enable bit for PORTB (0: disable; 1: enable)
 A logic change on any enabled PCINT7 – PCINT0 (connected to PORTB) triggers an interrupt (Pin
Change Interrupt Request 0)
 The microcontroller jumps to PCINT0 vector
 PCINT7 – PCINT0 are enabled individually by the Pin change Mask Register 0 (PCMSK0) register,
shown in the next slide
11
 If any PCINT7 – PCINT0 bit is set and PCIE0 bit in PCICR is set, pin change interrupt is enabled
on the corresponding I/O pin
• PCIE1: Pin Change Interrupt Enable bit for PORTC (0: disable; 1: enable)
 A logic change on any enabled PCINT15 – PCINT8 (connected to PORTC) triggers an interrupt
(Pin Change Interrupt Request 1)
 The microcontroller jumps to PCINT1 vector
 PCINT15 – PCINT8 are enabled individually by the Pin change Mask Register 1 (PCMSK1)
register, shown below:

 If any PCINT15 – PCINT8 bit is set and PCIE1 bit in PCICR is set, pin change interrupt is
enabled on the corresponding I/O pin

12
• PCIE2: Pin Change Interrupt Enable bit for PORTD (0: disable; 1: enable)
 A logic change on any enabled PCINT23 – PCINT16 (connected to PORTD) triggers an
interrupt (Pin Change Interrupt Request 2)
 The microcontroller jumps to PCINT2 vector
 PCINT23 – PCINT16 are enabled individually by the Pin change Mask Register 2 (PCMSK2)
register, shown below:

 If any PCINT23 – PCINT16 bit is set and PCIE2 bit in PCICR is set, pin change interrupt is
enabled on the corresponding I/O pin

PIN Change Interrupt Flag Register


• The Pin Change Interrupt Flag Register (PCIFR) is shown below:

13
• PCIF0: Pin Change Interrupt Flag 0
 When a logic change on any PCINT7 – PCINT0 pin triggers an interrupt, PCIF0 becomes set
 The flag is cleared when the ISR is executed
• PCIF1: Pin Change Interrupt Flag 1
 When a logic change on any PCINT15 – PCINT8 pin triggers an interrupt, PCIF1 becomes set
 The flag is cleared when the ISR is executed
• PCIF2: Pin Change Interrupt Flag 2
 When a logic change on any PCINT23 – PCINT16 pin triggers an interrupt, PCIF2 becomes set
 The flag is cleared when the ISR is executed

Example 3
The PB0, PB2 and PB3 pins are connected to switches. Write a program that makes
PORTB.5 high whenever any of the switches changes state.

14
Solution:
#include <avr/io.h>
#include <avr/interrupt.h>
int main()
{
DDRB |= 1 << 5; //set PB5 as an output pin
PCMSK0 |= (1 << 0)|(1 << 2)|(1 << 3); //enable pin change interrupt on PB0, 2, 3
PORTB |= (1 << 0)|(1 << 2)|(1 << 3); //enable pull-ups
PCICR |= (1 << PCIE0); //enable PORTB change interrupt
sei(); //enable interrupts
while(1); //wait here
}
ISR (PCINT0_vect) //ISR for Pin Change Interrupt 0
{
PORTB |= (1 << 5); //PORTB.5 = HIGH
}
15
Interrupt Priority
• If two interrupts are activated at the same time, the interrupt with the higher
priority is served first
• The priority of an interrupt is related to its address in the interrupt vector table
• The interrupt with a lower address has a higher priority
• For example, the address of INT0 is 0x0002 while that of INT1 is 0x0004
• Thus, INT0 has higher priority
• If both interrupts are activated at the same time, INT0 is served first

Interrupt inside an Interrupt


• When an interrupt occurs, the global interrupt enable I-bit is cleared and all
interrupts are disabled
• The user software can write logic one to the I-bit to enable nested interrupts
(interrupts within interrupts)
• When the RETI instruction is executed, the microcontroller sets the I bit, enabling
another interrupt to be served
16

You might also like