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



ОТЧЕТ ПО ВЫПОЛНЕНИЮ ЛАБОРАТОРНЫХ РАБОТ

По дисциплине «Цифровая обработка телекоммуникационных сигналов»

Лабораторная работа № 3

Синтез цифровых фильтров на процессорах
с ядром ARM Cortex-M4

 

Выполнил студент:                                             Дата выполнения:

 

 

1. Тестовый КИХ-фильтр с непрерывной обработкой.

 

Примерный вид АЧХ (указать тип, порядок, обозначить названия параметров, единиц измерения)

Тип фильтра:              Порядок фильтра:

 

Времена обработки при использовании различных форматов данных

 

  C фиксированной точкой C плавающей точкой и FPU C плавающей точкой без FPU
Время ввода отсчета      
Время обработки отсчета      
Время вывода отсчета      
Приведенное время одной итерации умножения-суммирования      

 

 

2. Тестовый КИХ-/БИХ-фильтр с блочной обработкой

 

Время ввода-вывода одного отсчета: … мкс

Время обработки блока отсчетов: … мкс

Время обработки одного отсчета: … мкс

Полное время, затрачиваемое на ввод-вывод-обработку отсчета: … мкс

Порядок фильтра: …

Приведенное время одной итерации умножения-суммирования: … мкс

Период дискретизации: … мкс

Коэффициент загрузки процессора: … %

 


3. Синтез КИХ- и БИХ-фильтров

 

Текст задания

Вариант … . Полоса частот входного сигнала ……….

 

КИХ-фильтр

 

Response Type (тип АЧХ)  
Design Method (метод синтеза):  
Частота дискретизации Fs  
Границы полосы пропускания Fpass  
Границы полосы ослабления Fstop  
Неравномерность в полосе пропускания Apass  
Уровень ослабления Astop  
Порядок фильтра (Order)  

 

Разностное уравнение:

yk =

Например, при порядке 50:

yk = -0.000919∙Xk - 0.002718∙Xk-1 + 0.002486∙Xk-2 + ... - 0.002718∙Xk-49 - 0.000919∙Xk-50

 

БИХ-фильтр

 

 

Response Type (тип АЧХ)  
Design Method (метод синтеза):  
Частота дискретизации Fs  
Границы полосы пропускания Fpass  
Границы полосы ослабления Fstop  
Неравномерность в полосе пропускания Apass  
Уровень ослабления Astop  
Порядок фильтра (Order)  
Число биквадратных звеньев (Sections)  
Признак стабильности фильтра (Stable)  

 

Разностные уравнения для первого и последнего звеньев :

yk =

yk =

 

 


4. Практическая реализация КИХ- и БИХ-фильтра

 

Таблица АЧХ КИХ- и БИХ-фильтров

 

  Частота, Гц                          
КИХ-фильтр, коэффициент передачи, дБ                        
БИХ-фильтр, коэффициент передачи, дБ                        

 

 

  Частота, Гц                          
КИХ-фильтр, коэффициент передачи, дБ                        
БИХ-фильтр, коэффициент передачи, дБ                        

 

 

Теоретические и экспериментальные АЧХ КИХ- и БИХ-фильтров

 

 

Времена блочной и непрерывной обработки для КИХ-/БИХ-фильтров и данных в форматах с фиксированной точкой (16 бит) и плавающей точкой (32 бита)

 

 

Блочная обработка

Непрерывная обработка

КИХ-фильтр

БИХ-фильтр

КИХ-фильтр

Фикс. Плав. Плав. Фикс. Плав.
Время ввода-вывода отсчета          
Время обработки блока отсчетов          
Время обработки одного отсчета          
Приведенное время одной итерации умножения-суммирования          
Коэффициент загрузки процессора          

 

 

5. Синтез многополосного фильтра (по второму каналу)

 

Исходные данные

 

Тип фильтра:

Центральные частоты полос:

Полоса пропускания:

Полоса ослабления:

 

Исходные данные для программы Filter Design:

 

Частота дискретизации:

Вектор частот (Freq. vector):

Вектор амплитуд (Mag. vector):

Вектор вес. коэф. (Weight vector):

