EmbeddedRelated.com
Forums

AVR, polling INT0 IRQ bit - help?

Started by larwe July 10, 2008
I'm porting some old code that uses a pin-change interrupt flag as an
edge detector. The new target micro is an AVR (ATmega169). I'm having
real trouble getting the INT0 logic to work like I think it should.

I set DDRD = 0xe5 (INT0 is on bit 1 of port D), PORTD = 0x20, and
EICRA = EICRA  | ISC00_MASK | ISC01_MASK to look for positive edges.

I see the input pin wiggling away, but (EIFR & (1 << INTF0_BIT)) stays
zero forever.

Is there something more I need to initialize to get the interrupt
request flag to work?

Thanks...

larwe wrote:
> I'm porting some old code that uses a pin-change interrupt flag as an > edge detector. The new target micro is an AVR (ATmega169). I'm having > real trouble getting the INT0 logic to work like I think it should.
Interesting, I am porting the same code from 169 to 6502.
> > I set DDRD = 0xe5 (INT0 is on bit 1 of port D), PORTD = 0x20, and > EICRA = EICRA | ISC00_MASK | ISC01_MASK to look for positive edges.
As far as I know, pin change interrupts are on port B and E only. Please check the spec.
> > I see the input pin wiggling away, but (EIFR & (1 << INTF0_BIT)) stays > zero forever. > > Is there something more I need to initialize to get the interrupt > request flag to work? > > Thanks...
On Thu, 10 Jul 2008 11:27:27 -0700 (PDT), larwe <zwsdotcom@gmail.com>
wrote:

>I'm porting some old code that uses a pin-change interrupt flag as an >edge detector. The new target micro is an AVR (ATmega169). I'm having >real trouble getting the INT0 logic to work like I think it should. > >I set DDRD = 0xe5 (INT0 is on bit 1 of port D), PORTD = 0x20, and >EICRA = EICRA | ISC00_MASK | ISC01_MASK to look for positive edges. > >I see the input pin wiggling away, but (EIFR & (1 << INTF0_BIT)) stays >zero forever. > >Is there something more I need to initialize to get the interrupt >request flag to work?
Not familiar with the ATMega169, but what about setting INT0 in EIMSK? Quoting: http://www.atmel.com/dyn/resources/prod_documents/doc2514.pdf "External Interrupt Mask Register - EIMSK [...] Bit 0 - INT0: External Interrupt Request 0 Enable When the INT0 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control0 bits 1/0 (ISC01 and ISC00) in the External Interrupt Control Register A (EICRA) define whether the external interrupt is activated on rising and/or falling edge of the INT0 pin or level sensed. [...]" Regards, Gilles.
On Jul 10, 9:12=A0pm, linnix <m...@linnix.info-for.us> wrote:

> > I set DDRD =3D 0xe5 (INT0 is on bit 1 of port D), PORTD =3D 0x20, and > > EICRA =3D EICRA =A0| ISC00_MASK | ISC01_MASK to look for positive edges=
.
> > As far as I know, pin change interrupts are on port B and E only. > Please check the spec.
PCINT is on B and E, but INT0 is a dedicated, polarity-programmable interrupt on PD1. Well, I solved my problem - it turns out very simply the pin on the IC wasn't soldered properly. My scope probe was on the trace, not the actual pin - when I probed the pin I saw it wasn't actually changing. A drop of solder fixed the problem. However, do you have the port B PCINTs working in your application? I am now trying to get the same sort of functionality working on Note that I don't want to actually fire the interrupt - I just need to poll the pin-change IRQ bit for one of the pins of port B.
On Jul 11, 12:31=A0am, Gilles Kohl <gilles_delete_t...@compuserve.com>
wrote:

