|
OK, enough with politics, time
to see how we implement interrupts in practice. Note, that each
compiler implements interrupts in a different way since the C language
by itself, does not determine the way interrupts should be implemented.
Thus, we will stick to gcc. Do you remember our example with the
button and the LED? Have a look at the following piece of code that
shows the use of the external interrupt 0 and we will discuss it.
We are using ATMega8 and the button is connected to pin4, PD2(INT0).
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
// Enable INT0 External Interrupt
GICR |= 1<<INT0;
// Falling-Edge Triggered INT0
MCUCR |= 1<<ISC01;
// Enable Interrupts
sei();
int main(void)
{
while (forever)
{
}
}
// External Interrupt 0 ISR
SIGNAL(SIG_INTERRUPT0)
{
PORTB &= ~(1<<4);
}
The first thing your eye will catch is the ISR. The
SIGNAL keyword tells the compiler that this is an ISR. The SIG_INTERRUPT0
keyword just indicates that this ISR is for the external interrupt
0. Note, that the ISR header is not declared anywhere else in the
program.
Before you get interrupts you have to enable them.
It comes down to enabling a specific interrupt; setting INT0 bit
in the GICR register in our case and enabling the global interrupt
flag with the sei() macro. Alternatively, you could use the asm("sei")
command for the same thing. Now, according to our setup we want
a falling-edge triggered interrupt, this is why ISC01 is set.
Now you see that our main loop is empty, meaning that
our micro will keep doing nothing, it will just enter the ISR when
the button is pressed. Of course, you could have any piece of code
in the main loop.
There is one thing you should take care of with interrupts,
an ISR has to be quick. Be quick or be dead as some friends of
mine suggest. There are many tasks for a microcontroller
that rely on timing, for example the 1-wire protocol does that.
If you have a long ISR and an interrupt hits when a timing-sensitive
routine is executed, your code will brake. If you can 't help it,
just protect any sensitive code. Disabe interrupts with cli() before
the critical code and enable them afterwards.
|