C中FIR滤波器的循环缓冲器实现

时间:2014-03-30 19:59:14

标签: c circular-buffer digital-filter

我正在使用32位浮点MCU的嵌入式微控制器(TMS320F28069)进行编程。我正在讨论一些示例项目,其中一个实现了对ADC采样数据的简单FIR滤波器。

Block diagram here

假设ADC缓冲区有10个元素。让我们说过滤器的长度为3(FILTER_LEN=3)。过滤器实现非常简单,它从延迟链的末尾开始,然后移动到开头。

float32 ssfir(float32 *x, float32 *a, Uint16 n)
{

Uint16 i;                                   // general purpose
float32 y;                                  // result
float32 *xold;                              // delay line pointer

/*** Setup the pointers ***/
    a = a + (n-1);                      // a points to last coefficient
    x = x + (n-1);                      // x points to last buffer element
    xold = x;                           // xold points to last buffer element

/*** Last tap has no delay line update ***/
    y = (*a--)*(*x--);

/*** Do the other taps from end to beginning ***/
    for(i=0; i<n-1; i++)
    {
        y = y + (*a--)*(*x);            // filter tap
        *xold-- = *x--;                 // delay line update
    }

/*** Finish up ***/
    return(y);

}

现在,这是ADC循环缓冲区的实现方式。

//---------------------------------------------------------------------
interrupt void ADCINT1_ISR(void)                // PIE1.1 @ 0x000D40  ADCINT1
{
static float32 *AdcBufPtr = AdcBuf;                 // Pointer to ADC data buffer
static float32 *AdcBufFilteredPtr = AdcBufFiltered; // Pointer to ADC filtered data buffer

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;     // Must acknowledge the PIE group

//--- Manage the ADC registers     
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;       // Clear ADCINT1 flag

//--- Read the ADC result:
    *AdcBufPtr = ADC_FS_VOLTAGE*(float32)AdcResult.ADCRESULT0;

//--- Call the filter function
    xDelay[0] = *AdcBufPtr++;                   // Add the new entry to the delay chain
    *AdcBufFilteredPtr++ = ssfir(xDelay, coeffs, FILTER_LEN);

//--- Brute-force the circular buffer
    if( AdcBufPtr == (AdcBuf + ADC_BUF_LEN) )
    {
        AdcBufPtr = AdcBuf;                     // Rewind the pointer to the beginning
        AdcBufFilteredPtr = AdcBufFiltered;     // Rewind the pointer to the beginning
    }

}

xDelay是一个长度为FILTER_LEN的float32数组,用0s初始化,coeffs是一个用过滤系数初始化的长度为FILTER_LEN的float32数组。

我的问题是,这里发生了什么:

//--- Call the filter function
    xDelay[0] = *AdcBufPtr++;                   // Add the new entry to the delay chain
    *AdcBufFilteredPtr++ = ssfir(xDelay, coeffs, FILTER_LEN);

如何将值存储在xDelay[1]xDelay[2]中? 他们的实现似乎工作正常,但我没有关注多少旧数据在xDelay数组中被推回。

1 个答案:

答案 0 :(得分:1)

在ssfir()函数中,以下行将洗牌xDelay数组中的元素

    *xold-- = *x--;                 // delay line update

该行在for循环中,因此[1]元素被复制到[2],然后[0]元素被复制到[1],因为x和xold指针递减,尽管for循环计数达