繁体   English   中英

ATmega2560使用UART中断来控制全局标志

[英]ATmega2560 using UART interrupt to control global flag

我最近在玩ATmega2560的时候遇到了一个问题,我真的不明白它有什么问题。

这是我的代码。

主要的:

#include "Definitions.h"

int main(void) {
    Initialization();
    while (1) {
        //_delay_ms(1); // or printf...
        //wait for RXC flag
        if (RxFlag) {
            //wait for new byte in
            //PORTB &= ~(1 << PB7);
            PORTB |= (1 << PB7);
            rxcount = 0;
            UDR0 = 'R';
            RxFlag = false;
            TxFlag = false;
        }
    }
}

中断请求:

#include "Definitions.h"

ISR(USART0_RX_vect) {
    while(!(UCSR0A & (1 << RXC0)))
    //wait for RXC flag
        ;
    /* Loop-back test */
    //PORTB |= (1 << PB7);
    //test_data = UDR0;
    TxFlag = true;
    //enableUDRI0();
    //PORTB &= ~(1 << PB7);
    //PORTB |= (1 << PB7);
    RxBuffer[rxcount++] = UDR0;
    if(!(rxcount < RX_BUF_SZ)) {
        //rxcount = 0;
        PORTB |= (1 << PB7);
        RxFlag = true;
    }
}

ISR(USART0_UDRE_vect) {
    while(!(UCSR0A & (1 << UDRE0)))
    //wait for udr to be empty
        ;
    /* Loop-back test */
    UDR0 = 0x30 + rxcount;
    disableUDRI0();
}

问题是,当我从 USART 收到一些数据时,我试图设置一个 RxFlag 可以激活主循环中的 if 语句。 但是直到我在 if 语句(可能是 _delay_ms() 或 printf() 之前取消对该函数的注释)它才起作用。

这没有道理。 我记得我不需要这些函数,它仍然可以设置全局变量来影响主循环。 还是我遗漏了什么细节? 请给我一些线索来弄清楚,我很困惑。

不可能确定,但​​是我认为这可以解释您的问题,因此很可能是错误。

您不包括RXFlag的声明,但我推测您没有将其声明为volatile 除非您这样做,否则允许编译器假定它知道该变量将发生什么的一切。 特别是它知道,除非main()调用任何其他函数,否则 RxFlag 的值永远不会改变。 因此它可以通过将if表达式移到循环之外来优化它。 实际上,它正在像这样更改您的代码:

#include "Definitions.h"

int main(void)
{
    register bool x;

    Initialization();

    x = RxFlag;

    while (1) 
    {
        //wait for RXC flag
        if (x) //wait for new byte in
        {
            //PORTB &= ~(1 << PB7);
            PORTB |= (1 << PB7);
            rxcount = 0;
            UDR0 = 'R';
            RxFlag = false;
            TxFlag = false;

        }
    }
}

但是,如果main()调用另一个函数,则编译器放弃尝试通过该调用将 RxFlag 保留在寄存器中。 另一个函数可能会改变保存 RxFlag 的寄存器。它必须将它压入堆栈或其他东西。 再次读取它在代码和时间上更便宜,因此每次循环时它都会读取它。

此错误的正确修复方法是将主线程和 ISR 之间共享的任何变量声明为volatile

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM