Исходные тексты модулей проекта 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; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!