0

I have an interrupt service routine that contains the variable count and a variable state that changes when count reaches a certain value.

What I want my code to do is change and maintain state for a certain period of time determined by the value of count in the if statements in the ISR.

e.g. I want the variable state to equal 1 for 10 counts; I want state to equal 0 for 5 counts. Somewhat similar to changing the duty cycle of a PWM.

The problem I am having is that the variable state resets to zero around the end of the ISR or the end of the if statement, I'm not sure.

After searching for answers, I have found that it might be related to the gcc compiler's optimisation but I cannot find a fix for this problem besides declaring volatile variables, which I have already done.

Any help is appreciated thanks.

My code:

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

volatile int count = 0;
volatile int state = 0;

int main(void)
{
    cli();

    DDRB |= (1 << PB2);

    TCCR0B |= (1 << CS02)|(0 << CS01)|(1 << CS00);

    TIMSK |= (1 << TOIE0);

    sei();

    while(1) {
    ...
    }
}

ISR(TIM0_OVF_vect)
{
    cli();
    // user code here
    count = count + 1;

    if ((count > 5) && (state < 1) && !(PORTB & (1 << PB2))) {
        state = 1;
        count = 0;
    }
    else if ((count > 10) && (state > 0) && (PORTB & (1 << PB2))) {
        state = 0;
        count = 0;
    }

    sei();
}    
Satchan
  • 1
  • 3

2 Answers2

0

First of all your cli() has no effect in your ISR. When an interrupt happens the I flag automatically cleared and restored at the end of ISR - so sei() is needless as well. However there is rational case when sei() inserted somewhere in the middle of an ISR service to let other ISR's to interrupt it. Though it is not beginner level to build such sophisticated ISR system.

Second: if you set up a conditional structure the elementary conditions should be chained by double operators. The evaluation of (count > 5) & (state < 1) cannot be predicted, correctly written it is (count > 5) && (state < 1). Obviously for 'or'-ing || is used.

uhum2004
  • 11
  • 3
  • Ah yes, that `&` was a typo. I have added another. But my main problem is that the variable `state` keeps resetting to zero. if ((count > 5) && (state < 1) && !(PORTB & (1 << PB2))) { state = 1; count = 0; } After this block, the variable `state` returns to zero again and I don't understand why. – Satchan Jul 12 '15 at 03:21
0

The conditions of the if statements look suspicious if you are mimicking a PWM.

Why is the pin of port B being tested? The bodies of the if statements will only be entered if the pin (button) is pressed with the correct frequency.

Do you mean to set the pin on port B instead? Then you would want

    count = count + 1;

    if ((count > 5) && (state < 1)) {
        PORTB &= ~(1 << PB2); // clears PB2
        state = 1;
        count = 0;
    }
    else if ((count > 10) && (state > 0)) {
        PORTB |= 1 << PB2; // sets PB2
        state = 0;
        count = 0;
    }
UncleO
  • 8,299
  • 21
  • 29
  • The pin of PortB is meant to be an indicator like an LED. The underlying problem is that the variable `state` is not maintaining its value. Say that the `count` equals 6 and `state` equals zero. The first case of the if statement is true and should change `state` to equal one. But at the end of the if statement, it returns back to zero. The else statement is not executed hence I am confused as to why this would happen. – Satchan Jul 12 '15 at 03:30
  • Then my answer seems to be the one you need. You want to set the pin as an indicator. Instead, you are checking what the value of the pin is. It looks like neither if condition evaluates to "true", because the state of the pin is not what you are expecting. – UncleO Jul 12 '15 at 07:23
  • I probably could have worded my problem better. Let us remove completely PORTB. The if statement is working completely fine but the issue I have is that variable `state` is not maintaining its value. `state` changes to 1 but changes immediately back to zero at the end of the if statement. I hope that is clearer. – Satchan Jul 13 '15 at 07:04
  • What evidence do you have that the variable is changing? and how can you know with such precision exactly when the variable is changing? So much is missing from the given code example that the problem is not reproducible. (Also, the PORTB stuff is still in your question. You must have made a mistake while trying to remove it to make the question clearer.) – UncleO Jul 13 '15 at 19:16