Задаваемый порядок (Specify order):

 

 

АЧХ, построенная программой синтеза

 

 

 

Текст программы

 

 


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

 

Модуль main.c

 

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

 *

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

 *

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

 * Непрерывная обработка для каждого отсчета сигнала

 *

 * Copyright (C) 2015 МИРЭА

 * Версия: 1.3

 *

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

/*

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

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

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

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

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

*/

 

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

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

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

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

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

 

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

// Объявления данных

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

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

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

int32_t Modes = 0;                 //Режимы обработки и конфигурация системы:

                                   // 0: аналоговый генератор -> АЦП -> обработка

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

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

// Прототипы функций в Proc.c

void DataInit(void);

void Proc(void);

 

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

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

int main()

{

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

  volatile uint32_t i = 0; 

 

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

DataInit();

 

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

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 

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

STM_LEDInit(LED1);

 

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

STM_PBInit(BUTTON_TAMPER, BUTTON_MODE_GPIO);

STM_PBInit(BUTTON_WAKEUP, BUTTON_MODE_GPIO);

 

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

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

SoundCodecInterruptConfig(ENABLE);

 

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

ADCConfig();

 

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

SignalGenConfig();

 

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

GgInterfaceInit();

 

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

while (1)

{

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

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

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

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

 

if (STM_PBGetState(BUTTON_WAKEUP)) break; //Выход из основного цикла, если нажата WAKEUP

}

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

 

//Сброс процессора - завершение выполнения данной программы, запуск начального загрузчика

NVIC_SystemReset();

 

while (1) {}

}

 

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

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

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

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

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

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

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

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

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

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

// - вызывается процедура обработки Proc(), возвращающая выходные отсчеты;

// - выходные отсчеты передаются кодеку.

void Sample_Handler(void)

{

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

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

if (Modes == 0)

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

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

DataADC = ADC_GetConversionValue(ADC1) ^ 0x8000;

DataChannel2 = DataChannel1 = DataADC - AmplOffset;

}

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

else DataChannel2 = DataChannel1 = GeneratorSamples;

 

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

ADC_SoftwareStartConv(ADC1);

 

//Вызов подпрограммы цифровой обработки сигнала (реализована в proc.c)

TimeMarker2();                  //Временная метка № 2

Proc();

TimeMarker3();                  //Временная метка № 3

 

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

}

 

 

Модуль proc.c

 

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

 *

 * ПОДПРОГРАММЫ ЦИФРОВОЙ ОБРАБОТКИ СИГНАЛА

 *

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

 * Непрерывная обработка для каждого отсчета сигнала

 *

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

 

/* Подключаемые заголовочные файлы */

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

#include "coef.h"                  //Значения коэффициентов

 

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

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

 

/* Константы */

// numTaps                         //Число отсчетов/коэффициентов - задано в coef.h

// float FIR_coef[numTaps]         //Массив коэффициентов в формате float - задан в coef.h

 

/* Текущие переменные */

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

          DataChannel2;       // (объявлены в main.c)

              

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

int16_t Samples[numTaps];          //Буфер 16-разрядных отсчетов (циклический) в формате 1.15

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

int16_t* pSamples;                 //Указатель на отсчеты

int16_t* pSamplesEnd;              //Указатель на конец буфера отсчетов

int32_t* pCoeffs;                  //Указатель на коэффициенты

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

float Samples[numTaps];           //Буфер отсчетов

float* pSamples;                   //Указатель на отсчеты

float* pSamplesEnd;                //Указатель на конец буфера отсчетов

float* pCoeffs;                    //Указатель на коэффициенты

#endif

 

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

ПОДПРОГРАММА ИНИЦИАЛИЗАЦИИ ФИЛЬТРА

Вызывается однократно при старте программы

*/

void DataInit(void)

{

#ifndef FLOAT_PROC

int32_t i;                       //Для варианта обработки с фиксированной точкой:

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

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

#endif 

pSamples = Samples;              //Установка указателя отсчетов на начало буфера

pSamplesEnd = Samples + numTaps; //Задание указателя конца буфера отсчетов

}

 

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

