数字滤波器的原理
1.从功能上分;低通、带通、高通、带阻。滤波器口诀:低通滤高频;高通滤低频;带通滤两边;带阻阻中间;
2.从实现方法上分:FIR、IIR
3.从设计方法上来分:Chebyshev(切比雪夫),Butterworth(巴特沃斯)
4.从处理信号分:经典滤波器、现代滤波器
经典滤波器从功能上分又可分为:
低通滤波器(LPAF/LPDF):Low pass analog filter
带通滤波器(BPAF/BPDF):Bandpass analog filter
高通滤波器(HPAF/HPDF):High pass analog filter
带阻滤波器(BSAF/BSDF):Bandstop analog filter
IIR滤波器和FIR滤波器
数字信号处理里面的滤波器分两种:一种是IIR滤波器,另一种是FIR滤波器,本质区别就是IIR滤波器的当前输出与以前的输出和输入有关,FIR滤波器只与输入有关,看一下差分方程就一目了然了。
更多对比参考:
细说IIR滤波器和FIR滤波器的区别_iir和fir的区别_Gordennizaicunzai的博客-CSDN博客
Matlab用指令实现滤波器
以下以IIR巴特沃斯带通滤波器设计为例。
fs=1000; %设置采样频率 1k
N=1024; %采样点数
n=0:N-1;
t=0:1/fs:1-1/fs; %时间序列
f=n*fs/N; %频率序列
x1=sin(2*pi*50*t); %噪声
x2=sin(2*pi*200*t); %信号
x=x1+x2; %信号混合
subplot(311);
plot(t,x); %绘制原始信号
xlabel('时间');
ylabel('幅值');
title('原始信号');
subplot(312);
y=fft(x,N); %绘制原始信号的幅频响应
plot(f,abs(y));
xlabel('频率/Hz');
ylabel('振幅');
title('原始信号 FFT');
subplot(313);
Wn=[125*2 300*2]/fs; %设置通带 125Hz 到 300Hz
[b,a]=butter(1,Wn); %注意第一个参数虽然是 1,但生成的却是 2 阶 IIR 滤波器系数
y2=filtfilt(b,a,x); %计算滤波后的波形 y2
y3=fft(y2,N); %滤波后波形的幅频响应
plot(f,abs(y3));
xlabel('频率/Hz');
ylabel('振幅');
title('滤波后信号 FFT');
Fdatool工具的使用
如果要对数据进行滤波,可以使用matlab提供的工具fdatool来进行滤波器的设计,我们可以设计出一系列的滤波器,并且可以实时看到滤波器的效果图,滤波器设计好之后,我们还可以对目标数据进行滤波,然后根据滤波的效果去调整滤波器的参数。
我们可以在matlab的命令行处输入fdatool命令来调出fdatool工具。
该界面内容较多,我们这里仅对较常使用的地方进行说明。
响应类型和设计方式
这里是滤波器的选择,从上到下依次是:
低通、高通、带通、带阻,接着是其他的一些特殊滤波器,这里面有个Notching陷波滤波器,常常用来滤除特定频率的信号比如工频干扰及其谐波。
再下方的就是IIR和FIR滤波器选择,这个根据需要去选择即可,具体滤波器的应用场景可以查阅相关资料。IIR里常用的就是巴特沃斯滤波器,FIR里常用的就是加窗方式window。
后面还有一些参数,我们就分别在滤波器的类型设计中去讲解吧。
这里先说一下几个问题:
第一个就是,FIR的阶数和IIR的阶数选择,基于FIR和IIR滤波器的特点,同样的效果,FIR需要比IIR有更多的阶数。通常,FIR的阶数都是几十几十的,甚至几百的,比如50阶、60阶、100阶、150阶等等,具体根据滤波效果来设定,总之,不能小,一小就效果差;相反,IIR设定的阶数不能大,一般不会超过6阶,常用的就是2阶或者4阶,如果大了,反而会溢出产生漂移等问题,初学者很容易看到IIR低阶效果不好,就加大阶数,这会适得其反。
第二个就是,我们可以通过参数图看下各参数是啥意思,通过幅频图直观地看到滤波器的效果,就是这个:
参数图
幅频图
可以直观地看到滤波器的效果。
接下来,依次介绍几个有代表性的滤波器,其他滤波器都是类似的。
IIR巴特沃斯低通滤波器
都比较好理解。
这里展示了当前滤波器的信息
有个地方需要注意,那就是Minimum order,虽然说是最小的阶数,但选中之后其实阶数很大,不知道是不是bug。
一般,我们手动指定阶数即可。
FIR加窗window低通滤波器
高通滤波器同理,不再赘述。
IIR巴特沃斯带通滤波器
带阻滤波器同理
单频率陷波滤波器
多频率陷波滤波器
这种滤波器被称作梳状滤波器,像一把梳子,可以滤去某个频率及其谐波成分,也就是某频率的所有整数倍频率,最常见的就是滤掉50Hz的工频干扰及其谐波。
这里需要注意的是,这里的阶数不能随便设,是有固定的数值的,=Fs/目标频率,比如,要滤掉50Hz及其谐波部分,采样率2000,那么这里的阶数就要填2000/50=40。
其他滤波器的参数补充
另外,还有一些其他滤波器,可能有一些不一样的参数,比如FIR默认的低通滤波器,截止频率填入时就不只是填入截止频率,而是填入一个范围
这里表示从Fpass开始截止,然后到Fstop时衰减到最低,看上面的幅频图就很明白了。
Wpass/Wstop/Apass/Astop这些意思都是差不多,分别调节衰减开始处和衰减结束出的频率范围精度,比如目标频率是50,如果这些值比较小,可能从49.5才开始衰减,但是值太大了,可能从45就开始衰减,这样的话,本来只想滤掉50Hz的频率,结果把45—55的频率都滤掉了。
再通俗点,就跟带阻滤波器两侧的范围误差差不多。
以上,就是设计滤波器时需要知道的一些参数设置。
这里总结一下,如何调节滤波器的效果?一般可以通过调节以下这些参数达到最适合的效果:
1、调节阶数,fir增大阶数,iir适当增加阶数;
2、陷波滤波器时提高品质;
3、调节Wpass/Wstop/Apass/Astop这些参数;
4、如果以上调节没什么改进的话,那就直接更换滤波器类型,比如,如果用IIR滤波器做带通,怎么调节效果都不好,那就直接换成FIR滤波器,再比如,如果陷波滤波器效果不好的话,就直接换成带阻滤波器。
……
总之,虽然需要一些经验,但也需要多多调试。
注意:设计滤波器时,所使用的阶数 n 应为偶数。
matlab验证滤波器效果
我们使用fdatool设置好滤波器参数之后,点击最下方的按钮Design Filter
此时,滤波器就设计好了。
接着,可以将设计好的滤波器导出成一个matlab对象。
fdatool工具界面上面,点击File——Export
这里的意思就是,将当前滤波器导出到matlab的变量空间Workspace,导出为对象,并且命名为Hd_bp,如果变量名已存在则覆盖,然后确定导出。
此时,在matlab的工作空间就会出现这个滤波器对象
接下来,我们准备好原始数据,然后对原始数据进行滤波
Fs = 2000;
%带通滤波器,Fir滤波
sig1 = filter(Hd_bp, VarName1);
%带阻滤波器,iir滤波
sig2 = filter(Hd_bs_50, sig1);
sig3 = filter(Hd_bs_100, sig2);
sig4 = filter(Hd_bs_150, sig3);%奇次谐波
sig5 = filter(Hd_bs_200, sig4);
sig6 = filter(Hd_bs_250, sig5);%奇次谐波
sig7 = filter(Hd_bs_300, sig6);
sig8 = filter(Hd_bs_350, sig7);%奇次谐波
sig9 = filter(Hd_bs_400, sig8);
sig10 = filter(Hd_bs_450, sig9);%奇次谐波
sig11 = filter(Hd_bs_500, sig10);
%频谱图
Y = fft(sig11);
L = length(Y);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
plot(f,P1);
%axis([0,Fs/2,0,2000]);
title('frequency-domain');
xlabel('f(Hz)');
ylabel('频率成分的幅值');
以上代码中,filter就是滤波函数,这里面放入两个参数,第一个就是刚才设计并导出的滤波器对象,第二个就是原始数据。
我们可以对滤波前后的数据分别绘制幅频图,以此来验证滤波效果。
上面的代码做了20~500的带通和工频干扰的带阻滤波,效果如下:
效果还是可以的。
STM32F4实现滤波器
我们在matlab设计好滤波器之后,如果把这个滤波器用到STM32里呢?因为F4有FPU,所以最好在F4上使用,要不速度会是个大问题。
其实也比较简单
如果是FIR滤波器,在滤波器设计好之后,导出头文件
Targets——Generate C header
生成并保存后,我们可以到目标路径去找到头文件并打开查看
这里面关键的就是个系数,系数的个数是设定的阶数+1,这是算法要求,不用管太多,直接拿到C里面使用即可。
如果是IIR滤波器
默认生成的IIR滤波器是II型
导出之前,我们先将滤波器转换成直接1型
Edit——Convert Struct
选择第一项并确定
然后File——Export导出为系数
系数中的关键信息就是系数和缩放系数
因为是4阶,由两个二阶滤波器组成,所以二阶滤波器系数有两组。
这里,系数分别为b0 b1 b2 a0 a1 a2,其中a0这个系数是固定的,所以不必使用。
同时,要注意的是,在STM32F4中用DSP调用时,需要将每组的a1和a2取反,即正的改成负的,负的改成正的。
这个看公式就知道了。
#include "IIR.h"
#include "arm_const_structs.h"
#include "stm32f4xx.h"
#define NUM_PER_CALL 1 //调用一次滤波函数所处理的采样点个数
//FIR带通滤波器
#define FIR_EFFICIENT_NUM 151 //fir滤波器系数个数
arm_fir_instance_f32 S_BP; //fir滤波器实例
static float32_t firStateF32[NUM_PER_CALL + FIR_EFFICIENT_NUM - 1]; //FIR状态缓存,大小FIR_EFFICIENT_NUM + NUM_PER_CALL - 1
const float32_t firCoeffs32BP[FIR_EFFICIENT_NUM] = //fir滤波器系数数组
{
0,6.783468507e-07,5.500670341e-06,6.206928447e-06,-3.594570046e-07,
1.734129728e-05,5.174893886e-05,3.377356188e-05,-6.174600458e-06,5.468466406e-05,
0.0001484536479,7.860602636e-05,-3.384135198e-05,0.0001032602231,0.0002951264905,
0.0001253946684,-0.0001162498447,0.0001406262745,0.0004820130707,0.0001433174912,
-0.0003082125622,0.0001265054452,0.0006859251298,8.190450171e-05,-0.0006903739995,
-5.077828102e-19,0.0008687517256,-0.0001297538547,-0.001369225443,-0.0003186257964,
0.000981297344,-0.000578189909, -0.00247148145,-0.0009198086918,0.0009743300034,
-0.001354034874,-0.004132688046,-0.001889958396,0.0008173419628, -0.00253453129,
-0.006482330617,-0.003291910049,0.0005241415929,-0.004162855446,-0.009630653076,
-0.005144232418,0.0001840474579,-0.006228647195, -0.01366603095, -0.00740425894,
-1.092867096e-18,-0.008654787205, -0.0186777208,-0.009959736839,0.0003446365299,
-0.01129483711, -0.02483416907, -0.01263269503, 0.00187640998, -0.013943634,
-0.03260042891, -0.01519669406, 0.005871396046, -0.01636073925, -0.04341268912,
-0.01740563288, 0.01548426691, -0.01830341667, -0.06258355826, -0.01902942732,
0.04320411757, -0.01956332289, -0.1251707077, -0.01988991722, 0.2981061041,
0.4799961746, 0.2981061041, -0.01988991722, -0.1251707077, -0.01956332289,
0.04320411757, -0.01902942732, -0.06258355826, -0.01830341667, 0.01548426691,
-0.01740563288, -0.04341268912, -0.01636073925, 0.005871396046, -0.01519669406,
-0.03260042891, -0.013943634, 0.00187640998, -0.01263269503, -0.02483416907,
-0.01129483711,0.0003446365299,-0.009959736839, -0.0186777208,-0.008654787205,
-1.092867096e-18, -0.00740425894, -0.01366603095,-0.006228647195,0.0001840474579,
-0.005144232418,-0.009630653076,-0.004162855446,0.0005241415929,-0.003291910049,
-0.006482330617, -0.00253453129,0.0008173419628,-0.001889958396,-0.004132688046,
-0.001354034874,0.0009743300034,-0.0009198086918, -0.00247148145,-0.000578189909,
0.000981297344,-0.0003186257964,-0.001369225443,-0.0001297538547,0.0008687517256,
-5.077828102e-19,-0.0006903739995,8.190450171e-05,0.0006859251298,0.0001265054452,
-0.0003082125622,0.0001433174912,0.0004820130707,0.0001406262745,-0.0001162498447,
0.0001253946684,0.0002951264905,0.0001032602231,-3.384135198e-05,7.860602636e-05,
0.0001484536479,5.468466406e-05,-6.174600458e-06,3.377356188e-05,5.174893886e-05,
1.734129728e-05,-3.594570046e-07,6.206928447e-06,5.500670341e-06,6.783468507e-07,
0
};
//IIR带阻滤波器-50Hz
#define numStages_50Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_50Hz;
static float32_t IIRStateF32_50Hz[4*numStages_50Hz];
static float32_t ScaleValue_50Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数
const float32_t IIRCoeffs32BP_50Hz[5*numStages_50Hz] =
{
1,-1.9754644172762135,1,1.9596811054397389,-0.98620549853243988,
1,-1.9754644172762135,1,1.9649189860762641,-0.98731438166310681
};
//IIR带阻滤波器-100Hz
#define numStages_100Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_100Hz;
static float32_t IIRStateF32_100Hz[4*numStages_100Hz];
static float32_t ScaleValue_100Hz = 0.99335783101529107 * 0.99335783101529107;//放缩系数
const float32_t IIRCoeffs32BP_100Hz[5*numStages_100Hz] =
{
1,-1.9021975146812826,1,1.8851730633310202,-0.98648991967768052,
1,-1.9021975146812826,1,1.8938697151225545,-0.98702972281202106
};
//IIR带阻滤波器-150Hz
#define numStages_150Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_150Hz;
static float32_t IIRStateF32_150Hz[4*numStages_150Hz];
static float32_t ScaleValue_150Hz = 0.99335783101529107 * 0.99335783101529107;//放缩系数
const float32_t IIRCoeffs32BP_150Hz[5*numStages_150Hz] =
{
1,-1.782092196243289,1,1.7640519295652939,-0.98658772855718069,
1,-1.782092196243289,1,1.7763809606964005,-0.98693187011384975
};
//IIR带阻滤波器-200Hz
#define numStages_200Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_200Hz;
static float32_t IIRStateF32_200Hz[4*numStages_200Hz];
static float32_t ScaleValue_200Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数
const float32_t IIRCoeffs32BP_200Hz[5*numStages_200Hz] =
{
1,-1.6181058535088741,1,1.5994425294189876,-0.98663912868667558,
1,-1.6181058535088741,1,1.6152032648694865,-0.98688045473364316
};
//IIR带阻滤波器-250Hz
#define numStages_250Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_250Hz;
static float32_t IIRStateF32_250Hz[4*numStages_250Hz];
static float32_t ScaleValue_250Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数
const float32_t IIRCoeffs32BP_250Hz[5*numStages_250Hz] =
{
1,-1.4142763744756295,1,1.3954270755132026,-0.98667212489138056,
1,-1.4142763744756295,1,1.4142763745489406,-0.98684745156199472
};
//IIR带阻滤波器-300Hz
#define numStages_300Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_300Hz;
static float32_t IIRStateF32_300Hz[4*numStages_300Hz];
static float32_t ScaleValue_300Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数
const float32_t IIRCoeffs32BP_300Hz[5*numStages_300Hz] =
{
1,-1.17562271738861,1,1.1570389697979899,-0.98669609658241275,
1,-1.17562271738861,1,1.1785379122261563,-0.98682347619380328
};
//IIR带阻滤波器-350Hz
#define numStages_350Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_350Hz;
static float32_t IIRStateF32_350Hz[4*numStages_350Hz];
static float32_t ScaleValue_350Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数
const float32_t IIRCoeffs32BP_350Hz[5*numStages_350Hz] =
{
1,-0.90802132733137575,1,0.91378825004392716,-0.98680445057512212,
1,-0.90802132733137575,1,0.8901524097715261,-0.98671512011202733
};
//IIR带阻滤波器-400Hz
#define numStages_400Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_400Hz;
static float32_t IIRStateF32_400Hz[4*numStages_400Hz];
static float32_t ScaleValue_400Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数
const float32_t IIRCoeffs32BP_400Hz[5*numStages_400Hz] =
{
1,-0.61806143864523178,1,0.62654427006115254,-0.98678826715653045,
1,-0.61806143864523178,1,0.60134116156514272,-0.98673130233100281
};
//IIR带阻滤波器-450Hz
#define numStages_450Hz 2 //2阶IIR滤波的个数
static arm_biquad_casd_df1_inst_f32 S_450Hz;
static float32_t IIRStateF32_450Hz[4*numStages_450Hz];
static float32_t ScaleValue_450Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数
const float32_t IIRCoeffs32BP_450Hz[5*numStages_450Hz] =
{
1,-0.31288282611132939,1,0.32387775390876944,-0.98677366833749702,
1,-0.31288282611132939,1,0.29771783508361671,-0.98674590052325395
};
//滤波后剩余的直流分量
#define DC_AFTER_FILTER 3088
//所有滤波器的初始化
void arm_emg_f32_filter_init()
{
//带通滤波器初始化
arm_fir_init_f32(&S_BP, FIR_EFFICIENT_NUM, (float32_t *)&firCoeffs32BP[0], &firStateF32[0], NUM_PER_CALL);
//IIR带阻滤波器-50Hz初始化
arm_biquad_cascade_df1_init_f32(&S_50Hz, numStages_50Hz, (float32_t *)&IIRCoeffs32BP_50Hz[0], (float32_t *)&IIRStateF32_50Hz[0]);
//IIR带阻滤波器-100Hz初始化
arm_biquad_cascade_df1_init_f32(&S_100Hz, numStages_100Hz, (float32_t *)&IIRCoeffs32BP_100Hz[0], (float32_t *)&IIRStateF32_100Hz[0]);
//IIR带阻滤波器-150Hz初始化
arm_biquad_cascade_df1_init_f32(&S_150Hz, numStages_150Hz, (float32_t *)&IIRCoeffs32BP_150Hz[0], (float32_t *)&IIRStateF32_150Hz[0]);
//IIR带阻滤波器-200Hz初始化
arm_biquad_cascade_df1_init_f32(&S_200Hz, numStages_200Hz, (float32_t *)&IIRCoeffs32BP_200Hz[0], (float32_t *)&IIRStateF32_200Hz[0]);
//IIR带阻滤波器-250Hz初始化
arm_biquad_cascade_df1_init_f32(&S_250Hz, numStages_250Hz, (float32_t *)&IIRCoeffs32BP_250Hz[0], (float32_t *)&IIRStateF32_250Hz[0]);
//IIR带阻滤波器-300Hz初始化
arm_biquad_cascade_df1_init_f32(&S_300Hz, numStages_300Hz, (float32_t *)&IIRCoeffs32BP_300Hz[0], (float32_t *)&IIRStateF32_300Hz[0]);
//IIR带阻滤波器-350Hz初始化
arm_biquad_cascade_df1_init_f32(&S_350Hz, numStages_350Hz, (float32_t *)&IIRCoeffs32BP_350Hz[0], (float32_t *)&IIRStateF32_350Hz[0]);
//IIR带阻滤波器-400Hz初始化
arm_biquad_cascade_df1_init_f32(&S_400Hz, numStages_400Hz, (float32_t *)&IIRCoeffs32BP_400Hz[0], (float32_t *)&IIRStateF32_400Hz[0]);
//IIR带阻滤波器-450Hz初始化
arm_biquad_cascade_df1_init_f32(&S_450Hz, numStages_450Hz, (float32_t *)&IIRCoeffs32BP_450Hz[0], (float32_t *)&IIRStateF32_450Hz[0]);
}
//带通滤波和带阻滤波
void arm_emg_f32_filter(float32_t *dataInput, float32_t *dataOutput)
{
float32_t dataOutputAfterFirbp = 0;
float32_t dataOutputAfterIIRbs_50Hz = 0;
float32_t dataOutputAfterIIRbs_100Hz = 0;
float32_t dataOutputAfterIIRbs_150Hz = 0;
float32_t dataOutputAfterIIRbs_200Hz = 0;
float32_t dataOutputAfterIIRbs_250Hz = 0;
float32_t dataOutputAfterIIRbs_300Hz = 0;
float32_t dataOutputAfterIIRbs_350Hz = 0;
float32_t dataOutputAfterIIRbs_400Hz = 0;
float32_t dataOutputAfterIIRbs_450Hz = 0;
//带通滤波
arm_fir_f32(&S_BP, dataInput, &dataOutputAfterFirbp, NUM_PER_CALL);
//50Hz带阻
arm_biquad_cascade_df1_f32(&S_50Hz, &dataOutputAfterFirbp, &dataOutputAfterIIRbs_50Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_50Hz *= ScaleValue_50Hz;
//100Hz带阻
arm_biquad_cascade_df1_f32(&S_100Hz, &dataOutputAfterIIRbs_50Hz, &dataOutputAfterIIRbs_100Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_100Hz *= ScaleValue_100Hz;
//150Hz带阻
arm_biquad_cascade_df1_f32(&S_150Hz, &dataOutputAfterIIRbs_100Hz, &dataOutputAfterIIRbs_150Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_150Hz *= ScaleValue_150Hz;
//200Hz带阻
arm_biquad_cascade_df1_f32(&S_200Hz, &dataOutputAfterIIRbs_150Hz, &dataOutputAfterIIRbs_200Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_200Hz *= ScaleValue_200Hz;
//250Hz带阻
arm_biquad_cascade_df1_f32(&S_250Hz, &dataOutputAfterIIRbs_200Hz, &dataOutputAfterIIRbs_250Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_250Hz *= ScaleValue_250Hz;
//300Hz带阻
arm_biquad_cascade_df1_f32(&S_300Hz, &dataOutputAfterIIRbs_250Hz, &dataOutputAfterIIRbs_300Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_300Hz *= ScaleValue_300Hz;
//350Hz带阻
arm_biquad_cascade_df1_f32(&S_350Hz, &dataOutputAfterIIRbs_300Hz, &dataOutputAfterIIRbs_350Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_350Hz *= ScaleValue_350Hz;
//400Hz带阻
arm_biquad_cascade_df1_f32(&S_400Hz, &dataOutputAfterIIRbs_350Hz, &dataOutputAfterIIRbs_400Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_400Hz *= ScaleValue_400Hz;
//450Hz带阻
arm_biquad_cascade_df1_f32(&S_450Hz, &dataOutputAfterIIRbs_400Hz, &dataOutputAfterIIRbs_450Hz, NUM_PER_CALL);
dataOutputAfterIIRbs_450Hz *= ScaleValue_450Hz;
//返回正数值以计算均方根
if(dataOutputAfterIIRbs_450Hz >= DC_AFTER_FILTER)
{
*dataOutput = dataOutputAfterIIRbs_450Hz - DC_AFTER_FILTER;
}
else
{
*dataOutput = DC_AFTER_FILTER - dataOutputAfterIIRbs_450Hz;
}
}
这里有个需要注意的问题,就是每次调用函数处理的数据个数,可以一个一个地处理,也可以一次处理多个,我这里是一个一个地处理的。其实,各滤波器就是个算法,也就是有个对应的公式,将数据输入进去,再输出即可,具体设计到傅里叶变换的知识,可自行查阅资料。
另外,这个FIR系数里有些是用科学计数法来表示的,不用特别处理,C能识别。在C语言中,我们可以使用科学计数法来表示数字。具体方法是在数字后面加上一个大写或小写的字母E,再加上一个指数。
我的一点想法:时域数据通过fft转成频域,删除特定频率的数据,再ifft转成时域,不就可以删除特定频率的数据了?
这样的话:
低通:就相当于我把高频率的数据删除,只留低频率的数据;
高通:就相当于我把低频率的数据删除,只留高频率的数据;
带通:就相当于我把两侧的数据都删了;
带阻:就相当于我把中间的数据删掉了
补充
直流分量信号的频率是0,高通,带通都会被过滤掉,只有低通可以通过。
更多内容可参考以下系列课程:NO.1 基于matlab中的fdatool进行电生理信号预处理实战演练,以肌电信号为例去除噪声_哔哩哔哩_bilibili