【发布时间】:2015-07-28 03:05:07
【问题描述】:
问题
在我的个人项目中,我在 UART 抽象库中定义了一个结构(我们称之为 UART.c 和 UART.h),我为 AVR 制作。
在 UART.h 中:
typedef struct ST_UARTRX_MESSAGECONTENTS{
uint8_t u_command[3]; //Command
uint32_t u32_value; //Parameter for Command
boolean b_newValue; //Is there new value written here
boolean b_Error; //Is there an error with this message
} ST_UARTRX_MESSAGECONTENTS;
volatile ST_UARTRX_MESSAGECONTENTS st_uartRX_MessageContents;
所以基本上它是一个保存 UART 消息的结构,它有一个“b_newValue”,它是接收新消息时的标志。当 AVR 接收到一个新行“\n”时,一条消息被“接收”。
在另一个文件的头文件中(我们称之为“foo.h”):我包含我的“UART抽象库”并将其放在头文件中:
extern volatile ST_UARTRX_MESSAGECONTENTS st_uartRX_MessageContents;
然后在 foo.c 中,我尝试访问“b_newValue”:
if(st_uartRX_MessageContents.b_newValue){
st_uartRX_MessageContents.b_newValue = TRUE;
fsm_state = ST_STOREMACRO;
}
但是即使我的调试器说结构值确实是真的,也永远不会输入“if”:
你可以看到我已经打破了 if 语句。如果我点击“Step”,它只是跳过它并且不进入!
Boolean typedef 供参考:
typedef enum{FALSE, TRUE} boolean;
我尝试过的一些事情
当我查看已编译的 ASM 代码时,我看到通用寄存器 R24 用于加载 b_newValue,但它加载的是 0x00,而不是我期望的 0x01。
uartTX_sendArray(st_uartRX_MessageContents.u_command, sizeof st_uartRX_MessageContents.u_command);
delay_ms(2000);
if(st_uartRX_MessageContents.b_newValue){
st_uartRX_MessageContents.b_newValue = TRUE;
fsm_state = ST_STOREMACRO;
}
我使用我的“UART:发送此数组”函数从相同的结构发送 ascii“命令”,它可以工作!我不知道为什么我的 foo.c 可以看到“命令”而不是“b_newValue”。
我已经把头发扯了好几个小时了。感谢观看。
【问题讨论】:
-
从您发布的代码的布局来看,
typedef struct ST_UARTRX_MESSAGECONTENTS{...位于定义volatile ST_UARTRX_MESSAGECONTENTS st_uartRX_MessageContents;的同一文件中,该文件应该是.c文件。但是您是如何设法在.h文件中声明extern volatile ST_UARTRX_MESSAGECONTENTS st_uartRX_MessageContents;的呢?在这种情况下,名称ST_UARTRX_MESSAGECONTENTS不应该在.h文件中知道。那么它是如何工作的呢?您能否提供有关声明和定义如何分布在不同源文件中的更准确信息? -
fsm_state的值是多少?如果它始终是ST_STOREMACRO,并且由于您将TRUE存储到b_newValue中,而它已经是TRUE,那么编译器是否有可能优化了整个块,因为它在逻辑上是一个 noop? -
我要问的原因是,如果这样的声明布局编译,那么你可能在其他地方有另一个独立声明
ST_UARTRX_MESSAGECONTENTS不同的成员序列。这样的事情很容易混淆调试器并导致您观察到的效果。 -
当
b_newValue被加载到 ASM 中的寄存器而不是总是从主内存中读取时,这里肯定发生了一些奇怪的事情,这表明对结构成员的访问不是实际上易变。如果所有其他方法都失败了,您可能可以通过执行以下操作来强制读取:*(volatile boolean *) &st_uartRX_MessageContents.b_newValue这显然很可怕,但只能作为最后的手段使用。 -
@AnT 感谢您的意见。 typedef 在 UART 抽象的头文件中。 extern 结构位于 foo.h 中,其中包含 UART 抽象库的标头。我将尝试在上面澄清这一点。