0
votes

I was recently trying to make an interrupt on my atmega328p using atmelstudio to make a LED that is connected to digitalpin 13/PB5/PCINT5 blink four times as slow as normal when the button that is connected to a 5V output and digitalpin 2/PD0/PCINT18 is pressed down.

But whenever I run the code and press the button it will never(as far as i can tell) go true the interrupt code.

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

volatile int t = 1;
int main(void)
{
    init();
    Serial.begin(9600);
    DDRB = (1 << 5);
    DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
    // PD2 (PCINT0 pin) is now an input

    PORTD |= (1 << PORTD2);    // turn On the Pull-up
    // PD2 is now an input with pull-up enabled



    EICRA |= (1 << ISC00);    // set INT0 to trigger on ANY logic change
    EIMSK |= (1 << INT0);     // Turns on INT0

    sei();                    // turn on interrupts
    Serial.println("loop started");

    while(1)
    {
        PORTB ^= (1 << 5);
        delay(500*t);
    }
}



ISR (INT0_vect)
{
    Serial.println("interrupt");
    if(t=1){
        t=4;
    }
    else{
        t=1;
    }
}

I went through the datasheet multiple times and eventually stumbled onto this code online (yea yea i know i'm a real piece of work) and added my own pieces to it. but it even this does not work, does anybody know why?

1
if(t=1) enable/read compiler warnings. There is no way this compiles cleanly with gcc. Also, drop printing from inside an ISR, toggle a pin or something instead. - Lundin
If you enable a pull-up on a digital input, then you must connect it to GND via the button, not to 5V. - linuxfan says Reinstate Monica
Calling a library function like Serial.println in an interrupt is pretty risky and unlikely to work unless the library was designed to be called from interrupts like that. For instance, the println function probably waits in a loop for all the bytes to be sent, but they can't be sent because the USART interrupt sends them and only one interrupt can happen at a time. I suggest just writing to a volatile variable in your interrupt and returning. Your main loop can check the value of the variable and change it back after detecting that the ISR wrote to it. - David Grayson

1 Answers

1
votes

There are a few possible problems in your code:

  1. The most important is the assignment in the if condition that was already mentioned in the comments.
  2. clearly another one is the also mentioned serial.print stuff in the ISR.
    ISRs should be as short and simple as possible.

  3. Another is the hardware. If you press a button, they bounces and usually give multiple interrupts. so look for some de-bouncing code or have a look in the arduino library if there is something there. you may have to change the code, because usually the hardware logic itself is handled in interrupts, but the actual testing of the button states should belong to main code.

  4. advanced stuff - if you currently reading tutorials and teach your self - ignore this, but may be keep in mind for actual projects
    Another issue is the program design: your processor now cannot do anything else then toggling LEDs because his main program flow waits.
    Normally you would want to use a hardware timer for this kind of tasks. Either use it as a time base, that signals passed intervals to the main via a volatile flag variable. or directly use the PWM-Feature to directly interface the LED via one of the Output Compare Pins (OC[012][AB]).