C 在ISR结束时使用reti()

C 在ISR结束时使用reti(),c,microcontroller,avr,atmelstudio,isr,C,Microcontroller,Avr,Atmelstudio,Isr,我有一个问题,这个代码不起作用。。 ISR正在工作。。我在其他代码中测试了它的闪烁 但要将x++放入ISR并在main()函数中读取x,它从不闪烁 我不熟悉asm,我认为这是编译器优化,所以我把变量放在volatile中,但它不起作用 #define F_CPU 16000000UL #include <avr/interrupt.h> #include <avr/io.h> #include <util/delay.h> volatile static

我有一个问题,这个代码不起作用。。 ISR正在工作。。我在其他代码中测试了它的闪烁

但要将x++放入ISR并在main()函数中读取x,它从不闪烁

我不熟悉asm,我认为这是编译器优化,所以我把变量放在volatile中,但它不起作用

#define F_CPU 16000000UL

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

volatile static uint8_t x = 1;

ISR( TIMER0_OVF_vect )
{
    x++;
    reti();
}

int main(void)
{

    /* Replace with your application code */
    DDRB = DDRB | 0B00100000 ; // pinMode(13,OUTPUT);
    TCCR0A = 0;
    TCCR0B = (1 << CS00 ) | (1 << CS02 ); //1024 prescaler
    TIMSK0 |= 1 << TOIE0 ;
    sei();

    while (1) 
    {

        if (x  >= 61) //never happens ? 
        {
            PORTB ^= 0B00100000;
            x=0;    
        }

    }
}
#定义F#U CPU 1600000UL
#包括
#包括
#包括
挥发性静态uint8_t x=1;
ISR(计时器0 OVF vect)
{
x++;
reti();
}
内部主(空)
{
/*替换为您的应用程序代码*/
DDRB=DDRB | 0B00100000;//pinMode(13,输出);
TCCR0A=0;

TCCR0B=(1对于普通ISR,编译器会生成一些“样板”代码,例如,包括保存和恢复CPU寄存器,并围绕您在ISR正文中编写的代码。当您声明ISR为“裸”时,不会发生这种情况

正如在您的代码中一样,ISR不是赤裸裸的,这个样板代码是存在的,但是您仍然使用
reti()
,这会立即离开ISR。因此,您的ISR将执行“序言”部分,而不会执行“尾声”部分,这可能会导致各种问题,例如混淆寄存器内容


顺便说一句,尾声样板中的最后一条指令无论如何都是
reti
。只有在编写裸ISR时才使用
reti()包括保存和恢复CPU寄存器的代码,以及围绕您自己在ISR正文中编写的代码。当您声明您的ISR为“裸体”时,不会发生这种情况

正如在您的代码中一样,ISR不是赤裸裸的,这个样板代码是存在的,但是您仍然使用
reti()
,这会立即离开ISR。因此,您的ISR将执行“序言”部分,而不会执行“尾声”部分,这可能会导致各种问题,例如混淆寄存器内容


顺便说一句,尾声样板中的最后一条指令无论如何都是
reti
。只有在编写裸ISR时才使用
reti()

您不应该在ISR中调用
reti()
,这只适用于“裸ISR”ISRs。这解决了问题,但我能知道原因吗?非标准关键字
ISR
用于在机器代码中生成此指令。您不应该在ISR中调用
reti()
,这仅用于“裸”指令ISRs。这解决了问题,但我能知道原因吗?非标准关键字
ISR
用于在机器代码中生成此指令。