БИХ-фильтр нижних частот с использованием платы STM32F429 Discovery в Keil uVision

Я разрабатываю БИХ-фильтр нижних частот 2-го порядка с частотой дискретизации = 100 Гц и частотой среза = 10 Гц. Коэффициенты фильтра относятся к типу Чебышева I с использованием fdatool в Matlab. Но код не может фильтровать сигнал (т.е. для всех частот он дает на выходе те же амплитуды, что и входной сигнал). Для входного сигнала 10 кГц и выше наблюдается лишь незначительное уменьшение амплитуды. Уверяю вас, что АЦП и ЦАП работают нормально, так как я тестировал фильтр БПФ.

Вот код:

/* 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) {     
    }
}

Любое предложение или решение будет большим подспорьем.


person user11622    schedule 14.05.2015    source источник
comment
Используется много коротких форм. И вопрос непонятный!   -  person Anand Gupta    schedule 14.05.2015
comment
Вы включали FPU? Хорошо, что вы не используете stdlib для чего-то большего, чем init, кстати. Но вам действительно стоит использовать символические константы для инициализации регистра! Это не требует дополнительных затрат. Также проверьте юстировку АЦП (и ЦАП?). Если я правильно понял, вы запускаете каждое преобразование в readADC. Это приводит к дрожанию (что приводит к шуму в оцифрованном сигнале); запускать разговоры по таймеру и использовать прерывание АЦП для чтения данных, для этого у STM есть свои варианты запуска переменных. Также: вы проверяли время на переполнение прерывания?   -  person too honest for this site    schedule 14.05.2015
comment
Вы можете легко выполнить профилирование с помощью модуля DWT (требуется справочное руководство по архитектуре ARM - бесплатно, но с регистрацией).   -  person too honest for this site    schedule 14.05.2015
comment
Спасибо @Olaf, проблема была только в выравнивании. Все было правильно. Просто я взял результат не с той стороны выходного массива. Как только я взял его с другого конца, проблема была решена. Большое спасибо. Также я представил разговоры по таймеру. Это была большая помощь с вашей стороны. Еще раз большое спасибо.   -  person user11622    schedule 14.05.2015
comment
Я ответил на этот вопрос и надеюсь, что вы его уважаете. О, и я добавил еще несколько подсказок.   -  person too honest for this site    schedule 14.05.2015


Ответы (2)


Некоторые возможные проблемы:

  • Вы включали FPU?
  • Проверить юстировку АЦП (и ЦАП?).
  • Убедитесь, что обработчик прерывания не работает слишком долго (переполнение).

Хорошо, что вы не используете stdlib для чего-то большего, чем init, кстати. Но вам действительно стоит использовать символические константы для инициализации регистра! Это не требует дополнительных затрат.

Не имеет прямого отношения, но будет (!) Давать неправильные результаты: если я все сделаю правильно, вы запускаете каждое преобразование в readADC. Это приводит к дрожанию (что приводит к шуму в оцифрованном сигнале); запускать разговоры по таймеру (это то, для чего на самом деле предназначена система триггеров) и использовать прерывание АЦП для чтения данных или использовать DMA (STM DMA обеспечивает режим двойного буфера, который идеально подходит для этого). В этом простом примере, используя DMA, вы даже можете полностью обойтись без прерывания и выполнять вычисления в основной программе.

Для ЦАПа у вас должно быть то же самое.

В любом случае не уверен, зачем использовать таймер; АЦП может запускаться автоматически. Этого недостаточно?

person too honest for this site    schedule 14.05.2015
comment
Я только новичок, постепенно учусь. Теперь моя следующая задача - использовать DMA. :) - person user11622; 15.05.2015
comment
Если я могу порекомендовать, сначала вы должны правильно настроить сигнальную цепочку. Это означает, например, устранение джиттера (насколько это возможно). Это может быть выполнено с помощью системы триггеров STM, которая довольно сложна (как и для большинства современных микроконтроллеров) и требуется для чтения справочника для всех (возможно) периферийных модулей. Только после этого следует оптимизировать обработку и передачу данных. Обычно, кстати. можно было бы выполнять обработку в потоке / основной программе, чтобы не мешать другим прерываниям. Альтернативой может быть использование приоритетов прерывания (это работает для моего текущего профессионального проекта STM32, кстати). - person too honest for this site; 15.05.2015
comment
Как я читал, у вас проблемы с шумом на ЦАПе. Это может быть из-за дрожания, но вы также можете ознакомиться с примечаниями по применению. Есть один о проблемах с АЦП / ЦАП и шумом. Кроме того, вы можете обнаружить, что плата Discovery не полностью соответствует практике аналогового проектирования (это скорее дешевый демонстратор возможностей LCD / SDRAM модели 429, которые являются новыми для семейства F4. - person too honest for this site; 15.05.2015
comment
Опять же: если приведенный выше ответ помог с проблемой, проголосуйте за и / или примите. - person too honest for this site; 15.05.2015

Вам не нужно каждый раз запускать БИХ-фильтр. Сделайте это только один раз в коде инициализации. Процедура инициализации очищает предыдущие значения в pState, но они необходимы для правильной работы IIR. Вот почему ваш фильтр не работает. Наличие FPU влияет только на скорость вычислений.

person romanetz    schedule 02.10.2015