本文主要是介绍[DSP学习笔记]基于TMS320F28335的IIR滤波实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、前言
IIR滤波器,递归滤波器,顾名思义,IIR滤波器采用递归型结构,结构上带有反馈回路。IIR数字滤波器相较于FIR数字滤波器具备幅频特性精度高的特点。
二、移植官方库
首先我们先将C2000 wave中我们所需要的函数库给导入到我们的新建工程中(可见于我实现FIR滤波文章中导入函数库的操作)。
工程中可见有以下文件。(仅进行滤波可删除FFT有关文件)
同时记得添加头文件路径
至此,对于我们进行滤波所需的函数库已经移植完毕。
三、借助MATLAB生成测试信号
使用MATLAB生成输入测试信号(相关程序可见于我另两篇文章)
%这里仅给出设定信号相关参数
fs=1e5; %设采样率为100K
f = [1e3,5e3,1e4]; %频率矩阵(1*N)测试信号频率为1K,5K,10K
phase = [0,0,0]; %初相位均为0
amp = [0.3,1.0,0.5];%幅度
N=512; %采样点数
生成信号的时域图与频域图如下:
将刚刚MATLAB生成的record.txt复制到input.c(没有就新建一个)中。
这里笔者给出自己生成好的输入信号
//#############################################################################
//! \file input.c
//! \brief Input Vector (1024)
//! \author Vishal Coelho
//! \date 16-Sep-2016
//!
//
// Group: C2000
// Target Family: $DEVICE$
//
//#############################################################################
//
//
// $Copyright: Copyright (C) 2022 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//#############################################################################
float test_input[512] = {0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,0.093107,-0.114798,-0.426010,-0.757295,-0.991651,-1.021653,-0.791865,-0.323977,0.285317,0.893485,1.358000,1.582180,1.544357,1.300000,0.956572,0.631123,0.406943,0.305699,0.285317,0.263809,0.159191,-0.070597,-0.403866,-0.757295,-1.013795,-1.065855,-0.857949,-0.411682,0.176336,0.763658,1.207840,1.412279,1.355387,1.092705,0.731771,0.389703,0.149857,0.033962,0.000000,-0.033962,-0.149857,-0.389703,-0.731771,-1.092705,-1.355387,-1.412279,-1.207840,-0.763658,-0.176336,0.411682,0.857949,1.065855,1.013795,0.757295,0.403866,0.070597,-0.159191,-0.263809,-0.285317,-0.305699,-0.406943,-0.631123,-0.956572,-1.300000,-1.544357,-1.582180,-1.358000,-0.893485,-0.285317,0.323977,0.791865,1.021653,0.991651,0.757295,0.426010,0.114798,-0.093107,-0.176103,-0.176336,-0.175872,-0.256783,-0.461223,-0.767601,-1.092705,-1.319556,-1.340760,-1.100913,-0.621747,-0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,0.093107,-0.114798,-0.426010,-0.757295,-0.991651,-1.021653,-0.791865,-0.323977,0.285317,0.893485,1.358000,1.582180,1.544357,1.300000,0.956572,0.631123,0.406943,0.305699,0.285317,0.263809,0.159191,-0.070597,-0.403866,-0.757295,-1.013795,-1.065855,-0.857949,-0.411682,0.176336,0.763658,1.207840,1.412279,1.355387,1.092705,0.731771,0.389703,0.149857,0.033962,0.000000,-0.033962,-0.149857,-0.389703,-0.731771,-1.092705,-1.355387,-1.412279,-1.207840,-0.763658,-0.176336,0.411682,0.857949,1.065855,1.013795,0.757295,0.403866,0.070597,-0.159191,-0.263809,-0.285317,-0.305699,-0.406943,-0.631123,-0.956572,-1.300000,-1.544357,-1.582180,-1.358000,-0.893485,-0.285317,0.323977,0.791865,1.021653,0.991651,0.757295,0.426010,0.114798,-0.093107,-0.176103,-0.176336,-0.175872,-0.256783,-0.461223,-0.767601,-1.092705,-1.319556,-1.340760,-1.100913,-0.621747,-0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,0.093107,-0.114798,-0.426010,-0.757295,-0.991651,-1.021653,-0.791865,-0.323977,0.285317,0.893485,1.358000,1.582180,1.544357,1.300000,0.956572,0.631123,0.406943,0.305699,0.285317,0.263809,0.159191,-0.070597,-0.403866,-0.757295,-1.013795,-1.065855,-0.857949,-0.411682,0.176336,0.763658,1.207840,1.412279,1.355387,1.092705,0.731771,0.389703,0.149857,0.033962,0.000000,-0.033962,-0.149857,-0.389703,-0.731771,-1.092705,-1.355387,-1.412279,-1.207840,-0.763658,-0.176336,0.411682,0.857949,1.065855,1.013795,0.757295,0.403866,0.070597,-0.159191,-0.263809,-0.285317,-0.305699,-0.406943,-0.631123,-0.956572,-1.300000,-1.544357,-1.582180,-1.358000,-0.893485,-0.285317,0.323977,0.791865,1.021653,0.991651,0.757295,0.426010,0.114798,-0.093107,-0.176103,-0.176336,-0.175872,-0.256783,-0.461223,-0.767601,-1.092705,-1.319556,-1.340760,-1.100913,-0.621747,0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,0.093107,-0.114798,-0.426010,-0.757295,-0.991651,-1.021653,-0.791865,-0.323977,0.285317,0.893485,1.358000,1.582180,1.544357,1.300000,0.956572,0.631123,0.406943,0.305699,0.285317,0.263809,0.159191,-0.070597,-0.403866,-0.757295,-1.013795,-1.065855,-0.857949,-0.411682,0.176336,0.763658,1.207840,1.412279,1.355387,1.092705,0.731771,0.389703,0.149857,0.033962,-0.000000,-0.033962,-0.149857,-0.389703,-0.731771,-1.092705,-1.355387,-1.412279,-1.207840,-0.763658,-0.176336,0.411682,0.857949,1.065855,1.013795,0.757295,0.403866,0.070597,-0.159191,-0.263809,-0.285317,-0.305699,-0.406943,-0.631123,-0.956572,-1.300000,-1.544357,-1.582180,-1.358000,-0.893485,-0.285317,0.323977,0.791865,1.021653,0.991651,0.757295,0.426010,0.114798,-0.093107,-0.176103,-0.176336,-0.175872,-0.256783,-0.461223,-0.767601,-1.092705,-1.319556,-1.340760,-1.100913,-0.621747,0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,0.093107,-0.114798,-0.426010,-0.757295,-0.991651,-1.021653,-0.791865,-0.323977,0.285317,0.893485,1.358000,1.582180,1.544357,1.300000,0.956572,0.631123,0.406943,0.305699,0.285317,0.263809,0.159191,-0.070597,-0.403866,-0.757295,-1.013795,-1.065855,-0.857949,-0.411682,0.176336,0.763658,1.207840,1.412279,1.355387,1.092705,0.731771,0.389703,0.149857,0.033962,0.000000,-0.033962,-0.149857,-0.389703,-0.731771,-1.092705,-1.355387,-1.412279,-1.207840,-0.763658,-0.176336,0.411682,0.857949,1.065855,1.013795,0.757295,0.403866,0.070597,-0.159191,-0.263809,-0.285317,-0.305699,-0.406943,-0.631123,-0.956572,-1.300000,-1.544357,-1.582180,-1.358000,-0.893485,-0.285317,0.323977,0.791865,1.021653,0.991651,0.757295,0.426010,0.114798,-0.093107,-0.176103,-0.176336,-0.175872,-0.256783,-0.461223,-0.767601,-1.092705,-1.319556,-1.340760,-1.100913,-0.621747,0.000000,0.621747,1.100913,1.340760,1.319556,1.092705,0.767601,0.461223,0.256783,0.175872,0.176336,0.176103,};// End of File
四、借助MATLAB计算IIR滤波器系数
首先进入MATLAB的filterDesigner。
滤波器截止频率选择2000Hz,滤除高频噪声,指定阶数为50阶。
将生成的滤波器系数导入到工作区
由于系数在SOS矩阵的行中排序为(b0,b1,b2,1,-a1,-a2),于是我们需要对其第五列与第六列进行取反操作。
这点在MATLAB提供的文档以及TI的例程注释中有提出
MATLAB提供的文档:
TI给出的注释:
G矩阵的元素为每一个对应的二阶节的增益。
编写MATLAB程序,处理导出到工作区的滤波器系数,并保存到本地便于我们后续使用
%将通过filterDesigner生成的SOS、G矩阵处理,保存到本地的coeffs_B.txt、coeffs_A.txt和scaleFactors.txtSOS_num=size(SOS,1);%获取SOS矩阵的行数
G_num=size(G,1);%获取G矩阵的行数
%对生成的系数A取反
SOS(:,5)=-SOS(:,5);
SOS(:,6)=-SOS(:,6);%将滤波器设计器生成的滤波器系数打印到coeffs_B,coeffs_A.txt文件中
fileID = fopen('coeffs_B.txt','w');%写文件
for i=1:1:SOS_numfprintf(fileID,'%6f,%6f,%6f,\n',SOS(i,1),SOS(i,2),SOS(i,3));
end
fclose(fileID);%将生成的初始信号保存到.m文件路径下的coeffs_B.txtfileID = fopen('coeffs_A.txt','w');%写文件
for i=1:1:SOS_numfprintf(fileID,'%6f,%6f,%6f,\n',SOS(i,4),SOS(i,5),SOS(i,6));
end
fclose(fileID);%将生成的初始信号保存到.m文件路径下的coeffs_A.txt%将滤波器设计器生成的比例系数打印到scaleFactors.txt文件中
fileID = fopen('scaleFactors.txt','w');%写文件TEMP=G(1:G_num-1,1);%取G前G_num-1个数
count=0;
for i=1:1:(G_num-1)fprintf(fileID,'%6f,',TEMP(i,1));count=count+1;if count==3fprintf(fileID,'\n');%每三个元素后就换行count=0;end
end
生成的滤波器系数及对应增益如下:
/** Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool* Generated by MATLAB(R) 9.11 and Signal Processing Toolbox 8.7.* Generated on: 24-Jul-2023 16:04:36*//** 离散时间 IIR 滤波器(实数)* ----------------* 滤波器结构 : 直接 II 型,二阶节* 节数 : 25* 稳定 : 是* 线性相位 : 否*//* General type conversion for MATLAB generated C-code */#define SOS_NUM (25U) // Number of Second Order Stages (biquad)const float scaleFactors[SOS_NUM]= {0.891251,1.000000,1.000000,1.000000,1.000000,1.000000,0.999999,0.999998,0.999996,0.999990,0.999976,0.999942,0.999861,0.999668,0.999202,0.998086,0.995413,0.989026,0.973869,0.938459,0.858783,0.694654,0.418945,0.129278,0.004035,
};
const float coeffs_B[SOS_NUM*3] = {1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984229,1.000000,1.000000,-1.984228,1.000000,1.000000,-1.984227,1.000000,1.000000,-1.984223,1.000000,1.000000,-1.984214,1.000000,1.000000,-1.984193,1.000000,1.000000,-1.984141,1.000000,1.000000,-1.984016,1.000000,1.000000,-1.983712,1.000000,1.000000,-1.982959,1.000000,1.000000,-1.981005,1.000000,1.000000,-1.975321,1.000000,1.000000,-1.952864,1.000000,1.000000,-1.685740,1.000000,1.000000,-1.984229,1.000000,
};
const float coeffs_A[SOS_NUM*3] = {1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-1.000000,1.000000,1.984229,-0.999999,1.000000,1.984228,-0.999999,1.000000,1.984227,-0.999997,1.000000,1.984224,-0.999992,1.000000,1.984216,-0.999980,1.000000,1.984197,-0.999953,1.000000,1.984150,-0.999886,1.000000,1.984040,-0.999727,1.000000,1.983777,-0.999348,1.000000,1.983154,-0.998450,1.000000,1.981703,-0.996359,1.000000,1.978466,-0.991696,1.000000,1.971931,-0.982279,1.000000,1.961429,-0.967146,1.000000,1.951510,-0.952853,1.000000,1.984229,-1.000000,
};
至此已完成了大部分准备工作,接下来开始进行IIR滤波操作。
五、IIR滤波的代码实现
仿照TI给出的例程,完成了以下文件的编写
IIR.h文件
/** IIR.h**/#ifndef APP_IIR_H_
#define APP_IIR_H_#include "DSP28x_Project.h"
#include <stdio.h>
#include <string.h>void IIR_filter_run(void);#endif /* APP_IIR_H_ */
IIR.c文件
/** FIR.c** Created on: 2023年7月28日* Author: yang*/#include <IIR.h>
#include "dsp.h"
#include "fpu_filter.h"
#include <math.h>
#include "complex.h"
#include "fdacoefs.h"#define pi 3.14159
#define IIR_SIZE (512U)
#define NUM_SOS (25U) // Number of Second Order Stages (biquad)
#define FILTER_ORDER (NUM_SOS<<1)#pragma DATA_SECTION(coeffs_B, "IIR_buffer0");
#pragma DATA_SECTION(coeffs_A, "IIR_buffer0");
#pragma DATA_SECTION(IIR_output, "IIR_buffer1");// IIR_f32 object
IIR_f32 iir;
// Handle to the IIR_f32 object
IIR_f32_Handle hnd_iir = &iir;// The filter coefficients and scale factors are tacked on to the end of the
// MATLAB generated input
extern const float coeffs_B[];//系数数组大小在fdacoefs.h中定义,大小为滤波器节数*3
extern const float coeffs_A[];
extern const float scaleFactors[];// The delay line buffer
float delayLine[NUM_SOS*4U];float IIR_output[IIR_SIZE];
extern float test_input[];
//*****************************************************************************
// the function definitions
//*****************************************************************************
void IIR_filter_run(void)
{// Localsuint16_t i;float32u_t in, out;// Configure the objectIIR_f32_setCoefficientsBPtr(hnd_iir, coeffs_B);IIR_f32_setCoefficientsAPtr(hnd_iir, coeffs_A);IIR_f32_setDelayLinePtr(hnd_iir, delayLine);IIR_f32_setInputPtr(hnd_iir, (float *)&in);IIR_f32_setOutputPtr(hnd_iir, (float *)&out);IIR_f32_setScalePtr(hnd_iir, scaleFactors);IIR_f32_setOrder(hnd_iir, FILTER_ORDER);IIR_f32_setInitFunction(hnd_iir, (v_pfn_v)IIR_f32_init);IIR_f32_setCalcFunction(hnd_iir, (v_pfn_v)IIR_f32_calc);// Run the initialization functionhnd_iir->init(hnd_iir);for(i = 0U; i < IIR_SIZE; i++){out.f32 = FLT_MAX;in.f32 = test_input[i];// Call the calculation routinehnd_iir->calc(hnd_iir);IIR_output[i] = out.f32;}}// End of File
由于笔者使用了自定义段,故要在cmd文件中分配其对于的存储空间。Cmd文件如下:
/*
// TI File $Revision: /main/3 $
// Checkin $Date: July 9, 2008 14:12:45 $
//###########################################################################
//
// FILE: 28335_RAM_lnk.cmd
//
// TITLE: Linker Command File For IQmath examples that run out of RAM
//
// NOTE; The example project uses memory protected by the
// Code Security Module (CSM). Make sure the CSM is
// unlocked before you load the project. One quick way
// to do this on an erased device is to open a memory
// window to the CSM password locations. If these locations
// read back 0xFFFF (or non-zero), then the CSM is unlocked:
//
// Device Password locations
// 28335: 0x33FFF8 - 0x33FFFF
//
//###########################################################################
//
//
// $Copyright: Copyright (C) 2014-2022 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################
*/MEMORY
{
PAGE 0 :BEGIN : origin = 0x000000, length = 0x000002 /* Boot to M0 will go here */BOOT_RSVD : origin = 0x000002, length = 0x00004E /* Part of M0, BOOT rom will use this for stack */RAML0 : origin = 0x008000, length = 0x000800RAML1L2 : origin = 0x008800, length = 0x004800ZONE7A : origin = 0x200000, length = 0x00FC00 /* XINTF zone 7 - program space */FLASHH : origin = 0x300000, length = 0x008000 /* on-chip FLASH */FLASHG : origin = 0x308000, length = 0x008000 /* on-chip FLASH */FLASHF : origin = 0x310000, length = 0x008000 /* on-chip FLASH */FLASHE : origin = 0x318000, length = 0x008000 /* on-chip FLASH */FLASHD : origin = 0x320000, length = 0x008000 /* on-chip FLASH */FLASHC : origin = 0x328000, length = 0x008000 /* on-chip FLASH */FLASHA : origin = 0x338000, length = 0x007F80 /* on-chip FLASH */CSM_RSVD : origin = 0x33FF80, length = 0x000076 /* Part of FLASHA. Program with all 0x0000 when CSM is in use. */CSM_PWL : origin = 0x33FFF8, length = 0x000008 /* Part of FLASHA. CSM password locations in FLASHA */OTP : origin = 0x380400, length = 0x000400 /* on-chip OTP */ADC_CAL : origin = 0x380080, length = 0x000009IQTABLES : origin = 0x3FE000, length = 0x000b50 /* IQ Math Tables in Boot ROM */IQTABLES2 : origin = 0x3FEB50, length = 0x00008c /* IQ Math Tables in Boot ROM */FPUTABLES : origin = 0x3FEBDC, length = 0x0006A0 /* FPU Tables in Boot ROM */ROM : origin = 0x3FF27C, length = 0x000D44 /* Boot ROM */RESET : origin = 0x3FFFC0, length = 0x000002VECTORS : origin = 0x3FFFC2, length = 0x00003E /* part of boot ROM */PAGE 1 :BOOT_RSVD : origin = 0x000002, length = 0x00004E /* Part of M0, BOOT rom will use this for stack */RAMM0 : origin = 0x000050, length = 0x0003B0 /* on-chip RAM block M0 */RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */RAML3 : origin = 0x00D000, length = 0x001000RAML4 : origin = 0x00E000, length = 0x001000RAML5 : origin = 0x00F000, length = 0x001000ZONE7B : origin = 0x20FC00, length = 0x000400 /* XINTF zone 7 - data space */FLASHB : origin = 0x330000, length = 0x008000 /* on-chip FLASH */}SECTIONS
{FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD/* Setup for "boot to SARAM" mode:The codestart section (found in DSP28_CodeStartBranch.asm)re-directs execution to the start of user code. */codestart : > BEGIN, PAGE = 0#ifdef __TI_COMPILER_VERSION__#if __TI_COMPILER_VERSION__ >= 15009000.TI.ramfunc : {} LOAD = RAML0,RUN = RAML0,LOAD_START(_RamfuncsLoadStart),LOAD_END(_RamfuncsLoadEnd),RUN_START(_RamfuncsRunStart),LOAD_SIZE(_RamfuncsLoadSize),PAGE = 0#elseramfuncs : LOAD = RAML0,RUN = RAML0,LOAD_START(_RamfuncsLoadStart),LOAD_END(_RamfuncsLoadEnd),RUN_START(_RamfuncsRunStart),LOAD_SIZE(_RamfuncsLoadSize),PAGE = 0#endif
#endif.text : {*(.text)}>> RAML1L2|RAML0 PAGE = 0.cinit : > RAML0, PAGE = 0.pinit : > RAML0, PAGE = 0.switch : > RAML0, PAGE = 0.stack : > RAMM1, PAGE = 1.ebss : > RAML3, PAGE = 1.econst : > RAML3, PAGE = 1.sysmem : > RAML3, PAGE = 1.esysmem : > RAML3, PAGE = 1.sysmem : > RAML3, PAGE = 1IIR_buffer0 : > RAML4, PAGE = 1IIR_buffer1 : > RAML5, PAGE = 1.cio : > RAML3, PAGE = 1ZONE7DATA : > ZONE7B, PAGE = 1DMARAML4 : > RAML4, PAGE = 1DMARAML5 : > RAML5, PAGE = 1.reset : > RESET, PAGE = 0, TYPE = DSECT /* not used */csm_rsvd : > CSM_RSVD PAGE = 0, TYPE = DSECT /* not used for SARAM examples */csmpasswds : > CSM_PWL PAGE = 0, TYPE = DSECT /* not used for SARAM examples *//* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */.adc_cal : load = ADC_CAL, PAGE = 0, TYPE = NOLOAD}/*
//===========================================================================
// End of file.
//===========================================================================
*/
在主函数中,我们调用IIR_filter_run();函数即可完成滤波操作。
借助CCS的Graph画图工具测试滤波效果如下:
原始信号:
滤波后的1KHz信号:
可以看到IIR数字滤波器滤除了5KHz与10KHz的信号,仅保留了1KHz的信号(图中信号1个完整周期的采样点数为100点,滤波后信号幅度约为0.3,与理论值相符),从而验证滤波结果的准确性。
这篇关于[DSP学习笔记]基于TMS320F28335的IIR滤波实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!