PORTB pin change and INT0 interrupts on ATtiny87

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

Can I enable both INT0 and PORTB pin change interrupts on an ATtiny87?  My pin change interrupt is working, but not the INT0.  The only enabled pin change interrupt is PB0. INT0 is PB6.

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

Quote:
Can I enable both INT0 and PORTB pin change interrupts on an ATtiny87?
Yes you can.

 

What do you mean by 'not working'?  Can you show some code?

 

"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]

 

Last Edited: Sat. Aug 22, 2015 - 01:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I can.

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

I stripped out all the code except for the two interrupts, and now it is working (i.e., functioning correctly, behaving as it should.)  I'll add the rest of the code gradually to find the offending bits.  Thanks, anyway.

 

Doug

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

The code is not working.  I forgot that I polled the INT0 pin just to make sure that everything was hooked up correctly on the PCB.  It is.  When I poll PORTB, pin 6, the code works.  When I don't poll, FallISR never executes when the INT0 pin falls.  What am I missing?

 

;***************************************************************************
.CSEG                                             ;Code Segment.

.org    $000                                    ;Interrupt vectors.

        rjmp    Main                            ;Reset.
        rjmp    FallISR                         ;INT0.
        rjmp    Main                            ;INT1.
        rjmp    Main                            ;Pin change 0.
        rjmp    BuckleChangeISR        ;Pin change 1.                
                                                                
;**************************************************************************

Main:    ldi     Temp1, 0x02           ;Set stack pointer to bottom of RAM.
            out    SPH, Temp1            ;SRAM address space is 0x100 to 0x2FF.
            ldi     Temp1, 0xFF
            out    SPL, Temp1
        
            ldi     Temp1,0b00101110   ;XTAL2, SCL, SDA, and Sounder are outputs.
            out    DDRB,Temp1
                                
            ldi     Temp1,0b01000101   ;Pull up on Hi-G IRQ, SDA, and BUCKLE.
            out    PORTB,Temp1

 

            ldi     Temp1,0b00000010   ;Enable pin change interrupts on PortB.
            sts    PCICR,Temp1  

 

            ldi     Temp1,0b00000001   ;Only PB0 (buckle) pin change interrupt
            sts    PCMSK1,Temp1          ;is enabled on PortB.

 

            ldi     Temp1,0b00000010   ;INT0 is activated with a falling edge.
            sts    EICRA,Temp1  

     

            ldi     Temp1,0b00000001   ;Enable INT0 external interrupt.
            sts    EIMSK,Temp1 

   

MainLoop:    
            sei
            nop
            nop
            nop

 

;           sbis    PINB,6        ;Is the Hi-G IRQ input high?
;           rcall    FallISR        ;Yes, so toggle PORTB, pin 5.

 

           rjmp    MainLoop    ;Keep looping.

 

BuckleChangeISR:
            sbi        PINB,1        ;Toggle PORTB, pin 1.
            ret  

 

FallISR:
            sbi        PINB,5        ;Toggle PORTB, pin 5.
            ret        

;***************************** END OF PROGRAM ******************************************/

 

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

The comment after "rcall   FallISR" in the MainLoop should read, "No, so toggle PORTB, pin 5."

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

Why are you using RET in the ISRs?  You should be using RETI.  Then there is no need put SEI in the main loop, only in setup code in main.

 

No need for the NOPs, either.  Just an empty loop will do.

 

However I think this may be your problem:

            sts    EIMSK,Temp1

This should be:

            out    EIMSK,Temp1

... because EIMSK is at I/O address 0x1D.  Using STS will result in writing to SRAM address 0x1D which is mapped to the general purpose register r29.

 

You still haven't answered what you mean by 'not working'.  Describe what you are >>doing<< i.e. what signals are you applying to PB1/PCINT8 and PB6/INT0, how are you applying them?  How are you monitoring the outputs on PB1 and PB5?  Are they driving LEDs?  Are you capturing them with a scope?

 

Have you tried a test program which enables >>only<< INT0 (without enabling PCINT8) i.e. does INT0 work by itself?

 

"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]

 

Last Edited: Sat. Aug 22, 2015 - 10:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are a little demanding and a little condescending, and it is a little annoying, but you might know something that could help me, and so I'm going to answer your questions:

 

