Go Down

Topic: Changing Interrupt Pins (Read 2063 times) previous topic - next topic

vex

Nov 21, 2010, 12:17 am Last Edit: Nov 21, 2010, 12:33 am by vex Reason: 1
Hey everyone, after hours of searching I am still very confused as to how to attach interrupts to pins. I am trying to make an interrupt on DP8; this is the part of my code I am having trouble with:
Code: [Select]

#include <avr/interrupt.h>
#include <avr/io.h>

int recpin = 8;
int ledPin3 = 11;

void setup() {
 pinMode(ledPin3, OUTPUT);
 pinMode(recpin, INPUT);
 PCICR |= (1 << PCIE0);
 PCMSK0 |= (1 << PCINT0);
 attachInterrupt(8, ISR(PCINT0_vect), CHANGE);
 interrupts();
}

void loop(){
some other functions
}

ISR(PCINT0_vect){
   digitalWrite(ledPin3, HIGH);
 }

I'm not getting the led to turn on when the button on DP8 changes states.
Could anyone point me in the proper direction? I would be most appreciative.

vex

#1
Nov 21, 2010, 12:36 am Last Edit: Nov 21, 2010, 12:36 am by vex Reason: 1
I realize that, so I'm trying to add additional pins using Atmega commands, in the same way that the Arduino Mega gains additional interrupts. As I understand it, all IO pins on Atmega are covered by Pin Change Interrupts.

vex

http://www.arduino.cc/playground/Main/PcInt
http://www.arduino.cc/playground/Main/PinChangeInt
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1259918394/15

billroy

#3
Nov 21, 2010, 12:51 am Last Edit: Nov 21, 2010, 12:52 am by billroy Reason: 1
I believe the problem is this: there are two types of pin related interrupts, and attachInterrupt() only handles one kind.  The wrong one, for your application.

The kind that attachInterrupt() handles is the External Interrupt Request, which is bound to the INT0 and INT1 pins.

The kind you seem to be requiring is a Pin Change interrupt, a different beast.  Any pin can be configured to generate this kind of interrupt; you set PCICR, PCIFR, and the appropriate PCMSKn.

Searching on pin-change interrupt here in the forum may be helpful as will be a look at the data sheet for the '328 at Section 12.2/page 71 from this url:

     http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf

Best,

-br
http://bitlash.net
http://entropymouse.com

edit: great links vex!


vex

Hmm, that makes sence. The closest replacement I can find for attachInterrupt() is in the third link I posted, where this code is claimed to work for pin 5:
Code: [Select]
ISR(PCINT2_vect)
{
 if (PIND & B00100000) // evaluates to TRUE when PortD bit #5 (Arduino digital pin #5) is HIGH
 {
   counter1++;
 }
}


Unfortunately, I have no idea what the binary part means as it seems to correspond to pin #4.

vex

Quote
Your example is NOT an "interrupt". It is simply an example of "polling". i.e. just going out at some specified time and saying "does this equal that?" Very much different than an interrupt.  They could just as easily have said: if digitalRead(5) Then counter1++

In the context of the persons code, it is. "ISD()" is apparently an AVR interrupt command, run on  "PCINT2_vect", the Atmega equivalent of pin 5, in the attached libraries.
Quote

Your other examples show extentions to the Arduino base functionality.  Apparently there are features in the Atmel chip which the Arduino basic language doesn't implement. So they have extentions that you can use to get to those other features. But you must use the special code and syntax. You can't simply use attachInterrupt() as it only supports the pins defined by the definition page.
All of them do. Interrupt pins aren't "hard-wired", like you said, into the Atmega; that's how the Arduino Mega can use the same chip and have more native interrupts. And yes, I understand that I can't use attachInterrupt(), I have to use some variation of ISR(). That's what I'm asking about.

vex

Quote
But your example clearly shows "attachInterrupt(8, ISR(PCINT0_vect), CHANGE);"  and the documentation clearly doesn't support that.

Sorry, I meant that I "understand that" after reading billroy's post.

If you want some sample code that uses pin change interrupts on arbitrary, specifiable pins, take a look at the OrangutanPulseIn code from the Pololu AVR Library.  Once you download the library, you can find the source code in the directory:

libpololu-avr/src/OrangutanPulseIn

The library code is documented in the command reference; this might help you better understand what it's doing.

I hope you find this more helpful than confusing!

- Ben

Quote
Unfortunately, I have no idea what the binary part means as it seems to correspond to pin #4.

I don't understand you're confusion here.  The statement is checking to see if the fifth bit of the digital input register for port D (PIND) is set:

PIND & B00100000

Why are you interpreting this as pin 4?

One key thing to note about pin change interrupts is that there is only one ISR per port, so if you have configured multiple pins from the same port to generate pin change interrupts, you need to do some extra computation in the ISR to figure out which pin actually changed.  External interrupts are nicer because you automatically know which pin caused the interrupt and what edge was detected.

- Ben

vex

Hey, that Pololu thing really helps, thanks!

And lol, I thought that since 00100000 in binary equaled 20 it must refer to Atmel 20 -> DP4.

Thanks a bunch!

Hah, that is a pretty convoluted way to get to pin 4!  Also, 00100000 is 20 in hex (it's actually 32 in decimal) :)

- Ben

Go Up