0
\$\begingroup\$

I'm trying to get ATTINY85 to trigger ONLY on HIGH interrupt, but no matter what combination of bits I set for GIMSK and MCUCR, I can't get it to work;

Here's my code:

#define F_CPU 1000000UL

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

int main(void)
{
    DDRB  = 0b00011000; 

    setup();

    PORTB = 0b00010000;

    while(1) {}

    return 0;
}

void setup()
{
    GIMSK = 0b01100000;  
    PCMSK = 0b00000010;   
    MCUCR = 0b00000011;   
    sei();            
}

ISR(PCINT0_vect)
{
    PORTB = 0b00011000;
    delayms( 100 );
    PORTB = 0b00010000;
}

Based on the datasheet, if I set the bits in MCUCR the following way, I should be able to accomplish my result with the last option:

ISC01 ISC00

0     0         The low level of INT0 generates an interrupt request.
0     1         Any logical change on INT0 generates an interrupt request.
1     0         The falling edge of INT0 generates an interrupt request.
1     1         The rising edge of INT0 generates an interrupt request

I tried all combinations, but absolutely nothing changed. Then I changed:

GIMSK = 0b01100000;

To

GIMSK = 0b00100000;

That made the interrupt trigger on HIGH, but that's where it left off, if I connect pin to high again, the interrupt is not triggered, same if I connect it to LOW. Only the first time when the controller is turned on and pin is connected to HIGH.

How can I make the interrupt trigger only when the pin gets HIGH, not both - HIGH and LOW. I want every time I press a button, interrupt to trigger, but NOT when I release the button. Any suggestions? Thanks!

\$\endgroup\$
  • \$\begingroup\$ Did you try clearing the corresponding interrupt flag inside the ISR? You have to; otherwise the MCU cannot be ready for the next interrupt. \$\endgroup\$ – Rohat Kılıç Oct 19 '16 at 14:40
  • \$\begingroup\$ @RohatKılıç thanks for the tip, I will try that, but this can't be set in initialization so that I don't have to set it in ISR? \$\endgroup\$ – 0x29a Oct 19 '16 at 14:46
  • 1
    \$\begingroup\$ @RohatKılıç I'm 99% sure the interrupt flag is cleared automatically in AVRs. \$\endgroup\$ – Brendan Simpson Oct 19 '16 at 14:50
  • \$\begingroup\$ If all else fails use a divide by 2 flip flop on the input \$\endgroup\$ – Andy aka Oct 19 '16 at 15:06
3
\$\begingroup\$

There are several things to consider:

  1. The only pin that can be configured for a specific edge change is pin 7, which is PB2. So, your pushbutton should be connected to that pin.
  2. It would be a good practice to pull this pin to ground with a 10k resistor, to make sure it is not floating (i.e. can not make a high on its own).
  3. Set the bit 6 of the GIMSK register to 1 to enable INT0.
  4. Set bits [1:0] of the MCUCR regiter to 11 to generate the interrupt only on the rising edge.
  5. Set bit 0 of DDRB register to 1 to make it output. That is, PB0 pin would be the output.
  6. Change the interrupt ISR(PCINT0_vect) to ISR(INT0_vect). There is a difference between PCINT0 and INT0.
  7. You can toggle the pin PB0 in your ISR as follows: PORTB = PORTB ^ 0x01
  8. It is not a good practice to have a delay in the ISR
  9. It would be good to implement a de-bounce subrountine to make sure that when you press the button, the INT0 triggers only once.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.