Electrical – ATTINY85 interrupt confusion

interrupts

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!

Best Answer

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.