Whenever a hardware interrupt occurs on the ATmega32, the appropriate instruction in the jump vector is executed. Recall that the C compiler places jumps to _bad_interrupt in all of the jump vectors for unused interrupts. In order to use interrupts in C we must:
Setting the global interrupt flag is done with the sei() “function” defined in <avr/interrupt.h>. Enabling the desired interrupt is accomplished by setting the appropriate flag in the control register for the desired interrupt. The syntax for defining the ISR and initializing the appropriate jump vector is described below.
The <avr/interrupt.h> header file defines a macro, ISR(interrupt_vector), for initializing the jump vector and specifying the code to be executed when the interrupt occurs.
The interrupt_vector must be one of the following (defined in avr/iom32.h, which is included by avr/io.h):
| Interrupt type | Vector Name | Vector Number |
|---|---|---|
| External Interrupt Request 0 | INT0_vect | 1 |
| External Interrupt Request 1 | INT1_vect | 2 |
| External Interrupt Request 2 | INT2_vect | 3 |
| Timer/Counter2 Compare Match | TIMER2_COMP_vect | 4 |
| Timer/Counter2 Overflow | TIMER2_OVF_vect | 5 |
| Timer/Counter1 Capture Event | TIMER1_CAPT_vect | 6 |
| Timer/Counter1 Compare Match A | TIMER1_COMPA_vect | 7 |
| Timer/Counter1 Compare Match B | TIMER1_COMPB_vect | 8 |
| Timer/Counter1 Overflow | TIMER1_OVF_vect | 9 |
| Timer/Counter0 Compare Match | TIMER0_COMP_vect | 10 |
| Timer/Counter0 Overflow | TIMER0_OVF_vect | 11 |
| Serial Transfer Complete | SPI_STC_vect | 12 |
| USART, Rx Complete | USART_RXC_vect | 13 |
| USART Data Register Empty | USART_UDRE_vect | 14 |
| USART, Tx Complete | USART_TXC_vect | 15 |
| ADC Conversion Complete | ADC_vect | 16 |
| EEPROM Ready | EE_RDY_vect | 17 |
| Analog Comparator | ANA_COMP_vect | 18 |
| 2-wire Serial Interface | TWI_vect | 19 |
| Store Program Memory Ready | SPM_RDY_vect | 20 |
Consider the following example program.
#include <avr/io.h> #include <avr/interrupt.h> uint8_t portVal = 128; int main() { sei(); DDRB = 0x00; DDRC = 0xff; while(1) { PORTC = portVal; } return 0; } ISR(TIMER0_OVF_vect) { portVal = PINB; }
00000000 <__vectors>: 0: 0c 94 2a 00 jmp 0x54 ; 0x54 <__ctors_end> 4: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 8: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 10: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 14: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 18: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 1c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 20: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 24: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 28: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 2c: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__vector_11> 30: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 34: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 38: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 3c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 40: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 44: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 48: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 4c: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> 50: 0c 94 47 00 jmp 0x8e ; 0x8e <__bad_interrupt> <snip> 00000092 <main>: 92: 78 94 sei 94: 17 ba out 0x17, r1 ; 23 96: 8f ef ldi r24, 0xFF ; 255 98: 84 bb out 0x14, r24 ; 20 9a: 80 91 60 00 lds r24, 0x0060 9e: 85 bb out 0x15, r24 ; 21 a0: fe cf rjmp .-4 ; 0x9e <main+0xc> 000000a2 <__vector_11>: a2: 1f 92 push r1 a4: 0f 92 push r0 a6: 0f b6 in r0, 0x3f ; 63 a8: 0f 92 push r0 aa: 11 24 eor r1, r1 ac: 8f 93 push r24 ae: 86 b3 in r24, 0x16 ; 22 b0: 80 93 60 00 sts 0x0060, r24 b4: 8f 91 pop r24 b6: 0f 90 pop r0 b8: 0f be out 0x3f, r0 ; 63 ba: 0f 90 pop r0 bc: 1f 90 pop r1 be: 18 95 reti
Changing the declaration of portVal in the previous example to this:
volatile uint8_t portVal = 128;
Results in a minor change to the machine code generated for main:
00000092 <main>: 92: 78 94 sei 94: 17 ba out 0x17, r1 ; 23 96: 8f ef ldi r24, 0xFF ; 255 98: 84 bb out 0x14, r24 ; 20 9a: 80 91 60 00 lds r24, 0x0060 9e: 85 bb out 0x15, r24 ; 21 a0: fc cf rjmp .-8 ; 0x9a <main+0x8>