嵌入式C:AVR; 标头中的变量无法在main中进行评估

Nic*_*ams 0 c microcontroller assembly avr

感谢您抽出宝贵时间阅读.

我遇到的问题

我有:

main.h 
Run Code Online (Sandbox Code Playgroud)

声明:

uint8_t u_newVar
Run Code Online (Sandbox Code Playgroud)

我也有

foo.h 
Run Code Online (Sandbox Code Playgroud)

写道:

extern uint8_t u_newVar
Run Code Online (Sandbox Code Playgroud)

应用程序位于main.c中的无限while循环中,直到出现ISR.

在foo.c中,所述ISR在foo.c中调用一个函数.

在该函数中(如果你愿意,则为foo_function()):0x01被写入u_newVar.

最后,从中断返回到无限时,有一个"if"语句:

while(1){
  if(u_newVar == 0x01){
    uartTX_sendArray(st_uartRX_MessageContents->u_command, (sizeof st_uartRX_MessageContents->u_command));
    uartTX_sendButtonPressData(st_uartRX_MessageContents->u32_value);    
    u_newVar = 0x00;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,应用程序永远不会进入if.如果它位于foo.c之后,这个"if"块将起作用

u_newVar = 0x01;
Run Code Online (Sandbox Code Playgroud)

线.

我试过的东西

我看着编译过的集合,我发现了什么样的东西让我感到难过.

如果我看一下main中的"if",这就是我所看到的:

在此输入图像描述

因此它从SRAM中加载地址:0x011D的值,我可以确认它是0x01.

然后"CPI"将R24直接与0x01进行比较,这显然应该可行.

然后是"BREQ",如果相等则分支,并将程序计数器增加两次到下面的uart函数.也有道理.

然而这部分很奇怪.否则,使用"RJMP"跳转到当前所在的指令.除非我弄错了,否则这将永远锁定在这里?

那么,还记得当我提到在写入u_newVar之后将if块放入foo.c时吗?是的,这不是太有趣:

在此输入图像描述

"if"应该在"u_newVar = 0x01"之后,但编译器太聪明并且如何优化它.这就是它始终在那里工作的原因.

Ign*_*ams 8

您忘了告诉编译器可能异步修改变量.例如在ISR中.

volatile uint8_t u_newVar;
Run Code Online (Sandbox Code Playgroud)