Interrupt
Interrupt
Review of C Programming
Pooling
while (1) {
get_device_status;
if (service_required) {
service routine;
}
normal_execution;
}
▪ Using polling, the CPU must continually check the device’s status
▪ Using interrupt:
❑ When needed, a device sends an interrupt signal
❑ In response, the CPU will perform an interrupt service routine, and then resume its normal execution
Interrupt execution sequence
▪ Vector No:
❑ An interrupt with a lower “Vector No” has a higher priority
❑ E.g., INT0 has a higher priority than INT1 and INT2
▪ Program Address:
❑ The fixed memory location for a given interrupt handler
❑ E.g., in response to interrupt INT0, CPU runs instruction at $002
▪ The C macro ISR() is used to define the handler for a given interrupt
▪ Its syntax is given as
ISR(interrupt_vector_name){
// … code for interrupt handler here
}
▪ Example: To process interrupt ‘RXD Complete’ and put the received character in Port
B, we write
ISR(USART_RXC_vect){
PORTB = UDR; // put the received character in Port B
}
Serial RXD interrupt
Write a C interrupt-driven program to use the serial port of ATmega16 at baud rate 9600
bps, no parity, 1 stop bit, 8 data bits, clock speed 8MHz. Whenever a character is
received, it should be sent to Port B.
1 0 0 1 1 0 0 0
RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8 UCSRB
Tx extra data bit for 9-bit character size
▪ For any interrupt, the ATmega16 manual explains how to enable the interrupt
▪ E.g., for serial RXD interrupt, we look at ‘USART’ section
Serial RXD interrupt: Programing
#include <avr/io.h>
#include <avr/interrupt.h> 1
void serial_init(void){
UCSRA = 0b00000000; // Normal speed, disable multi-proc
UCSRB = 0b10010000; // Enable Rx pins, enable RX interrupt 2
UCSRC = 0b10000110; // Asynchronous mode, no parity, 1 stop bit, 8 data bits
UBRRH = 0x00; // Baud rate 9600bps, assuming 8MHz clock
UBRRL = 0x33;
}
}
PORTB = UDR; // Received character is displayed on port B 3
int main(void) {
serial_init(); // initialize USART
sei(); // enable interrupt subsystem globally 4
DDRB = 0xFF;
while (1) {;}
//
//
set port B for output
infinite loop
5
return 0;
}
Serial RXD: Polling approach
For comparison, the program below uses polling for the same effect.
#include <avr/io.h>
void serial_init(void) {
UCSRA = 0b00000000; // Normal speed, disable multi-proc
UCSRB = 0b00010000; // Enable Rx, disable interrupts
UCSRC = 0b10000110; // Asynchronous mode, no parity, 1 stop bit, 8 data bits
UBRRH = 0x00; // Baud rate 9600bps, assuming 8MHz clock
UBRRL = 0x33;
}
int main(void) {
serial_init(); // initialize USART
DDRB = 0xFF; // set port B for output
while (1) { // infinite loop
while ((UCSRA & (1<<RXC)) == 0x00){;} // Poll until RXC flag = 1
PORTB = UDR; // received character is displayed on port B
}
return 0;
}
External interrupts
ATmega16 chip
External interrupts: Configuration
▪ To enable an external interrupt, set a flag in General Interrupt Control Register (GICR)
INT1 INT0 INT2 - - - IVSEL IVCE
Read/Write R/W R/W R/W R R R R/W R/W
Initial value 0 0 0 0 0 0 0 0
Note that INT1 and GICR names are already defined in <avr/io.h>
#define INT1 7
External interrupts: Configuration
▪ For INT2:
INT1 INT0
ISC11 ISC10 An interrupt is triggered when ISC01 ISC00 An interrupt is triggered when
Write a C program to toggle port B.4→B.7 whenever a switch on the demo board is pressed. The
program should use an external interrupt.
#include <avr/io.h>
#include <avr/interrupt.h> 1
ISR(INT2_vect) { // handler for INT2 interrupt
PORTB ~= (PORTB & 0xF0); // toggle port B.4 → B.7 2
}
int main(void) {
GICR = (1 << INT2); // enable interrupt INT2 3
MCUCSR = (1 << ISC2); // triggered on rising edge in INT2 pin (B.2) 4
sei(); // enable interrupt subsystem globally 5
DDRB = 0xF0; // set port B.4 → B.7 for output and B.0 → B.3 for input
PORTB = 0xAF; // initial value
while (1) {;} // infinite main loop
return 0;
}