AVR:volatile变量重置为零

时间:2015-07-11 08:00:22

标签: variables interrupt avr volatile avr-gcc

我有一个中断服务例程,其中包含变量count和变量state,当count达到某个值时会发生变化。

我希望我的代码要做的是在ISR的if语句中由state的值确定的特定时间段内更改并维护count

e.g。我希望变量state在10个计数中等于1; 我希望state在5个计数中等于0。 有点类似于改变PWM的占空比。

我遇到的问题是变量state在ISR结尾或if语句结束时重置为零,我不确定。

在搜索答案之后,我发现它可能与gcc编译器的优化有关,但除了声明我已经完成的volatile变量之外,我找不到解决这个问题的方法。 / p>

感谢任何帮助。

我的代码:

#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();
}    

2 个答案:

答案 0 :(得分:0)

首先,你的cli()对你的ISR没有任何影响。当一个中断发生时,I标志自动清除并在ISR结束时恢复 - 所以sei()也是不必要的。然而,当在一个ISR服务中间某处插入sei()以让其他ISR中断它时,有理性的情况。虽然建立如此复杂的ISR系统并非初学者水平。

第二:如果你设置一个条件结构,基本条件应该由双算子链接。评价(计数> 5)&amp; (状态&lt; 1)无法预测,正确写入(计数&gt; 5)&amp;&amp; (州&lt; 1)。显然对于&#39;或&#39; -ing ||使用。

答案 1 :(得分:0)

如果您正在模仿PWM,if语句的条件看起来很可疑。

为什么要测试端口B的引脚?只有在以正确频率按下引脚(按钮)时,才会输入if语句的正文。

您的意思是将引脚设置在端口B上吗?那你想要

    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;
    }