148 6. INTERRUPT SUBSYSTEM
void setup()
{
attachInterrupt(0, int0_ISR, RISING);
}
void loop()
{
//wait for interrupts
}
//*************************************************************************
//int0_ISR: interrupt service routine for INT0
//*************************************************************************
void int0_ISR(void)
{
//Insert interrupt specific actions here.
}
//*************************************************************************
6.4.2 INTERNAL INTERRUPT PROGRAMMING
In this example, we use Timer/Counter0 as a representative example on how to program internal
interrupts. In the example that follows, we use Timer/Counter0 to provide prescribed delays within
our program.
We discuss the ATmega328 timer system in detail in the next chapter. Briefly, the
Timer/Counter0 is an eight bit timer. It rolls over every time it receives 256 timer clock “ticks.”
There is an interrupt associated with the Timer/Counter0 overflow. If activated, the interrupt will
occur every time the contents of the Timer/Counter0 transitions from 255 back to 0 count. We
can use this overflow interrupt as a method of keeping track of real clock time (hours, minutes,
and seconds) within a program. In this specific example, we use the overflow to provide precision
program delays.
6.4.2.1 Programming an internal interrupt in C
In this example, the ATmega328 is being externally clocked by a 10 MHz ceramic resonator. The
resonator frequency is further divided by 256 using the clock select bits CS[2:1:0] in Timer/Counter
6.4. PROGRAMMING INTERRUPTS IN C AND THE ARDUINO ENVIRONMENT 149
Control Register B (TCCR0B). When CS[2:1:0] are set for [1:0:0], the incoming clock source is
divided by 256. This provides a clock “tick” to Timer/Counter0 every 25.6 microseconds.Therefore,
the eight bit Timer/Counter0 will rollover every 256 clock “ticks” or every 6.55 ms.
To create a precision delay, we write a function called delay.The function requires an unsigned
integer parameter value indicating how many 6.55 ms interrupts the function should delay. The
function stays within a while loop until the desired number of interrupts has occurred. For example,
to delay one second the function would be called with the parameter value “153. That is, it requires
153 interrupts occurring at 6.55 ms intervals to generate a one second delay.
The code snapshots to configure the Time/Counter0 Overflow interrupt is provided below
along with the associated interrupt service routine and the delay function.
//function prototypes******************************************************
//delay specified number 6.55ms
void delay(unsigned int number_of_6_55ms_interrupts);
void init_timer0_ovf_interrupt(void); //initialize timer0 overf.interrupt
//interrupt handler definition*********************************************
//interrupt handler definition
#pragma interrupt_handler timer0_interrupt_isr:17
//global variables*********************************************************
unsigned int input_delay; //counts number of Timer/Counter0
//Overflow interrupts
//main program*************************************************************
void main(void)
{
init_timer0_ovf_interrupt(); //initialize Timer/Counter0 Overflow
//interrupt - call once at beginning
//of program
:
:
delay(153); //1 second delay
}
150 6. INTERRUPT SUBSYSTEM
//*************************************************************************
//int_timer0_ovf_interrupt(): The Timer/Counter0 Overfl. interrupt is being
//employed as a time base for a master timer for this project. The ceramic
//resonator operating at 10 MHz is divided by 256.
//The 8-bit Timer0 register
//(TCNT0) overflows every 256 counts or every 6.55 ms.
//*************************************************************************
void init_timer0_ovf_interrupt(void)
{
TCCR0B = 0x04; //divide timer0 timebase by 256,
//overflow occurs every 6.55ms
TIMSK0 = 0x01; //enable timer0 overflow interrupt
asm("SEI"); //enable global interrupt
}
//*************************************************************************
//timer0_interrupt_isr:
//Note: Timer overflow 0 is cleared automatically
//when executing the corresponding interrupt handling vector.
//*************************************************************************
void timer0_interrupt_isr(void)
{
input_delay++; //increment overflow counter
}
//*************************************************************************
//delay(unsigned int num_of_6_55ms_interrupts): this generic delay function
//provides the specified delay as the number of 6.55 ms "clock ticks"
//from the Timer/Counter0 Overflow interrupt.
//
//Note: this function is only valid when using a 10 MHz crystal or ceramic
//resonator. If a different source frequency is used, the clock
//tick delay value must be recalculated.
//*************************************************************************
void delay(unsigned int number_of_6_55ms_interrupts)
{
6.4. PROGRAMMING INTERRUPTS IN C AND THE ARDUINO ENVIRONMENT 151
TCNT0 = 0x00; //reset timer0
input_delay = 0; //reset timer0 overflow counter
while(input_delay <= number_of_6_55ms_interrupts)
{
; //wait for spec. number of interpts.
}
}
//*************************************************************************
6.4.2.2 Programming an internal interrupt using the Arduino Development Environment
The Arduino Development Environment uses the GNU tool chain and the AVR Libc to compile
programs. Internal interrupt configuration uses AVR-GCC conventions. To tie the interrupt event
to the correct interrupt service routine, the AVR-GCC interrupt name must be used. These vector
names are provided in the right column of Figure 6.2.
In the following sketch, the previous example is configured for use with the Arduino De-
velopment Environment using AVR-GCC conventions. Also, the timing functions in the previous
example assumed a time base of 10 MHz. The Arduino UNO R3 is clocked with a 16 MHz crystal.
Therefore, some of the parameters in the sketch were adjusted to account for this difference in time
base.
//*************************************************************************
#include <avr/interrupt.h>
unsigned int input_delay; //counts number of Timer/Counter0
//Overflow interrupts
void setup()
{
init_timer0_ovf_interrupt(); //initialize Timer/Counter0 Overfl.
}
void loop()
{
:
delay(244); //1 second delay
:

Get Arduino Microcontroller, 2nd Edition now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.