1

环境:STM32H7 和 GCC
处理数据流:每 250 我们从 SPI 接收 1 个样本
我用 256 个样本做一个“三角形”加权移动平均,就像这样,但中间样本的权重为 1,它在它周围形成一个三角形
我的样本存储在uint32_t val[256]循环缓冲区中,它适用于 auint8_t write_index
样本为 24 位,样本的最大值为0x00FFFFFF

uint8_t write_idx =0;
uint32_t val[256];
float coef[256];

void init(void)
{
  uint8_t counter=0;
  // I calculate my triangle coefs
  for(uint16_t c=0;c<256;c++) 
  {
    coef[c]=(c>127)?--counter:++counter;
    coef[c]/=128;
  }
}

void ACQ_Complete(void)
{
  uint32_t moy=0;
  // write_idx is meant to wrap
  val[write_idx++]= new_sample;
  // calc moving average (uint8_t)(c-write_idx) is meant to wrap
  for(uint16_t c=0;c<256;c++)
    moy += (uint32_t)(val[c]*coef[(uint8_t)(c-write_idx)]);
  moy/=128;
}

我必须在250 us 的时间跨度内进行计算,但我用调试 GPIO 引脚测量“moy”部分需要252 us
代码在这里
模拟有趣的事实:如果我在接近尾声时移除(uint32_t)演员表,则需要 274 us 252 我们

我怎样才能更快地完成它?

我正在考虑使用uint32而不是floatfor coef(例如乘以 1000),但我uint32会溢出

4

1 回答 1

2

毫无疑问,这应该以整数形式完成。它将更快,更准确。

该处理器可以在一个周期内进行 32x32+64=64 乘法累加!

将所有系数乘以 2 的幂(不是评论中提到的 1000),然后在最后向下移动而不是除以。

uint32_t coef[256];

uint64_t moy = 0;

for(unsigned int c = 0; c < 256; c++)
{
   moy += (val[c] * (uint64_t)coef[(c - write_idx) & 0xFFu]);
}

moy >>= N;
于 2021-03-18T14:32:19.863 回答