> >Is there something more I need to initialize to get the interrupt > >request flag to work? > > Not familiar with the ATMega169, but what about setting INT0 in EIMSK?
I don't want the interrupt to fire. As it turns out my problem was a silly one... see my other posting. But thanks for the reply.
On Jul 11, 5:16 am, larwe <zwsdot...@gmail.com> wrote:
> On Jul 10, 9:12 pm, linnix <m...@linnix.info-for.us> wrote: > > > > I set DDRD = 0xe5 (INT0 is on bit 1 of port D), PORTD = 0x20, and > > > EICRA = EICRA | ISC00_MASK | ISC01_MASK to look for positive edges. > > > As far as I know, pin change interrupts are on port B and E only. > > Please check the spec. > > PCINT is on B and E, but INT0 is a dedicated, polarity-programmable > interrupt on PD1. > > Well, I solved my problem - it turns out very simply the pin on the IC > wasn't soldered properly. My scope probe was on the trace, not the > actual pin - when I probed the pin I saw it wasn't actually changing. > A drop of solder fixed the problem.
OK
> > However, do you have the port B PCINTs working in your application? I > am now trying to get the same sort of functionality working on
Yes, I use four pins (E3 to E0) for buttons. Any button changes wake up the processor, which was put to sleep after a few minutes of idleing.
> > Note that I don't want to actually fire the interrupt - I just need to > poll the pin-change IRQ bit for one of the pins of port B.
I do need interrupt to get the uC out of sleep mode.
larwe wrote:
> > However, do you have the port B PCINTs working in your application? I > am now trying to get the same sort of functionality working on > > Note that I don't want to actually fire the interrupt - I just need to > poll the pin-change IRQ bit for one of the pins of port B.
I have used the port change interrupt to read an optical encoder. IIRC it had 3 bits of output, A, B, and index. PCINT was the best available option as all other resources were allocated. A minor problem with PCINT is that there is not a register indicating which pin changed to fire the interrupt. By the time you get around to reading it it may be unchanged (due to bouncing). So it helps to keep a copy of the prior values laying around to XOR the current values against. If (as in my case with the optical encoder) the value has to be stable for a bit to be valid, be prepared to exit the interrupt handler having done nothing. Unless the shaft was turning fast my optical encoder bounced a lot when it was making changes. The solution was once phase A or B changed to disable that pin change interrupt and enable the other. When one was changing the other was stable.
On Jul 11, 3:36=A0pm, David Kelly <n4...@Yahoo.com> wrote:

> If (as in my case with the optical encoder) the value has to be stable > for a bit to be valid, be prepared to exit the interrupt handler having
I'm not permitted to use interrupts in this code. I am simply trying to use the IRQ bit as an edge detector - which isn't working at all : ( I'm pretty baffled and wondering if this feature actually works. No response from Atmel FAE yet.
On 11/07/2008 larwe wrote:

> On Jul 10, 9:12&#4294967295;pm, linnix <m...@linnix.info-for.us> wrote: > > > > I set DDRD = 0xe5 (INT0 is on bit 1 of port D), PORTD = 0x20, and > > > EICRA = EICRA &#4294967295;| ISC00_MASK | ISC01_MASK to look for positive > > > edges. > > > > As far as I know, pin change interrupts are on port B and E only. > > Please check the spec. > > PCINT is on B and E, but INT0 is a dedicated, polarity-programmable > interrupt on PD1. > > Well, I solved my problem - it turns out very simply the pin on the IC > wasn't soldered properly. My scope probe was on the trace, not the > actual pin - when I probed the pin I saw it wasn't actually changing. > A drop of solder fixed the problem. > > However, do you have the port B PCINTs working in your application? I > am now trying to get the same sort of functionality working on > > Note that I don't want to actually fire the interrupt - I just need to > poll the pin-change IRQ bit for one of the pins of port B.
Sorry to come in late on this one. But it should be possible to do what you want. Let's say for example that you want to get a signal from a pin change on PB7. Then you need to do the following: Set DDRB bit 7 Set PORTB bit 7 to enable the internal pull-up on PB7 Clear the PUD bit in MCUCR to enable internal pull-ups globally Set PCMSK1 bit 7 (PCINT15 bit) Set EIMSK bit 7 (PCIE1 bit) Clear SREG bit 7 (I bit) Now any change on PINB7 should set bit 7 in EIFR (PCIF1). Note that in order to clear this bit, you must write a 1 to it when it is set, HTH -- John B
On Jul 13, 4:57=A0pm, "John B" <spamj_baraclo...@blockerzetnet.co.uk>
wrote:

> Set DDRB bit 7
Set? That makes it an output.
> Set PORTB bit 7 to enable the internal pull-up on PB7 > Clear the PUD bit in MCUCR to enable internal pull-ups globally > Set PCMSK1 bit 7 (PCINT15 bit) > Set EIMSK bit 7 (PCIE1 bit) > Clear SREG bit 7 (I bit)
Is it necessary to set PCIE1 if you do not actually want the IRQ to fire? I want/need to poll this bit in mainline code, I can't let an ISR grab it. (Having said this, the IRQ wouldn't fire when I tried it the normal way, with PCIE1 set, anyway).