Interrupts

ATmega1284p has three external interrupts as well as pin change interrupts available on available on all IO pins.

Available External Interrupts

IO Pin Interrupt Available Modes
RXD1 INT0
  • LOW
  • CHANGE
  • RISING
  • FALLING
TXD1 INT1
D10 INT2

Available Pin Change Interrupts

IO Pin Interrupt Available Modes
D4-D12, D18-D13 pin
  • CHANGE
A0-A7 pin

ISRs

Interrupt Service Routines (ISRs) are functions which are invoked when the interrupt is triggered. When an external interrupt is configured, a reference to a user defined ISR must be included. The format of these functions must be:

typedef void (*voidFuncPtr)(void);

Which is a function which does not return a value (return type void) and which has an empty parameter list.

Enabling an External Interrupt

An external interrupt can be enabled with a call to attachInterrupt():

attachInterrupt(interrupt, ISR, mode);

WhereВ interruptВ is the external interrupt number (i.e. 0 for INT0, 1 for INT1 and 2 for INT2),ISR is the Interrupt Service Routine function and mode is one of the supported interrupt modes (LOW, CHANGE, RISING or FALLING).

Enabling an Pin ChangeВ Interrupt

An pin changeВ interrupt can be enabled with a call to PcInt::attachInterrupt() from theSodaq_PcInt library.

PcInt::attachInterrupt(interrupt, ISR);

WhereВ interruptВ is the pinВ number (e.g. 4 for D4, A1 for A1), ISR is the Interrupt Service Routine function. Since the only mode available to a pin change interrupt is CHANGE, the mode parameter is not required.

External Interrupt Example

void setup()
{
 В //Setup the Serial Monitor
 В Serial.begin(57600);
 В 
 В //Switch on the second Grove column
 В pinMode(22, OUTPUT);
 В digitalWrite(22, HIGH);

 В //D10 Interrupt
 В attachInterrupt(2, exampleISR, RISING); //D10 Yellow Grove pin 1
}

void exampleISR()
{
 В //Normally it is bad practice
 В //to use a println() in an ISR
 В Serial.println("Interrupt!");
}

void loop()
{
}

Pin Change Interrupt Example

#include <Sodaq_PcInt.h>

void setup()
{
 В //Setup the Serial Monitor
 В Serial.begin(57600);

 В //D10 Interrupt
 В PcInt::attachInterrupt(4, exampleISR); //D4 Yellow Grove pin 1
}

void exampleISR()
{
 В //Normally it is bad practice
 В //to use a println() in an ISR
 В Serial.println("Interrupt!");
}

void loop()
{
}

Other Notes

When an interrupt is triggered, the microprocessor effectively suspends the current code, executes the ISR, and then resumes with the original code. If another interrupt is triggered during the execution of the anВ ISR, the new interrupt will be executed once the first ISR has finished. This means that interrupts are effectively suspended during the execution of any ISR.

Due to this behaviour it is recommended to keep the ISR code as simple as possible. Additionally, some function calls are unavailable due to those functions being dependent on other interrupts. A good example of this is the method delay(ms)В which inserts a delay of msmilliseconds. This method depends on a counter which is updated via an internal interrupt, as that interrupt is suspended during the execution of an ISR, the call toВ delay() will never return as the counter never reaches the defined target.

Sometimes it is desirable to disable/suspend interrupts during the execution of a critical section of code, code which wouldВ be negatively affected by jumping to the execution of an ISR. To achieve this, interrupts can be be suspended before thatВ section of code and enabled after.

SuspendВ Interrupts

noInterrupts();
// or
cli();

Enable Interrupts

interrupts();
// or
sei();