Overview
An interrupt is a notification for CPU of a micro-controller. It happen very fast commanding the CPU to execute the routine in the Interrupt Service Routine (ISR) handler without waiting for next instruction execution . This mechanism make the program execution more responsive and effective.
The ATMega644P has many interrupt source each corresponds to their interrupt vector number.
![]() |
| Interrupt Vectors in ATmega644 |
An interrupt source could happen whenever the user's program enable it and properly configure it.
External Interrupt Programming in C
The Atmega644P has three external interrupt sources, INT0( PD2), INT1(PD3) and INT2(PB2). These interrupt sources are use to detect edge(falling or rising) and logic level (Low or High). Their interrupt vector addresses are list in the figure above.
I Microchip Studio that use the AVR-LibC tool-chain the programmer doesn't need to remember the address number of each source. All of them have a readable name specified the compiler.
The programmer must modify these registers to enable the external interrupts.
- EICRA – External Interrupt Control Register A ( Modes: edge or logic level)
- EIMSK – External Interrupt Mask Register (Enable or Disable)
- EIFR – External Interrupt Flag Register (Flag of external interrupt source)
These feature are common for most of the 40-pin AVR ATMega series.
In this example I use these interrupt sources to toggle each LED at PortB.
- /*
- * 4-external_interrupt.c
- *
- * Created: 1/25/2026 7:12:38 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include "avr/interrupt.h"
- #include <util/delay.h>
- #define F_CPU 16000000UL
- int main(void)
- {
- /* Replace with your application code */
- DDRB=0xFF;
- DDRB&=~(1<<2);
- DDRD=0x01;
- PINB=(1<<2);
- PIND=(1<<2)|(1<<3);
- EIMSK=0x07;
- sei();
- while (1)
- {
- PORTD^=1;
- _delay_ms(500);
- }
- }
- /*
- Interrupt Service Routine (ISR)
- for External Interrupt
- */
- ISR(INT0_vect){
- PORTB^=(1<<5);
- }
- ISR(INT1_vect){
- PORTB^=(1<<6);
- }
- ISR(INT2_vect){
- PORTB^=(1<<7);
- }
Proteus VSM simulate this program correctly.
![]() |
| Proteus Schematic and Simulation |
However in real hardware the input button bounce. So we need to add a short delay time in the ISR or adding a low pass filter to each input button.
![]() |
| Testing in Real Hardware |
Multiplexing Display Example
Since the interrupts happens very fast it's suitable to make a counting display that counts the time of switch pressing. The on-board display has up to six digits that able display the number of 999999.
- /*
- * 4-ext_interrupt_6_digit_16M.c
- *
- * Created: 1/26/2026 8:53:49 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const uint8_t cc_7[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
- 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
- const uint16_t d_time=5;
- volatile long count=0;
- int main(void)
- {
- /* Replace with your application code */
- DDRB=0xFF;
- DDRC=0xFF;
- DDRD=0x00;
- PIND=(1<<2)|(1<<3);
- EIMSK=0x03;
- sei();
- while (1)
- {
- PORTC=0;
- PORTB=cc_7[count/100000];
- PORTC=0x20;
- _delay_ms(d_time);
- PORTC=0;
- PORTB=cc_7[(count%100000)/10000];
- PORTC=0x40;
- _delay_ms(d_time);
- PORTC=0;
- PORTB=cc_7[(count%10000)/1000];
- PORTC=0x80;
- _delay_ms(d_time);
- PORTC=0;
- PORTB=cc_7[(count%1000)/100];
- PORTC=0x04;
- _delay_ms(d_time);
- PORTC=0;
- PORTB=cc_7[(count%100)/10];
- PORTC=0x08;
- _delay_ms(d_time);
- PORTC=0;
- PORTB=cc_7[count%10];
- PORTC=0x10;
- _delay_ms(d_time);
- }
- }
- /*
- Interrupt Service Routine (ISR)
- for External Interrupt
- */
- ISR(INT0_vect){
- count++;
- if(count>999999) count=0;
- }
- ISR(INT1_vect){
- count--;
- if(count<0) count=999999;
- }
Whenever each buttons are pressed it will update the value on the display.
![]() |
| Program Simulation |
In Proteus VSM the display run very smooth without flickering.
However in real hardware the display flickers whenever any button is pressed due to switch bouncing. It does not increase or decrease by one.






No comments:
Post a Comment