I don't like to use interrupts.  I would rather poll for information, because when you use interrupts, you must always ask yourself "What if an interrupt occurs here?" for every line of code and consider the consequences.  But this product I am currently designing must have an extended battery life, and so I will be asleep for 59.9 seconds of every minute, but there are two inputs which must be monitored while I am asleep.  So I will only be enabling interrupts while the uC is asleep.  That is why the ISRs have "ret" instead of "reti".  When the uC is awakened from sleep by an interrupt, I do not want interrupts to be enabled until the uC goes back to sleep in 100 msecs.  I thank you for your concern, however, about me potentially using "ret" inefficiently.

 

The code you see is stripped down and simplified from the actual code, only showing the pertinent parts.  I thought it would be less confusing that way.  I only added the NOPs for looks, to give the MainLoop a little body.  Sorry.

 

You would like to know what signals are being applied to PB1 and PB6.  I think you meant to write PB0 and PB6.  PB6 is a 3.3 volt push-pull digital signal from a sensor IC.   PB1 comes from an open collector output which is pulled up to 3.3 volts with a 10k resistor. 

 

I am monitoring the outputs (PB1 and PB5) with an oscilloscope.

 

By "not working" I mean that when a falling edge occurs at PB6, PB5 does not toggle.

 

You asked, "Have you tried a test program which enables >>only<< INT0 (without enabling PCINT8) i.e. does INT0 work by itself?"  Are you not sure that both the Pin Change Interrupt and External Interrupt can be used simultaneously?

 

Thanks for the "out" vs. "sts" tip.  I expect that is the problem.

 

Gratefully,

 

Doug

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

Quote:
I don't like to use interrupts.
Your thread is titled "PORTB pin change and INT0 interrupts on ATtiny87", so I guess there is an expectation that the thread will be about interrupts.  Whether or not you like them is not likely to matter to anyone.

 

Quote:
That is why the ISRs have "ret" instead of "reti".
That approach will miss the case where >>both<< interrupts occur at the same time (or one wakes the device, and the other occurs before going back to sleep) .  Using RETI lets you handle that case simply.  You >>could<< handle that case by polling interrupt flags after the higher-priority interrupt's (or first-to-occur interrupt's) ISR returns, but that seems needlessly complex.  Perhaps your app doesn't require that you handle this case.  If that is so, you need at least to clear the interrupt flags before going to sleep, otherwise the second unserviced interrupt from the >>last<< sleep interval will immediately wake the AVR in the >>next<< sleep interval.

 

None of this is relevant to your problem, of course (STS instead of OUT).

 

Quote:
I think you meant to write PB0 and PB6.
Indeed.  I wrote PB1/PCINT8, whereas PCINT8 is on PB0.  Just a typo.

 

Quote:
Are you not sure that both the Pin Change Interrupt and External Interrupt can be used simultaneously?
I am indeed sure.  One has no impact on the other.  I was asking >>you<< what work >>you<< had done to try to narrow down the problem.  Since you didn't mention that INT0 didn't work, only that it didn't work >>with pin change interrupts<<, it is a natural question to ask what you had done to break the problem down into smaller parts.

 

Douglas Holub wrote:
You are a little demanding and a little condescending, and it is a little annoying, but you might know something that could help me, and so I'm going to answer your questions:
Well, no good deed goes unpunished, I guess...

 

I see you've only joined AVR Freaks a few months ago, and have made only a handful of posts.  Perhaps you haven't had a chance yet to read these:

https://www.avrfreaks.net/forum/newbie-start-here

http://www.catb.org/%7Eesr/faqs/smart-questions.html

 

These are valuable resources which will help you get your questions answered faster and more effectively.  They will also keep you from getting frustrated, or from causing frustration for others.  There is no faster way to get ignored than asking for free help, and then getting defensive about the help you are getting, especially when nobody is attacking you.

 

You'll find that more often than not, if you come here (or to any other embedded or programming forum) with a code-related question, you will be asked to show some code which demonstrates the problem, along with a full description of the troubleshooting work you have done thus far.  This isn't an attack, nor condescension.  It is the quickest path to a solution.

 

Good luck with your project, Douglas.

 

"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]