Исходные тексты модулей проекта 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 фильтра см. в предыдущем проекте.

 


Формирование файлов коэффициентов по результатам синтеза в среде MATLAB

 

Модуль fir_coef.m

 

% Формирование заголовочного файла с коэффициентами FIR-фильтра

% из массива Num, экспортируемого из оболочки Filter Design

fname = 'D:\Arm\Work\DspLab_fir_iir\fir_coef.h'; % Имя файла по умолчанию

fid = fopen(fname,'r');

yn = 1;

if fid > 0

fclose(fid);

yn = input('Перезаписать существующий файл? Введите 1 (да) или иное (нет): ');

end;

nt = length(Num);

if yn == 1 && nt > 0

if bitand(nt, 1) % Приведение числа коэффициентов к четному значению

nt = nt + 1; Num(nt) = 0;

end;

fid = fopen(fname,'w');

fprintf(fid, '\n#define numTaps %d\n\n', nt);

fprintf(fid, 'float FIR_coef[numTaps] =\n{\n ');

j = 0;

for i = 1: nt - 1

fprintf(fid, ' %1.16ff,', Num(i));

j = j + 1;

if (j >= 4) j = 0; fprintf(fid, '\n ');

end;

end;

fprintf(fid, ' %1.16ff\n};\n', Num(nt));

fclose(fid);

fprintf(1, 'Файл %s создан\n', fname);

end;

 

Модуль iir_coef.m

 

% Формирование заголовочного файла с коэффициентами IIR-фильтра

% из массивов G, SOS, экспортируемых из оболочки Filter Design.

% Матрица SOS имеет размер n x 6 (n - число секций),

% коэффициенты в строке: b0, b1, b2, 1, a1, a2.

% Для DSP требуется 5 коэффициентов: b0, b1, b2, -a1, -a2

fname = 'D:\Arm\Work\DspLab_fir_iir\iir_coef.h'; % Имя файла по умолчанию

fid = fopen(fname,'r');

yn = 1;

if fid > 0

fclose(fid);

yn = input('Перезаписать существующий файл? Введите 1 (да) или иное (нет): ');

end

[ns, nc] = size(SOS);

if (yn == 1 && ns > 0 && nc == 6)

fid = fopen(fname,'w');

fprintf(fid, '\n#define numStages %d\n\n', ns);

fprintf(fid, 'float IIR_coef[numStages*5] =\n{\n ');

for i = 1: ns

for j = 1: 3

fprintf(fid, ' %1.16ff,', SOS(i,j)); %b0, b1, b2

end

fprintf(fid, ' %1.16ff,', -SOS(i,5)); %-a1

fprintf(fid, ' %1.16ff', -SOS(i,6)); %-a2

if i ~= ns fprintf(fid, ',\n ');

else fprintf(fid, '\n');

end

end

fprintf(fid, '};\n');

fprintf(fid, '\nfloat IIR_gain[numStages] =\n{\n ');

for i = 1: ns - 1

fprintf(fid, ' %1.16ff,\n ', G(i));

end

fprintf(fid, ' %1.16ff\n};\n', G(ns));

fclose(fid);

fprintf(1, 'Файл %s создан\n', fname);

end



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: