Исходные тексты модулей проекта DspLab_fir_iir



Модуль main.c

 

/******************************************************************************

 *

 * УЧЕБНЫЙ ПРОЕКТ

 *

 * Фильтр с конечной импульсной характеристикой (FIR)

 * Фильтр с бесконечной импульсной характеристикой (IIR)

 *

 * Блочная обработка с использованием функций библиотеки CMSIS DSP Library

 *

 * Copyright (C) 2015 МИРЭА

 * Версия: 1.3

 *

 ******************************************************************************/

/*

ОРГАНЫ УПРАВЛЕНИЯ

Джойстик "вверх/вниз" - увеличение/уменьшение частоты генератора синусоидального сигнала

Джойстик "влево" - переключение между типами входного сигнала: синусоидальный / шум / нет сигнала

Джойстик "вправо" - переключение форматов входного сигнала: аналоговый (через АЦП) / цифровой код

Джойстик "выбор" - переключение типов фильтров: КИХ / БИХ.

Кнопка TAMPER    - вывод меток времени обработки

*/

 

/******************************************************************************

ФОРМАТ ЗАПИСИ КОЭФФИЦИЕНТОВ

Для КИХ-фильтра:

{ b0, b1, b2, ..., bN } , где N - порядок фильтра; numTaps = N+1 - число коэффициентов

 При использовании 16-разрядного формата с фиксированной точкой число коэффициентов должно быть четное

 

Для БИХ-фильтра:

{ b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...} ,

первый индекс - номер звена (каскада) 2-го порядка,

второй индекс - номер коэффициента (5 коэффициентов для одного звена),

по умолчанию коэффициенты a10, a20, ... всегда равны 1 и в массив не включаются

*/

 

#include "stm32_p407.h"            //Файл конфигурации отладочной платы STM32-P407

#include "adcdac.h"                    //Объявления функций для работы с периферийными устройствами

#include "gauge.h"                 //Процедуры управления и измерения

#include "arm_math.h"              //Определения и функции библиотеки CMSIS DSP Library

#include "mathfunc.h"              //Прототипы вспомогательных математических функций

#include "values.h"                //Числовые значения исходных операндов

#include "fir_coef.h"              //Значения коэффициентов FIR-фильтра

#include "iir_coef.h"              //Значения коэффициентов и усилений IIR-фильтра

 

//---------------------------------------------------------------------------

// ОБЪЯВЛЕНИЯ ДАННЫХ

 

// Следующие параметры объявлены в подключаемых файлах коэффициентов:

// numTaps    - Число отсчетов/коэффициентов FIR-фильтра (константа)

// FIR_coef[] - Массив коэффициентов FIR-фильтра в формате float

// numStages - Число звеньев IIR-фильтра (константа)

// IIR_coef[] - Массив коэффициентов IIR-фильтра в формате float

// IIR_gain[] - Массив коэффициентов усилений для звеньев IIR-фильтра в формате float

 

#define FLOAT_PROC                 //Определение для использования при обработке сигнала

                                   // данных с плавающей точкой

#define BlockSize 1024            //Размер блока обрабатываемых отсчетов

 

#ifndef FLOAT_PROC                 //В а р и а н т обработки с фиксированной точкой

 

q15_t Coeffs[numTaps];             //Буфер 16-разрядных коэффициентов в дробном формате 1.15

int16_t DataIn0[BlockSize];        //Буферы для входных отсчетов

int16_t DataIn1[BlockSize];

int16_t DataOut0[BlockSize];       //Буферы для выходных отсчетов

int16_t DataOut1[BlockSize];

int16_t *DataIn, *DataOut;         //Текущие указатели на буферы

arm_fir_instance_q15 SF;           //Структура для обработки данных FIR-фильтра

q15_t StateF[numTaps+BlockSize]; //Рабочий массив для обработки данных FIR-фильтра

 

#else                              //В а р и а н т обработки с плавающей точкой

 

float32_t DataIn0[BlockSize];      //Буферы для входных отсчетов

float32_t DataIn1[BlockSize];

float32_t DataOut0[BlockSize];     //Буферы для выходных отсчетов

float32_t DataOut1[BlockSize];

float32_t *DataIn, *DataOut;        //Текущие указатели на буферы

arm_fir_instance_f32 SF;           //Структура для обработки данных FIR-фильтра

float32_t StateF[numTaps+BlockSize-1]; //Рабочий массив для обработки данных FIR-фильтра

float32_t StateI[4*numTaps];       //Рабочий массив для обработки данных IIR-фильтра

arm_biquad_casd_df1_inst_f32 SI;   //Структура для обработки данных IIR-фильтра

float32_t GainScale;               //Коэффициент масштабирования отсчетов для IIR-фильтра

 

#endif

 

int32_t DataIndex;                      //Индекс текущего входного/выходного отсчета

int32_t TransferBuf;               //Номер (0 или 1) буфера для текущего ввода-вывода

int32_t ProcBuf;                   //Номер (0 или 1) обрабатываемого (обработанного) буфера

int16_t DataChannel1, DataChannel2; //Входные и выходные отсчеты в формате 1.15 с фиксированной точкой

int16_t DataADC;                   //Прямой отсчет с АЦП для системы калибровки

int32_t AmplOffset = 0;            //Смещение нулевого уровня сигнала с АЦП

int32_t ProcessMode = 0;           //Режим обработки: 0 - FIR-фильтр, 1 - IIR-фильтр

int32_t HardwareMode = 0;          //Конфигурация системы:

                                   // 0: цифровой генератор -> ЦАП--(анал. сигнал)--> АЦП -> обработка

                                   // 1: цифровой генератор -> обработка

 

//---------------------------------------------------------------------------

// ГЛАВНАЯ ФУНКЦИЯ

int main()

{

//Счетчик для реализации периода изменения тестовой индикации

volatile uint32_t i = 0; 

 

//Инициализация цифровой обработки сигнала

#ifndef FLOAT_PROC                 //В а р и а н т обработки с фиксированной точкой (только FIR)

for (i = 0; i < numTaps; i++)    // Преобразование формата коэффициентов из float в дробный 1.15

Coeffs[i] = float_to_q15(FIR_coef[i]);

arm_fir_init_q15(&SF, numTaps, Coeffs, StateF, BlockSize);

#else                              //В а р и а н т обработки с плавающей точкой (FIR и IIR)

arm_fir_init_f32(&SF, numTaps, FIR_coef, StateF, BlockSize);

arm_biquad_cascade_df1_init_f32(&SI, numStages, IIR_coef, StateI);

for (i = 0, GainScale = 1.f; i < numStages; i++) GainScale *= IIR_gain[i];

#endif

 

//Задание 4-х уровней групповых приоритетов и 4-х уровней приоритетов в каждой группе

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 

//Инициализация тестового индикатора

STM_LEDInit(LED1);

STM_LEDInit(LED2);

 

//Инициализация кнопок

STM_PBInit(BUTTON_TAMPER, BUTTON_MODE_GPIO);

STM_PBInit(BUTTON_WAKEUP, BUTTON_MODE_GPIO);

 

//Инициализация кодека (ЦАП выходных отсчетов сигнала)

SoundCodecConfig(FS_FIR_IIR);             //Аргумент - частота дискретизации, Гц

SoundCodecInterruptConfig(ENABLE);

 

//Инициализация АЦП

ADCConfig();

 

//Инициализация генератора входного сигнала

SignalGenConfig();

 

//Инициализация графического интерфейса, джойстика, системы измерений

GgInterfaceInit();

 

//ОСНОВНОЙ ЦИКЛ

while (1)

{

if (TransferBuf != ProcBuf)             //Ожидание заполнения буфера

{

TimeMarker3();                        //Метка времени выполнения № 3 (НАЧАЛО ОБРАБОТКИ)

DataIn = ProcBuf ? DataIn1 : DataIn0; //Установка указателей на обрабатываемые буферы

DataOut = ProcBuf ? DataOut1 : DataOut0;

 

#ifndef FLOAT_PROC                 //В а р и а н т обработки с фиксированной точкой

arm_fir_q15(&SF, DataIn, DataOut, BlockSize);             //Только FIR-фильтр

 

#else                              //В а р и а н т  обработки с плавающей точкой

if (!ProcessMode)

   arm_fir_f32(&SF, DataIn, DataOut, BlockSize);           //FIR-фильтр

else

{                                                         //IIR-фильтр

   arm_scale_f32(DataIn, GainScale, DataIn, BlockSize);    //Масштабирование отсчетов

   arm_biquad_cascade_df1_f32(&SI, DataIn, DataOut, BlockSize); //Фильтрация

}

#endif

ProcBuf ^= 1;                         //Переключение на другой буфер

TimeMarker4();                        //Метка времени выполнения № 4 (КОНЕЦ ОБРАБОТКИ)

}

 

GgControl();                            //Управление частотой и амплитудой генератора сигнала,

                                            // вывод результатов измерений

if (i++ == 0x800) STM_LEDOff(LED1);     //Тестовое управление индикатором

if (i == 0x50000) STM_LEDOn(LED1), i = 0;

 

//Проверка нажатия кнопки WAKEUP завершения программы

if (STM_PBGetState(BUTTON_WAKEUP)) NVIC_SystemReset();

}

//ОКОНЧАНИЕ ОСНОВНОГО ЦИКЛА

}

 

