在Keil uVision中使用STM32F429发现板的IIR低通滤波器

时间:2015-05-14 13:04:18

标签: c arm signal-processing cortex-m lowpass-filter

我正在设计一个IIR二阶低通滤波器,采样频率= 100Hz,截止频率= 10 Hz。滤波器系数是在Matlab中使用fdatool的Chebyshev Type I。 但是代码不能过滤信号(即,对于所有频率,它给出的输出具有与输入信号相同的幅度)。对于10KHz及以上的输入信号,仅观察到幅度的轻微下降。我保证ADC和DAC工作正常,因为我测试了FFT滤波器。

以下是代码:

/* Include core modules */
#include "stm32f4xx.h"
#include "stdint.h"
#include "stdlib.h"
#include "arm_math.h"

#include "my_files.h"

#define URS 2
#define numStages 1
#define NUM_TAPS 5*numStages
#define samples 3

////////ADC FUNCTION//////////////////
void ADC_configure(void)
 {
     RCC->APB2ENR|=1Ul<<8;                         // ADC1 clock enabled
     ADC1->CR2|=0x00000001;                      // enable ADC
     ADC1->CR1|=0;                                   // single conversion ADC1 pin 0 has been selected
 }

int32_t readADC(void)
             {
                    ADC1->CR2|=(1UL<<30);
                    return(ADC1->DR);
             }

////////DAC FUNCTION/////////////////
int32_t dv1,dv2,ds;
//---function declaration--//
// initilising DAC---------//
void DAC_init(void)
{
  RCC->APB1ENR|=1UL<<29;
    DAC->CR|=((1UL<<16)|(1UL<<0));
  RCC->AHB1ENR|=0x00000001;                              // clock to gpio A
    GPIOA->MODER|=0x00000F03;                            // pt0,4,5 in Analog mode
}
// Sending to DAC...........//
void Send_DAC(int32_t data_in1, int32_t data_in2)
{   dv1=data_in1;
      dv2=data_in2<<16;
      ds=dv2+dv1;

      DAC->DHR12RD=ds;
}


/* IIR settings */
float32_t pState[2*numStages];
const float pCoeffs[NUM_TAPS] = {1,2,1,-1.1997,0.5157};//{b0,b1,b2,a1,a2}


/* Global variables */
float32_t Input[samples];                           /* Data to be read from ADC */
float32_t InputData[samples];                       /* Data to be processed */
float32_t Output[samples];                          /* Output filtered Data */

    arm_biquad_cascade_df2T_instance_f32 S;         /* ARM IIR module */
    uint16_t i;

void TIM3_Init (void) {

  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;             /* enable clock for TIM1    */

  TIM3->PSC   = 8600;                             /* set prescaler   = 10KHz  */
  TIM3->ARR   = 100;                              /* set auto-reload = 10ms */
  TIM3->RCR   =  0;                               /* set repetition counter   */
  TIM3->CR1 |= (1UL << URS);

  TIM3->DIER = TIM_DIER_UIE;                      /* Update Interrupt enable  */
  NVIC_EnableIRQ(TIM3_IRQn);                      /* TIM1   Interrupt enable  */
  NVIC_SetPriority (TIM3_IRQn, 0); 
  TIM3->CR1  |= TIM_CR1_CEN;                      /* timer enable             */
}

void TIM3_IRQHandler() {

        /*Shift Operation*/
        for(i=samples-1;i>0;i--){
            Input[i]= Input[i-1];
            InputData[i]= Input[i];
        }

        /* Input part from the ADC */
        Input[0] = (float32_t)readADC();
        InputData[0] = Input[0];

        //////////IIR//////////////////////
        /* Initialize the IIR module */
        arm_biquad_cascade_df2T_init_f32(&S, numStages, pCoeffs, pState);

        /* Process the data through the IIR module */
        arm_biquad_cascade_df2T_f32(&S, InputData, Output, samples);

        ////////DAC Output/////////////////
        Send_DAC(Input[0], Output[0]);
    }

/////////main function///////////////
int main(void) {
    /* Initialize system */
    SystemInit();
    DAC_init();
    ADC_configure();
    TIM3_Init();

    while (1) {     
    }
}

任何建议或解决方案都会有很大的帮助。

2 个答案:

答案 0 :(得分:1)

一些可能的问题:

  • 你启用了FPU吗?
  • 检查ADC(和DAC?)的对齐情况。
  • 确保中断处理程序运行时间不会太长(溢出)。

好的,你不要使用stdlib进行更多的初始化,顺便说一句。但你真的应该使用符号常量进行寄存器初始化!这不需要额外费用。

不直接相关,但会(!)给出错误的结果:如果我做对了,你会在readADC中触发每次转换。这会导致抖动(导致数字化信号产生噪声);通过定时器触发对话(触发系统实际上是什么)并使用ADC中断读取数据或使用DMA(STM DMA提供双缓冲模式,这是完美的) 。在这个简单的例子中,如果使用DMA,你甚至可以完全没有中断地相处并在主程序中进行计算。

对于DAC你也应该这样。

不知道为什么还要使用计时器; ADC可以自触发。这还不够吗?

答案 1 :(得分:0)

每次都不需要初始化IIR过滤器。在init代码中只执行一次。 Init过程清除pState中的先前值,但它们是IIR正确执行所必需的。这就是你的过滤器不起作用的原因。 FPU的存在只会影响计算速度。