C++ 在C中定义整数会解析为无符号字符,或者在进行数学运算时产生意外行为

C++ 在C中定义整数会解析为无符号字符,或者在进行数学运算时产生意外行为,c++,c,embedded,microcontroller,iar,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

我正在开发一个微控制器,我想对结果值实现一个简单的平均滤波器,以滤除噪声(或者说实话,不要让值在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
因此,缓冲区大小为8,其类型为
uint32\u 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  
这意味着DMA将ChA和ChB的结果始终放在固定的位置

现在要计算每个通道的平均值,我有以下函数:

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;
}
是什么导致了这种行为?如果“定义”在我的情况下不起作用,我还有什么其他选择


编译器是IAR Embedded Workbench。平台为STM32F103

为减少意外,请始终在宏定义周围加括号

#定义FP_过滤器_元素_计数(FP_模拟_缓冲_大小/FP_模拟_计数)


这可以防止出现奇怪的运算符优先级问题和其他意外的语法和逻辑错误。在这种情况下,当您想返回
sum/4
时,返回
sum/8/2
(即
sum/16
),括号将有所帮助,正如@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;

在C++中,所有这些都是编译时积分常量表达式,可以用作数组边界、case标签、模板参数等。但是不同于宏,它们尊重命名空间,类型安全,并且像真实值,而不是文本替换。< /P>似乎返回值是除以4的期望值。代替当前返回语句,尝试
uint32\u t average=sum/(uint32\u t)FP\u FILTER\u ELEMENT\u COUNT;收益率平均值average
的值。看起来你被一个额外的4:-)除掉了。很高兴Russ能够找到解决方案。仅仅计算平均值并不能阻止值“跳舞”,它们只会跳得不那么频繁/剧烈。您需要将平均计算与滞后相结合,这意味着您只允许值发生一定程度的变化。您应该将
adc\u vals
声明为volatile,以便编译器不会做出疯狂的决定-编译器可能无法判断DMA在任何给定时间点都会显示数据。理想情况下,将阵列的副本与DMA写入同步,这样在DMA写入时就不会读取。也许DMA中有一些标志可以检查,或者在读取时可以暂时禁用它?否则,大多数片上ADC都有一个选项,只要有时间,您就可以随时从ADC数据缓冲区读取最新的结果。在这种情况下,DMA是多余的。@saeid:这部传奇的另一章“为什么宏是邪恶的”。想一想,使用
静态常量32\u t FP\u FILTER\u ELEMENT\u COUNT=FP\u ANALOGS\u BUFFER\u SIZE/FP\u ANALOGS\u COUNT可以节省多少时间常量的另一个优点是,它们以一个标识符结束,因此您可以在调试器中查看它们的值,这总是很方便的。
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;