//---------------------------------------------------------------------------

// ОБСЛУЖИВАНИЕ ПРЕРЫВАНИЯ С ЧАСТОТОЙ ДИСКРЕТИЗАЦИИ

// Данная подпрограмма вызывается из обработчика прерывания ..._IRQHandler(),

// реализованного в adcdac.c

// Частота дискретизации формируется модулем процессора SPI/I2S,

// посредством которого по интерфейсу I2S отсчеты сигнала выводятся на внешний звуковой кодек.

// Этот модуль также генерирует прерывания с частотой дискретизации. В обработчике

// прерывания, размещенном здесь, производятся следующие операции:

// - считываются отсчеты входного сигнала с АЦП или цифрового входа;

// - АЦП запускается на следующий цикл преобразования;

// - входные отсчеты размещаются в одном из входных буферов;

// - из выходного буфера с тем же номером извлекаются обработанные отсчеты и передаются кодеку;

// - проверяется заполнение текущего буфера и при необходимости производится их переключение.

 

void Sample_Handler(void)

{

extern int16_t GeneratorSamples; //Цифровой выход генератора сигналов (в доп. коде)

                                  // параметр объявлен в adcdac.c

if (HardwareMode == 0)

{ //Получение данных с АЦП, преобразование смещенного кода в дополнительный,

// коррекция нулевого уровня

DataADC = ADC_GetConversionValue(ADC1) ^ 0x8000;

DataChannel2 = DataChannel1 = DataADC - AmplOffset;

}

//Получение цифрового отсчета входного сигнала (минуя АЦП)

else DataChannel2 = DataChannel1 = GeneratorSamples;

 

//Перезапуск АЦП

ADC_SoftwareStartConv(ADC1);

 

//Сохранение входных отсчетов в текущем буфере, чтение выходных отсчетов

#ifndef FLOAT_PROC                 //В а р и а н т обработки с фиксированной точкой

if (TransferBuf)

{ DataIn1[DataIndex] = DataChannel1;

DataChannel1 = DataOut1[DataIndex++];

}

else 

{ DataIn0[DataIndex] = DataChannel1;

DataChannel1 = DataOut0[DataIndex++];

}

#else                              //В а р и а н т обработки с плавающей точкой

if (TransferBuf)

{ DataIn1[DataIndex] = q15_to_float(DataChannel1);

DataChannel1 = float_to_q15(DataOut1[DataIndex++]);

}

else 

{ DataIn0[DataIndex] = q15_to_float(DataChannel1);

DataChannel1 = float_to_q15(DataOut0[DataIndex++]);

}

#endif

//Проверка достижения конца буфера, если да, переключение на другой буфер

if (DataIndex >= BlockSize) DataIndex = 0, TransferBuf ^= 1;

 

DataChannel2 = DataChannel1;

 

//Обработанные значения - в DataChannel1, DataChannel2

}

 

Пример файла коэффициентов iir_coef.h

 

 

#define numStages 4               //Число звеньев второго порядка

 

float IIR_coef[numStages*5] =

{

1.0000000000000000f, -0.8508242964744567f, 1.0000000000000000f, 1.2679487466812134f, -0.9085670709609985f,

1.0000000000000000f, -1.7376896142959595f, 1.0000000000000000f, 1.4469995498657227f, -0.9191916584968566f,

1.0000000000000000f, -1.1725169420242310f, 1.0000000000000000f, 1.2251321077346802f, -0.9785795807838439f,

1.0000000000000000f, -1.6086072921752930f, 1.0000000000000000f, 1.5572113990783691f, -0.9830712080001831f

};

 

float IIR_gain[numStages] =

{

0.2331655323505401f,

0.2331655323505401f,

0.7605150938034057f,

0.7605150938034057f

};

 

Пример файла коэффициентов FIR фильтра см. в предыдущем проекте.

 


Дата добавления: 2018-04-05; просмотров: 348; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!