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

Interrupt

The document discusses interrupt programming in C for the ATmega16 microcontroller. It covers the interrupt execution sequence, the ATmega16 interrupt subsystem including vector numbers and descriptions, and steps to program an interrupt in C including using the ISR macro and enabling interrupts. Examples are provided for serial receive interrupts and external interrupts.

Uploaded by

Loan Đỗ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Interrupt

The document discusses interrupt programming in C for the ATmega16 microcontroller. It covers the interrupt execution sequence, the ATmega16 interrupt subsystem including vector numbers and descriptions, and steps to program an interrupt in C including using the ISR macro and enabling interrupts. Examples are provided for serial receive interrupts and external interrupts.

Uploaded by

Loan Đỗ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

Lecture 4’s sequence

4.1 Interrupt programming in C for ATmega16

4.2 Timers in ATmega16

Review of C Programming

4.3 Timer applications


Interrupt programming in C for ATmega16

▪ Compared to polling, interrupt is a more efficient approach for the


CPU to handle peripheral devices

▪ Example peripheral devices are serial port, external switches,


timers, PWM, and ADC

▪ In this lecture, we will learn the interrupt subsystem in the


ATmega16

▪ We will also learn how to write an interrupt-driven program in C


Polling versus Interrupt

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

1. A device issues an interrupt

2. CPU finished the current instruction

3. CPU acknowledges the interrupt

4. CPU saves its states and PC onto stack

5. CPU loads the address of ISR onto PC

6. CPU executes the ISR

7. CPU retrieves its states and PC from stack

8. Normal execution resumes


ATmega16 interrupt subsystem

▪ The ATmega16 has 21 interrupts:


❑ 3 external interrupts
❑ 8 timer interrupts
❑ 3 serial port interrupts our focus
❑ 1 ADC interrupt

❑ 1 analogue comparator interrupt


❑ 1 SPI interrupt
❑ 1 TWI interrupt
❑ 2 memory interrupts
❑ 1 reset interrupt
Table 4.1: Interrupts in ATmega16

Vector No. Program address Interrupt vector name Description


1 $000 RESET_vect Reset
2 $002 INT0_vect External Interrupt Request 0
3 $004 INT1_vect External Interrupt Request 1
4 $006 TIMER2_COMP_vect Timer/Counter2 Compare Match
5 $008 TIMER2_OVF_vect Timer/Counter2 Overflow
6 $00A TIMER1_CAPT_vect Timer/Counter1 Capture Event
7 $00C TIMER1_COMPA_vect Timer/Counter1 Compare Match A
8 $00E TIMER1_COMPB_vect Timer/Counter1 Compare Match B
9 $010 TIMER1_OVF_vect Timer/Counter1 Overflow
10 $012 TIMER0_OVF_vect Timer/Counter0 Overflow
11 $014 SPI_STC_vect Serial Transfer Complete
12 $016 USART_RXC_vect USART, Rx Complete
13 $018 USART_UDRE_vect USART Data Register Empty
14 $01A USART_TXC_vect USART, Tx Complete
15 $01C ADC_vect ADC Conversion Complete
16 $01E EE_RDY_vect EEPROM Ready
17 $020 ANA_COMP_vect Analog Comparator
18 $022 TWI_vect 2-wire Serial Interface
19 $024 INT2_vect External Interrupt Request 2
20 $026 TIMER0_COMP_vect Timer/Counter0 Compare Match
21 $028 SPM_RDY_vect Store Program Memory Ready
Interrupts in ATmega16

▪ 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

▪ Interrupt Vector Name:


❑ This is the interrupt name, to be used with C macro ISR()
Steps to program an interrupt in C

▪ To program an interrupt, 5 steps are required


1. Include header file <avr/interrupt.h>
2. Use C macro ISR() to define the interrupt handler and update IVT
3. Enable the specific interrupt
4. Configure details of the interrupt by setting relevant registers
5. Enable the interrupt subsystem globally using sei()

▪ Later, we’ll study steps for interrupt programming in C, via 2 examples


❖ USART RXD Complete interrupt
❖ External interrupts
Using C macro ISR()

▪ 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
}

where interrupt_vector_name is given in Table 4.1

▪ 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.

▪ The serial port on ATmega16 can trigger an RXD interrupt whenever a


character is received [Lecture 3]

▪ We enable this interrupt by setting a flag in a serial port register

▪ We then write the ISR, to be run whenever the interrupt is triggered


Serial RXD interrupt: Configuration

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

Rx extra data bit for 9-bit character size

bit 2 to decide character size

1 to enable USART transmitter: Pin D.1 = TXD pin

1 to enable USART receiver: Pin D.0 = RXD pin

1 to enable USART Data Register Empty Interrupt

1 to enable TX Complete Interrupt

1 to enable RX Complete Interrupt

▪ 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;
}

ISR(USART_RXC_vect) { // Handler for RXD interrupt

}
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

▪ External interrupts on ATmega16 and ATmega8515 are similar

▪ Key references: ATmega16 user manual, ‘External Interrupts’ section

▪ Three external interrupts can be triggered:


rising-edge interrupt
❑ INT0 on pin D.2
1
❑ INT1 on pin D.3
0
❑ INT2 on pin B.2
falling-edge interrupt
1
▪ Key steps in using external interrupts:
0
❑ enable the interrupt

❑ specify what types of event will trigger the interrupt


External interrupts: Relevant pins

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

▪ Example: To enable INT1 (pin D.3), we can write


GICR = 0b10000000 // same as GICR = (1 << INT1);

Note that INT1 and GICR names are already defined in <avr/io.h>
#define INT1 7
External interrupts: Configuration

▪ Specify the events that trigger an external interrupt by using


❑ MCU Control Register (INT0 and INT1), or
❑ MCU Control and Status Register (INT2)

▪ For INT2:

MCUCSR JTD ISC2 - JTRF WDRF BORF EXTRF PORF

INT2 0: falling edge triggers an interrupt INT2


1: rising edge triggers an interrupt INT2
External interrupts: Configuration

▪ For INT0 and INT1:


MCUCR SM2 SE SM1 SM0 ISC11 ISC10 ISC01 ISC00

INT1 INT0

ISC11 ISC10 An interrupt is triggered when ISC01 ISC00 An interrupt is triggered when

0 0 low level of INT1 0 0 low level of INT0

0 1 any change of INT1 0 1 any change of INT0

1 0 falling edge of INT1 1 0 falling edge of INT0

1 1 rising edge of INT1 1 1 rising edge of INT0


External interrupts: Example

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.

▪ Let’s use interrupt INT2. This interrupt is triggered on pin B.2


▪ To enable interrupt INT2
GICR = 0b00100000 // same as GICR = (1 << INT2);

▪ To specify that INT2 is triggered on rising edge of pin B.2


MCUCSR = 0b01000000; // same as MCUCSR = (1 << ISC2);

▪ Then, we write interrupt handler and enable interrupt subsystem


External interrupts: Programming

#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;
}

You might also like