Interrupts are exactly what they sound like. They are events that cause a microcontroller’s CPU to stop executing a main program in order to execute a snippet of code on the side. As an example, here I discuss how the analog comparator on the ATmega328 (Arduino Uno) can be configured to generate an interrupt. Let me first show you the code then I will tell you what it does.
void setup()
{
pinMode(7,INPUT);
Serial.begin(9600);
ACSR = B01011010; // comparator interrupt enabled and tripped on falling edge.
}
void loop()
{
}
ISR(ANALOG_COMP_vect)
{
Serial.println("Interrupt Executed!")
}
Now for the explanation. The 8-bit ACSR
register (Analog Comparator Control and Status Register) has the following bit structure.
ACSR – [ACD, ACBG, ACO, ACI, ACIE, ACIC, ACIS1, ACIS0]
I won’t explain what all of these bits do, only the ones I am setting in the code. First, seting the ACBG (Analog Comparator Bandgap Select) bit to one tells the ATmega328 to apply its own internal bandgap voltage (about 1.1V) to the positive input of the comparator. The negative input is analog pin 7 on the Arduino. I set the ACI (Analog Comparator Interrupt Flag) bit to one (this clears the interrupt flag) because I am changing other settings and I don’t want these changes to accidently trigger an interrupt. The ACIE (Analog Comparator Interrupt Enable) bit is set so when the analog comparator output changes as specified by the ACISx bits, an interrupt is executed. Setting the ACISx
bits to 10 triggers the interrupt on a falling edge occurring at the comparator output. Setting these bits differently will trigger the interrupt on any change of the comparator output (00), or on a rising edge (11).
An aside about how the analog comparator works: The analog comparator output is high if the voltage applied to the positive input is greater then the voltage applied to the negative input. The output is low if the voltage applied to the positive input is less then that applied to the negative input. So, my setup will result in the comparator output going low when the voltage applied to Arduino pin 7 rises above 1.1 V (the bandgap reference voltage applied to the positive input). The falling edge occurring when this happens triggers the interrupt. This allows me to detect analog inputs above 1.1 V on pin 7 and do something when the input is detected. Now back to the explanation of the code above.
When the interrupt is executed, the code contained in the ISR(ANALOG_COMP_vect)
function is executed before the CPU returns to the main program. ISR stands for interrupt service request. Here, whenever the interrupt occurs, I am simply printing a message to the serial monitor.
Permalink //
So you could use an external square wave oscillator to trigger the interrupts I’m assuming? As long as you set the comparator up correctly and then your oscillator goes above 1.1 volts?
Permalink //
Yes, that would work. Just curious, what type of use do you have in mind?
Permalink //
A good use for it is period measurement. the microseconds() difference between two isr calls, is the wave period, with about the 8-16 us latency time of the interrupt call.
Permalink //
Carlos,
If one assumes that all interrupt function calls have the same latency then I don’t think you would have to take this latency into account when figuring out the period. Both the start and stop time would have this latency built into it. What do you think?
Permalink //
I see this is an older posting, so I hope it is still active. Your sample is for pin 7 . What exactly tells the chip which pin the interrupt should respond to? Can it be assigned to another pin, and then back when multiple inputs are used? If so, how?
Great information. I appreciate it.
Permalink
Permalink //
Thanks – nice posting, except for this: “The negative input is analog pin 7 on the Arduino.” – there is no analog pin 7 on the Arduino UNO, the only analog pins are A0 to A5 (or AIN0 to AIN5). What exactly did you means with that?
Permalink //
The negative input to the onboard comparator is also digital pin 7. But, when it is used with the comparator it is working as an analog input. That is my understanding.