在C中定义整数会解析为unsigned char,或者在数学运算时会产生意外行为

Sae*_*ani 3 c c++ embedded microcontroller iar

我正在研究一个微控制器,我想在结果值上实现一个简单的平均滤波器来滤除噪声(或者老实说,不要让值在LCD上跳舞!).

ADC结果通过DMA插入存储器.我(为了便于调试)一个大小为8的数组.为了让生活更轻松,我已经编写了一些定义,使我的代码可以用最少的工作量编辑:

#define FP_ID_POT_0             0  //identifier for POT_0
#define FP_ID_POT_1             1  //identifier for POT_1
#define FP_ANALOGS_BUFFER_SIZE  8 //buffer size for filtering ADC vals
#define FP_ANALOGS_COUNT        2  // we have now 2 analog axis
#define FP_FILTER_ELEMENT_COUNT  FP_ANALOGS_BUFFER_SIZE / FP_ANALOGS_COUNT
//means that the DMA buffer will have 4 results for each ADC
Run Code Online (Sandbox Code Playgroud)

因此,缓冲区的大小为8,其类型为uint32_t.我正在阅读2个ADC频道.在缓冲区中,我将为通道A提供 4个结果,为通道B提供 4个结果(以循环方式).这个数组的简单转储就像:

INDEX    0      1      2       3     4      5      6    7
CHNL     A      B      A       B     A      B      A    B
VALUE   4017    62    4032    67    4035    64    4029  63  
Run Code Online (Sandbox Code Playgroud)

这意味着DMA将ChAChB的结果始终放在固定的位置.

现在计算每个通道的平均值我有以下功能:

uint32_t filter_pots(uint8_t which) {

  uint32_t sum = 0;
  uint8_t i = which;

  for( ; i < FP_ANALOGS_BUFFER_SIZE; i += FP_ANALOGS_COUNT) {
    sum += adc_vals[i];
  }

  return sum / (uint32_t)FP_FILTER_ELEMENT_COUNT;
}
Run Code Online (Sandbox Code Playgroud)

如果我想使用该函数,chA我将0作为参数传递给函数.如果我想要chB通过1......如果碰巧chC我会通过2等等.这样我就可以启动for循环来指向我需要的元素.

问题是,在我想要返回结果的最后一步,我没有得到正确的值.1007当用于chA16用于chB时,该函数返回.我很确定sum计算好了(我可以在调试器中看到它).我相信,问题在于除以使用#define定义的值.即使把它uint32_t扔到也无济于事.将sum被计算好了,但我不能看到什么类型或值FP_FILTER_ELEMENT_COUNT已经被编译器分配.Mybe是uint32划分uint32的溢出问题?

#define FP_FILTER_ELEMENT_COUNT  FP_ANALOGS_BUFFER_SIZE / FP_ANALOGS_COUNT
//means FP_FILTER_ELEMENT_COUNT  will be 8 / 2 which results in 4
Run Code Online (Sandbox Code Playgroud)

是什么导致了这种行为,如果#define无法在我的情况下起作用,我还有其他选择吗?

编译器是IAR Embedded Workbench.平台是STM32F103

Rus*_*ltz 9

对于较少的意外,总是在您的宏定义周围加上括号

#define FP_FILTER_ELEMENT_COUNT (FP_ANALOGS_BUFFER_SIZE / FP_ANALOGS_COUNT)

这可以防止奇怪的运算符优先级问题和其他意外的语法和逻辑错误的出现.在这种情况下,当您想要返回时,您将返回sum/8/2(即sum/16)sum/4.


Ben*_*igt 5

正如@Russ所说,括号将有所帮助,但更好的解决方案是使用常量:

static const int FP_ID_POT_0 = 0;  //identifier for POT_0
static const int FP_ID_POT_1 = 1;  //identifier for POT_1
static const int FP_ANALOGS_BUFFER_SIZE = 8; //buffer size for filtering ADC vals
static const int FP_ANALOGS_COUNT = 2;  // we have now 2 analog axis
static const int FP_FILTER_ELEMENT_COUNT = FP_ANALOGS_BUFFER_SIZE / FP_ANALOGS_COUNT;
Run Code Online (Sandbox Code Playgroud)

在C++中,所有这些都是编译时整数常量表达式,可以用作数组边界,大小写标签,模板参数等.但与宏不同,它们尊重名称空间,类型安全,并且像真实值一样,而不是文字替换.