ПОДПРОГРАММА ОБРАБОТКИ

Вызывается с частотой дискретизации при получении новых отсчетов.

Отсчеты входного сигнала для первого и второго каналов

размещены в глобальных переменных DataChannel1, DataChannel2. В эти же

переменные записываются обработанные отсчеты по соответствующим каналам.

В исходном варианте производится обработка данных только первого канала.

*/

void Proc(void)

{

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

 

int32_t x, b;                    //Текущие значения отсчета и коэффициента

int32_t i = numTaps;             //Счетчик циклов умножений-накоплений

int64_t acc = 0;                 //Очистка 64-разрядного аккумулятора (накопителя)

 

pCoeffs = &Coeffs[numTaps-1];    //Установка указателя на последний коэффициент bN

*pSamples++ = DataChannel1;      //Сохранение входного отсчета в памяти

if (pSamples >= pSamplesEnd) pSamples = Samples; //Проверка перехода на начало циклического буфера

 

do                               //Организация цикла с счетчиком i, изменяющимся от numTaps до 1

{

  x = *pSamples++;               //Выборка отсчета, продвижение указателя на следующий отсчет

b = *pCoeffs--;                //Выборка коэффициента, продвижение указателя на предыдущий коэффициент

acc += (int64_t)b * x;         //Умножение коэффициента и отсчета с накоплением

if (pSamples >= pSamplesEnd) pSamples = Samples; //Проверка перехода на начало циклического буфера

 

} while (--i != 0);              //Декремент счетчика i, проверка его на обнуление

 

DataChannel1 = (int16_t)(acc >> 31u); //Преобразование формата 2.62 в формат 1.31 с усечением до 1.15

 

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

 

float x, b;                      //Текущие значения отсчета и коэффициента

int32_t i = numTaps;             //Счетчик циклов умножений-накоплений

float acc = 0;                   //Очистка аккумулятора (накопителя)

 

pCoeffs = &FIR_coef[numTaps-1];  //Установка указателя на последний коэффициент bN

  *pSamples++ = q15_to_float(DataChannel1); //Преобразование входного отсчета в формат float,

                                       // сохранение его в памяти

if (pSamples >= pSamplesEnd) pSamples = Samples; //Проверка перехода на начало циклического буфера

 

do                               //Организация цикла с счетчиком i, изменяющимся от numTaps до 1

{

x = *pSamples++;               //Выборка отсчета, продвижение указателя на следующий отсчет

b = *pCoeffs--;                //Выборка коэффициента, продвижение указателя на предыдущий коэффициент

acc += b * x;                  //Умножение коэффициента и отсчета с накоплением

if (pSamples >= pSamplesEnd) pSamples = Samples; //Проверка перехода на начало циклического буфера

 

} while (--i != 0);              //Декремент счетчика i, проверка его на обнуление

 

DataChannel1 = float_to_q15(acc); //Преобразование формата float в формат 1.15

 

#endif 

 

DataChannel2 = DataChannel1;

}

 

 

Пример заголовочного модуля coef.h (fir_coef.h)

 

#define numTaps 34                //Число коэффициентов

 

float FIR_coef[numTaps] =

{

0.0214619597717033f, 0.0307411336820300f, 0.0038734707706876f, -0.0082041254073283f,

-0.0381282158344837f, -0.0378178633033697f, -0.0198560236913657f, 0.0217448788296480f,

0.0539662691353649f, 0.0594653676995162f, 0.0257788446908599f, -0.0276575170129635f,

-0.0704352004893433f, -0.0728329271355395f, -0.0310751415250206f, 0.0317280678231007f,

0.0771282967388960f, 0.0771282967388960f, 0.0317280678231007f, -0.0310751415250206f,

-0.0728329271355395f, -0.0704352004893433f, -0.0276575170129635f, 0.0257788446908599f,

0.0594653676995162f, 0.0539662691353649f, 0.0217448788296480f, -0.0198560236913657f,

-0.0378178633033697f, -0.0381282158344837f, -0.0082041254073283f, 0.0038734707706876f,

0.0307411336820300f, 0.0214619597717033f

};

 

 


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

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






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