【发布时间】:2023-05-24 21:53:01
【问题描述】:
这是我的头文件(Header.h)
#include <stdio.h>
#include <string.h>
void Process(void);
和“Header.C”
#include <stdio.h>
#include <string.h>
#include "Header.h"
struct St{
unsigned long int volatile Var1;
unsigned long int volatile Var2;
unsigned char volatile Flag;
};
extern struct ST Variable;
void Process(void){
Variable.Var1=Variable.Var2;
}
和主文件:
#include <stdio.h>
#include <string.h>
#include "Header.h"
struct St{
unsigned long int volatile Var1;
unsigned long int volatile Var2;
unsigned char volatile Flag;
};
struct ST Variable;
//Interrupt each 10us
void TIM_IRQHandler(){
//Do something
if(something==True)
{
Variable.Flag=1;
Variable.Var2=AVariable; //AVariable is between 30-40
}
}
int main(){
while(1)
{
//wait 10ms
if(Variable.Flag==1)
{
Process();
Variable.Flag=0;
}
}
}
正如您所见,每 10us 发生一次中断,如果它正确执行某些代码,它会将 Var2 更改为 30-40 之间的值并设置一个标志变量。在主代码中,如果已设置标志,则应调用处理函数并将 Var1 更改为 Var2 值。 但是有时我会收到带有其他不正确值的奇怪值的 var1。我测试了我的中断,发现我从来没有用奇怪的值填充我的 Var2。
void TIM_IRQHandler(){
//Do something
if(something==True)
{
Variable.Flag=1;
Variable.Var2= < 30-40>;
}
if(Variable.Var2>40 || Variable.Var2<30){
printf("ERROR");
}
}
所有中断功能都可以正常工作,但在处理功能中它让我很生气。
我会感谢我没有注意的任何技巧。
【问题讨论】:
-
这是什么意思?
Variable.Var2= < 30-40>;它应该如何编译? -
这不是我的确切代码,但这意味着它的值可以在 30 到 40 之间
-
@Ehsan Zakeri:你有一个潜在的竞争,第二个中断触发和
Var2,而之前的结果仍在处理中。如果读取不是原子的,例如在典型的 8 位 MCU 上,那么您最终可能会得到一些来自先前值的字节和一些来自新值的字节。最简单的解决方法是在Process之前重置Variable.Flag并测试以查看它是否在之后再次升起,在这种情况下您旋转并重试。相反,标志应该是sig_atomic_t类型,这在实践中不太可能成为问题。还有其他需要注意的问题。 -
@doynax 感谢您的解释和贡献,我有同样的想法,它想要处理变量,但在其他过程中它想要填充它。我正在使用 Stm32f MCU(32 位)不幸的是,这个技巧不起作用。它快把我逼疯了。
-
@Ehsan Zakeri:很公平,极短的中断间隔往往会打击任何可能潜伏的微妙比赛。不幸的是,说明性代码中有太多空白,无法有效地分析它。我建议您尝试缩小一个最小但完整的可重现示例。