Description
From @robinhedwards on November 20, 2013 10:16
There are two differences in the behaviour of interrupts on a Due, after comparison to an Uno (well actually a Duemilanove).
First - When I attachInterrupt() to FALLING on a digital pin, and drive the pin as an OUTPUT between HIGH and LOW, I would expect the interrupt to trigger each time the output pin is set low. This happens on the Uno, but NOT on the Due, where the interrupt only seems to fire once.
Test case:
// Interrupt comparison between Uno & Due
// Expected output (obtained on Uno)
// Pin high, count=0
// Pin low, count=1
// Pin high, count=1
// Pin low, count=2
// BUT...
// On due, count remains 1
int pin = 3; // INT 1 on UNO
volatile int i = 0;
void test() { i++; }
void setup() {
Serial.begin(9600);
pinMode(pin, OUTPUT);
// attachInterrupt(1, test, FALLING); // Uno
attachInterrupt(pin, test, FALLING); // Due
}
void loop() {
digitalWrite(pin, HIGH);
Serial.print("Pin high, count="); Serial.println(i);
delay(500);
digitalWrite(pin, LOW);
Serial.print("Pin low, count="); Serial.println(i);
delay(500);
}
The expected behaviour can be obtained on the Due by replacing the digitalWrite() with digitalWriteDirect():
inline void digitalWriteDirect(int pin, boolean val){
if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
else g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
Now both Uno and Due count up as expected.
Second - Switching the pinMode() on a Due seems to detach the interrupts set up on the pin. You need to call attachInterrupt() again after changing e.g. from input to output mode. Again this is different behaviour from the Uno, where there is no need to do this.
Test case (replaces loop in first test case):
void loop() {
static int secs = 3;
digitalWriteDirect(pin, HIGH);
Serial.print("Pin high, count=");
Serial.println(i);
delay(500);
digitalWriteDirect(pin, LOW);
Serial.print("Pin low, count=");
Serial.println(i);
delay(500);
secs--;
if (secs == 0) {
pinMode(pin, INPUT);
pinMode(pin, OUTPUT);
}
More details on the forum:
http://forum.arduino.cc/index.php?topic=199320.0
Note that this difference in behaviour causes e.g. the PS2KeyboardExt2 library not to work on a Due, since the library relies on either the host or the keyboard being able to send data on the CLOCK & DATA lines. The call to pinMode() causes the interrupt on the CLOCK line to stop triggering.
Copied from original issue: arduino/Arduino#1693