Interrupt Vector Setup

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

 

I am using a ATmega324P, and I am trying to set pin PA7/ PCINT7 as an external interrupt.  Reading the datasheet on page on page 79 it mentions this pin can be used as an external interrupt. My next task is to get it to work.  I have tried the below examples but this does not work.

 

I would appreciate if somebody could point out what I am doing wrong and if the below actually sets up PA7/ PCINT7 as an external interrupt.

 

Thanks in advance.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/portpins.h>
#include <avr/interrupt.h>

#define F_CPU 4000000UL

void hw_setup(void)
{
    DDRA = 0x00;                   // set portA as input
    PORTA.INT0MASK = 0x40;  // bit PC7

}

ISR(PORTA_INT0_vect)
{
     print("Hello World")
    
}

 

 

int main(void)
{

    hw_setup();
    
    sei();

    while(1)
    {
        

    }
}

      Also I have tried the below ISR and this does not work either.  

ISR(PCINT7_Vect)
{
     print("Hello World")
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    PORTA.INT0MASK = 0x40;  // bit PC7

Where did you get this syntax from? As far as I know the tiny/mega headers do not define the ports as structures/bitfields ?!? I guess you mean something like:

PCICR |= (1 << PCIE0);
PCMSK0 |= (1 << 7);

but I have no idea which pin you want to use - the comment in your code says "PC7" but PC7 has never been a part of PORTA ?!? Did you mean "PA7". Setting (1<<7) in PCMSK0 should enable that as an interrupt source.

ISR(PORTA_INT0_vect)

Where did you get that made up name from. When I inspect the header for 324 I find:

/usr/lib/avr/include/avr$ grep _VECTOR iom324*
iom324pa.h:#define INT0_vect      _VECTOR(1)  /* External Interrupt Request 0 */
iom324pa.h:#define INT1_vect      _VECTOR(2)  /* External Interrupt Request 1 */
iom324pa.h:#define INT2_vect      _VECTOR(3)  /* External Interrupt Request 2 */
iom324pa.h:#define PCINT0_vect      _VECTOR(4)  /* Pin Change Interrupt Request 0 */
iom324pa.h:#define PCINT1_vect      _VECTOR(5)  /* Pin Change Interrupt Request 1 */
iom324pa.h:#define PCINT2_vect      _VECTOR(6)  /* Pin Change Interrupt Request 2 */
iom324pa.h:#define PCINT3_vect      _VECTOR(7)  /* Pin Change Interrupt Request 3 */
iom324pa.h:#define WDT_vect      _VECTOR(8)  /* Watchdog Time-out Interrupt */
iom324pa.h:#define TIMER2_COMPA_vect      _VECTOR(9)  /* Timer/Counter2 Compare Match A */
iom324pa.h:#define TIMER2_COMPB_vect      _VECTOR(10)  /* Timer/Counter2 Compare Match B */
iom324pa.h:#define TIMER2_OVF_vect      _VECTOR(11)  /* Timer/Counter2 Overflow */
iom324pa.h:#define TIMER1_CAPT_vect      _VECTOR(12)  /* Timer/Counter1 Capture Event */
iom324pa.h:#define TIMER1_COMPA_vect      _VECTOR(13)  /* Timer/Counter1 Compare Match A */
iom324pa.h:#define TIMER1_COMPB_vect      _VECTOR(14)  /* Timer/Counter1 Compare Match B */
iom324pa.h:#define TIMER1_OVF_vect      _VECTOR(15)  /* Timer/Counter1 Overflow */
iom324pa.h:#define TIMER0_COMPA_vect      _VECTOR(16)  /* Timer/Counter0 Compare Match A */
iom324pa.h:#define TIMER0_COMPB_vect      _VECTOR(17)  /* Timer/Counter0 Compare Match B */
iom324pa.h:#define TIMER0_OVF_vect      _VECTOR(18)  /* Timer/Counter0 Overflow */
iom324pa.h:#define SPI_STC_vect      _VECTOR(19)  /* SPI Serial Transfer Complete */
iom324pa.h:#define USART0_RX_vect      _VECTOR(20)  /* USART0, Rx Complete */
iom324pa.h:#define USART0_UDRE_vect      _VECTOR(21)  /* USART0 Data register Empty */
iom324pa.h:#define USART0_TX_vect      _VECTOR(22)  /* USART0, Tx Complete */
iom324pa.h:#define ANALOG_COMP_vect      _VECTOR(23)  /* Analog Comparator */
iom324pa.h:#define ADC_vect      _VECTOR(24)  /* ADC Conversion Complete */
iom324pa.h:#define EE_READY_vect      _VECTOR(25)  /* EEPROM Ready */
iom324pa.h:#define TWI_vect      _VECTOR(26)  /* 2-wire Serial Interface */
iom324pa.h:#define SPM_READY_vect      _VECTOR(27)  /* Store Program Memory Read */
iom324pa.h:#define USART1_RX_vect      _VECTOR(28)  /* USART1 RX complete */
iom324pa.h:#define USART1_UDRE_vect      _VECTOR(29)  /* USART1 Data Register Empty */
iom324pa.h:#define USART1_TX_vect      _VECTOR(30)  /* USART1 TX complete */
iom324pa.h:#define _VECTOR_SIZE 4 /* Size of individual vector. */
iom324pa.h:#define _VECTORS_SIZE (31 * _VECTOR_SIZE)

From that the vector associated with PORTA would therefore be PCINT0:

iom324pa.h:#define PCINT0_vect      _VECTOR(4)  /* Pin Change Interrupt Request 0 */

So your code would be:

ISR(PCINT0_vect)
{
     print("Hello World")

}

or at least it would be if there were such a thing as print() - but there isn't. The closest thing C has is the function printf() but in avr-gcc you cannot just call that without some setup - the C compiler has no idea what your output device is going to be (UART, LCD, etc). Also it is NEVER a good idea to call a "long" function like printf() form an interrupt handler.

 

Oh and finally please don't say you are trying to read a button input using PCINT7 - because of contact bounce you should never use INTn/PCINTn for reading input states (though you might use it simply to wake the AVR from sleep if you plan a sleeping battery powered application)

Last Edited: Tue. Jan 12, 2016 - 05:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson,

 

Thanks for your help.  Yes I found that code as an example then tried to edit for my processor but I was getting errors.  Also it is for PA7/ PCINT7 so yes you were correct.  

 

When it is all up and running, then I want to put the processor to sleep, and wake up on this external interrupt pin.  I will come back to this another time if I get stuck.

 

Thanks again.

 

Tuurbo46

#include <avr/io.h>
#include <util/delay.h>
#include <avr/portpins.h>
#include <avr/interrupt.h>
#define F_CPU 4000000UL

void hw_setup(void)
{
    DDRA = 0x00;                   // set portA as input
    PCICR |= (1 << PCIE0);         
    PCMSK0 |= (1 << 7);            // PA7
}
ISR(PCINT0_vect)
{
     printf("Hello World") // For testing purposes
  
}
 
 
int main(void)
{
    hw_setup();
    
    sei();
    while(1)
    {
        
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

printf() still won't work

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok thanks.

 

One last question, do I have to set what level the interrupt will trigger.  I want it to fire from logic low to high.  So on logic high the interrupt is triggered.

 

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK after further reading, and it not working.  I have added two more lines.

 

EICRA = 0x03;      // Enable interrupt to trigger on rising edge

 

EIFR = 0x01;       // clear interrupt 0

 

It still does not work, am I still missing setup parameters?

 

#include <avr/io.h>
#include <util/delay.h>
#include <avr/portpins.h>
#include <avr/interrupt.h>
#define F_CPU 4000000UL

int8_t Flag;

void hw_setup(void)
{
    DDRA = 0x00;                   // set portA as input
    PCICR |= (1 << PCIE0);         
    PCMSK0 |= (1 << 7);            // PA7
    EICRA = 0x03;                  // Enable interrupt 0 to trigger on rising edge
}
ISR(PCINT0_vect)
{
     Flag;
     EIFR = 0x01; // clear interrupt 0
}
 
 
int main(void)
{
    hw_setup();
    
    sei();
    while(1)
    {
     
        
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

[non relevant text removed]

 

Jim

 

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Tue. Jan 12, 2016 - 07:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you mean "does not work"?

 

Re-read the datasheet section on external interrupts.  Pin-change interrupts trigger on both edges.  EICR has nothing to do with pin-change interrupts, does it?

 

Also, if using a button to test, buttons bounce so you will get typically several pin-change "hits" every time you press the button.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Tue. Jan 12, 2016 - 08:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Also, if using a button to test, buttons bounce so you will get typically several pin-change "hits" every time you press the button.

Yup, but since this is the "wake-up botton" this will not be a problem, right? If the device isn't sleeping,the it just isn't sleeping and the wake-up interrupt will do no harm?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As others have said I think you really do need to take a step back and do some datasheet reading before jut throwing some random bits of C into your text editor. Good programs start with good design. That means reading and researching the background of what you wan to achieve. Then sketching out some strategy of how you are going to achieve that. Then adding more detail to that until you know the exact sequence of steps you need. Finally you start you text editor and write some C that matches the design/specification you have come up with.

 

The opposite technique of "grapeshot C" where you throw a few lines of C into an editor, build/try that. It doesn't work. You go back and remove that stuff and throw some more random lines of C into your editor is not a great approach. It's said that an infinite number of chimps at an infinite number of typewriters may eventually end up typing the works of Shakespeare - but it could take a while!

 

As I review this thread it seems you are pretty intent on using PA7 as your "input". While I would question the choice of that if you really do mean PA7 then the datasheet tells you that the only uses of PA7 (apart from the obvious one as GPIO) are either ADC channel 7 or Pin Change  interrupt 7. I'll assume you intend to use it as the latter. So next you would find out about pin change interrupts. In my copy of the 164/324/644/1284 data that is in chapter 13 under "External Interrupts". That chapter is possibly a little confusing as it talks about two different kinds of external interrupt. The INTn type and the PCINTn type. As PA7 is only PCINT7 then anything relating to INTn is irrelevant and that includes anything you read about "rising edge", "falling edge", "level interrupts". A PCINT signal is not that sophisticated. In fact it is very simple indeed. You can turn it on for one or more pins and then if the signal input to those pin(s) changes from 1 to 0 or 0 to 1 you are notified. Nothing more, nothing less.

 

When you read about PCINTn (not INTn) you find that they are grouped in 8's. Singals PCINT0..PCINT7 are related to PORTA, PCINT8..PCINT15 for PORTB, PCINT16..PCINT23 for C and PCINT24..PCINT31 for port D.

 

Unfortunately Atmel also made a very unwise choice of also using PCINT0..PCINT3 to be the names of these four groups of 8. So sometimes PCINT2 (say) will refer to the 3 pin of PORTA and sometimes it means "the complete group of pins for PORTC". So you have to watch for this!

 

Now when you read section 13.2 about "Register Description" you will see mention of EICRA, EIMSK and EIFR. You should ignore these - they are only involved with INTn, nt PCINTn. All the registers that relate to the PC (Pin Change) interrupts start with the letters PC - those are PCICR, PCFR, PCMSK0, PCMSK1, PCMSK2, PCMSK3. The first two of those have control for all four groups of PC ints (Ports A, B, C and D) while the PCMSK registers each relate to a single port. PCMSK0 for A, PCMSK1 for B, PCMSK2 for C and PCMSK3 for D. So if you are only interested in PA7 then the only three of these registers you need concern yourself with are PCICR, PCMSK0 and PCFR (though you may never read/write the latter at all in fact!). In PCICR there are four active bits PCIE0..PCIE3. Because it is PA7 on PORTA you are interested in then of these it is only PCIE0 that will concern you. By setting it to 1 you arrange to potentially get a pin change interrupt from any pin on PORTA as it "turns on" the signals from PORTA. However if you set that alone nothing would happen. As well as turning on A as a source you have to say which of the pins in A you are interested in hearing about changes from and you do that with bits 0..7 in PCMSK0. As it's just PA7 then the only bit there you want to set is bit 7 (that the datasheet calls PCINT7). So to use pin change interrupts on PA7 you now know your C is going to be:

int main(void) {
    PCICR = (1 << PCIEO); // switch on "A"
    PCMSK0 = (1 << PCINT7); // just get interrupts for pin 7 in A
...

And that is pretty much it. Now when PA7 changes the PCIF0 bit in PCFR will be set. So without using interrupts you could use:

int main(void) {
    PCICR = (1 << PCIEO); // switch on "A"
    PCMSK0 = (1 << PCINT7); // just get interrupts for pin 7 in A
    while(1) {
        if (PCFR & (1 << PCIF0)) {
            // pin has changed: do something
            PCFR = (1 << PCIF0); // clear the flag
        }
    }

but usually you want to do something else in the while(1) and get notified about the pin change separately (in which case you can ignore PCIFR all together as bits getting set in it automatically trigger a switch to your ISR code). So you would use something like:

int main(void) {
    PCICR = (1 << PCIEO); // switch on "A"
    PCMSK0 = (1 << PCINT7); // just get interrupts for pin 7 in A
    sei()
    while(1) {
    }
}

ISR(PCINT0_vect) {
    // could get here for any of 0..7 on A but as only 7 is enabled
    // it must be a change on PA7 if we get here
}

Notice that the interrupts (there are potentially 4) are called PCINT0_vect, PCINT1_vect, PCINT2_vect and PCINT3_vect. Each one relates to a whole port. Not a single pin. So changes on PA0..PA7 might trigger PCINT0_vect. changes on PB0..PB7 might trigger PCINT1_vect and so on. This is where that choice of Atmel's to use PCINT0..PCINT3 to mean two different things can be confusing.

 

So, did you see what I did in all that? I read the datasheet. I figured out what were the salient details and what were the details to be ignored. I then determined that for that salient stuff what I would need to put into each register and finally I created some C code that put actions into words.

 

Having said all this I am not sure if it is PA7 and PCINT0 you really want to use. As I say this can only give interrupts for a CHANGE. It won't tell you what kind of change (0->1 or 1->0) - you would have to work that out yourself (by reading PINA after the interrupt occurs). A "more powerful" form of external interrupt is the INTn ones. They can give you interrupts for different conditions like only 1 to 0 transitions (falling) or only 0 to 1 transitions (rising) or the pin being held in a low or high state (level)

 

Your most recent code mentions "rising edge". If you really are going to be specifically looking for rising edge changes then forget PCINTn and PCICR, PCIFR, PCMSKn completely. You need to switch to focus on EICRA, EIFR and EIMSK but if you do that you need to relaise that the 324 chip only has three of them. They are on pins PD2, PD3 and PB2. So if you are going to use one of them you have to arrange for your input signal to route to one of those 3 pins. This is a decision you should be making early in the design process - not while you are already typing C code into your text editor.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff, did you notice that it was I and not the OP that asked the previous question?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johan, not sure of the point you are making? My post was a response to #6 (and indirectly #1).

 

in #6 I see him providing an ISR for PCINT0 but then messing with (the totally unrelated) EIFR within it. Equally in hw_setup() I see it messing with register relating to PA7 (which could be right) but also EICRA (which seems wrong - especially since EIMSK is then never touched).

 

I see you and Lee "discussing" the actual intent of the pin reading (wake from sleep or something else) but that seems to be a tangent to the core intention of simply getting ISR()s for pin activity.

 

My main point was not even the actual mechanism to achieve this (pin reading) but the importance of a methodical approach to design and avoiding "grapeshot".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your detailed explanation Clawson.

 

Tuurbo46.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Johan, not sure of the point you are making? My post was a response to #6 (and indirectly #1).

OK. It looked as if you where misinterpreting my post as being done by the OP. (I was in a narrow browser at the time where one can not see the avatars, and just had the gut reaction that you saw it the same way. Stupid me..)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
where one can not see the avatars

Am I the only one who HATES that with a vengeance? I almost never access Freaks with phone or tablet for this very reason. What's really annoying is that my tablet is 10.1" and yet I still don't get to see the avatars to easily identify the poster/flow. That's true even if I switch it to "request desktop site" so it's something  about the geometry and it clearly deciding that there isn't room. Yet it's pretty fundamental to actually reading the content of the page! At the very least, in that "shrunk" view I'd like to see the name of the posters in a bigger/bolder font.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I actually like it - on the rare occasions I access freaks on the 'droid phone. There would be very little room left for anything else if the avatars where there. I agree that the limit for when they occur/disappear seems to have been set a wee bit conservatively.

 

If you're really plagued I could see if this can be fixed by injecting some CSS to override what is being fed from the server. What browser on your tablet?

 

What I really miss is that I don't get to see the "n new" links in listings. Grrrrr...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Mon. Jan 18, 2016 - 12:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
What's really annoying is that my tablet is 10.1" and yet I still don't get to see the avatars to easily identify the poster/flow. That's true even if I switch it to "request desktop site" so it's something  about the geometry and it clearly deciding that there isn't room. Yet it's pretty fundamental to actually reading the content of the page! At the very least, in that "shrunk" view I'd like to see the name of the posters in a bigger/bolder font.
My suspicion is that avrfreaks is not detecting the size of your screen.

More likely it is detecting that you have a laptop-specific OS.

Perhaps this should go to the site feedback forum.

 

BTW I am on a desktop with a 12"+ wide screen with 1280x1024 pixels.

I'm not seeing any avatars nor any way to change that.

Perhaps the button is just too obscure for me to find.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
BTW I am on a desktop with a 12"+ wide screen with 1280x1024 pixels. I'm not seeing any avatars nor any way to change that.

Try a few Ctrl-minus, or whatever your browser command for "zoom out", until the print doesn't get any smaller.  Do you get avatars then?  In my Firefox, they disappear when I "zoom in" far enough...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ctrl-minus did the trick.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I really miss is that I don't get to see the "n new" links in listings. Grrrrr...

+1

 

My suspicion is that avrfreaks is not detecting the size of your screen.

It's not 'avrfreaks', it's the HTML delivered to your browser.  All the content is there (avatars, etc).  There is a script defined in the <head></head> section of each thread's page called jQuery.extend (48 kB!) which I believe is responsible for determining when to use each of the formats.  I'm no HTML expert, to be sure, but I think the identifier 'adaptivetheme' is involved.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]