Arduino/AVR: Interrupt only works once

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

I've implemented an interrupt in my program, so that when a button is pressed, the program does something. This works and it's all fine. The program gets interrupted from A, does B, and returns to A.

My issue:

Once returned to A, I can't re-interrupt the program. I've tried adding `buttton_init();` after `ledGood();`, but then my program stops working all together!

Here's what I have so far:

    static void button_init(void)
    {
        PORTB |= (1<<PB2); /* enable pull-up */
        PCICR |= (1<<PCIE0); /* enable Pin Change 0 interrupt */
        PCMSK0 |= (1<<PCINT2); /* PORTB2 is also PCINT42*/
    }
    
    ISR(PCINT0_vect) /* pin change interrupt service routine */
    {    
        ledInProgress();
        
        int count = 0;
        while (count < 100) {
            _delay_ms(200);
            count++;
        }
        
        /* Let the user know we've finished */
        ledGood();
    }
    
    int main(void)
    {    
       /* Init the interrupt button */
       button_init();
       
        /* Enable interrupts globally - cli() would clear this! */
       sei();
       
       /* set PORTB for output/input*/
       DDRB = 0b11011111;
       
        while(true)
        {
            sleep_mode();
        }
    }

 

This topic has a solution.
Last Edited: Thu. Jun 8, 2017 - 07:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If button is on PB2, why make in an output in:

DDRB = 0b11011111;

I believe that should be:

DDRB = 0b11111011;

David

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

You're right.

 

It's still not working though..

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

what's in sleep_mode(), ledGood() & ledInProgress()?

 

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

sleep_mode() is an AVR-libc function:

 

http://avr-libc.nongnu.org/user-...

 

The LED functions just turn the LEDs on:

 

ledGood()

 

void ledGood() {
	PORTB = (1<<PB4);
}

 

ledInProgress()

 

void ledInProgress() {
	PORTB = (1<<PB3);
}

 

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

By using out right assignment you are turning off the pull-up resistor on PB2. Try using |= rather than =.

 

Edit: To explain further...

	PORTB = (1<<PB4);

will set PORTB to 0b0001000. Thus bit 2 is clear, thus the pull up is disabled. The same applies with

	PORTB = (1<<PB3);

 

Last Edited: Thu. Jun 8, 2017 - 07:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, I knew it would be something like that, I just couldn't figure out what. Do you know of any good resources for bit values, etc? (not limited to the Arduino, more assignment related stuff).

 

One thing though..

 

Now, I get an turqoise colour in my RGB LED (ledInProgress = blue, ledGood = green). I know this is because I have both pins toggled at the same time, but I'm not sure why :(
 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You get a turquoise colour because you have both the blue and green leds on at the same time. When you do 

PORTB |= (1<<PB4);

You essentially set bit 4 of PORTB, but the other 7 bits are left unaffected. so for example, if before that line of code is executed PORTB = 0b11001001, then afterwards it would be 0b11011001.

 

If you google 'bit manipulation in C' or something to that effect you should find plenty on it, but in general:

 

Set a bit: REG |= (1<<BITn);

Clear a bit: REG &= ~(1<<BITn);

Toggle a bit: REG ^= (1<<BITn);

Checking if a bit is set: REG & (1<<BITn);

 

For example...

if (PORTB & (1<<PB2)) {   // if bit 2 of port B is high
    PORTB |= (1<<PB4);
} else {
    PORTB &= ~(1<<PB4);
}

Note: BITn = bit number.

 

Just for clarification, the (1<<PB4) part means 1, shifted left by 'PB4' times, and you'll find PB4 #define'ed as 4, so:

0000 0001

0000 0010

0000 0100

0001 0000

 

PORTB |= (1<<PB4); is essentially the same as PORTB |= 0b00010000;

Last Edited: Thu. Jun 8, 2017 - 08:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're amazing. Thank you!

 

 

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

No problem. Also worth knowing, if you're using Atmel Studio 7 you can use IO View to observe various registers and the effects your code has on them.