728x90

728x90

Monday, January 26, 2026

ATMega644P External Interrupt Programming

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.

ATMega644P External Interrupt Programming

The ATMega644P has many interrupt source each corresponds to their interrupt vector number.

ATMega644P External Interrupt Programming
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.

  1. EICRA – External Interrupt Control Register A ( Modes: edge or logic level)
  2. EIMSK – External Interrupt Mask Register (Enable or Disable)
  3. 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.

  1. /*
  2. * 4-external_interrupt.c
  3. *
  4. * Created: 1/25/2026 7:12:38 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include "avr/interrupt.h"
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. int main(void)
  12. {
  13. /* Replace with your application code */
  14. DDRB=0xFF;
  15. DDRB&=~(1<<2);
  16. DDRD=0x01;
  17. PINB=(1<<2);
  18. PIND=(1<<2)|(1<<3);
  19. EIMSK=0x07;
  20. sei();
  21. while (1)
  22. {
  23. PORTD^=1;
  24. _delay_ms(500);
  25. }
  26. }

  27. /*
  28. Interrupt Service Routine (ISR)
  29. for External Interrupt
  30. */
  31. ISR(INT0_vect){
  32. PORTB^=(1<<5);
  33. }

  34. ISR(INT1_vect){
  35. PORTB^=(1<<6);
  36. }

  37. ISR(INT2_vect){
  38. PORTB^=(1<<7);
  39. }

 

Proteus VSM simulate this program correctly. 

ATMega644P External Interrupt Programming
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. 

ATMega644P External Interrupt Programming
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.

  1. /*
  2. * 4-ext_interrupt_6_digit_16M.c
  3. *
  4. * Created: 1/26/2026 8:53:49 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <avr/interrupt.h>
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. const uint8_t cc_7[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
  12. 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
  13. const uint16_t d_time=5;
  14. volatile long count=0;
  15. int main(void)
  16. {
  17. /* Replace with your application code */
  18. DDRB=0xFF;
  19. DDRC=0xFF;
  20. DDRD=0x00;
  21. PIND=(1<<2)|(1<<3);
  22. EIMSK=0x03;
  23. sei();
  24. while (1)
  25. {
  26. PORTC=0;
  27. PORTB=cc_7[count/100000];
  28. PORTC=0x20;
  29. _delay_ms(d_time);
  30. PORTC=0;
  31. PORTB=cc_7[(count%100000)/10000];
  32. PORTC=0x40;
  33. _delay_ms(d_time);
  34. PORTC=0;
  35. PORTB=cc_7[(count%10000)/1000];
  36. PORTC=0x80;
  37. _delay_ms(d_time);
  38. PORTC=0;
  39. PORTB=cc_7[(count%1000)/100];
  40. PORTC=0x04;
  41. _delay_ms(d_time);
  42. PORTC=0;
  43. PORTB=cc_7[(count%100)/10];
  44. PORTC=0x08;
  45. _delay_ms(d_time);
  46. PORTC=0;
  47. PORTB=cc_7[count%10];
  48. PORTC=0x10;
  49. _delay_ms(d_time);
  50. }
  51. }

  52. /*
  53. Interrupt Service Routine (ISR)
  54. for External Interrupt
  55. */
  56. ISR(INT0_vect){
  57. count++;
  58. if(count>999999) count=0;
  59. }

  60. ISR(INT1_vect){
  61. count--;
  62. if(count<0) count=999999;
  63. }

Whenever each buttons are pressed it will update the value on the display.

ATMega644P External Interrupt Programming
Program Simulation

In Proteus VSM the display run very smooth without flickering.

ATMega644P External Interrupt Programming

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

320x50

Search This Blog

tyro-728x90