1、基本原理
FIR滤波器:
FIR滤波器是一种数字滤波器,其名称代表了其特性——有限脉冲响应(Finite Impulse Response)。它的特点是其响应是有限长度的,不会无限延长。FIR滤波器通过一系列加权的输入信号来产生输出信号,其中每个输入信号都有一个对应的加权系数。这些加权系数决定了滤波器的频率响应。
FIR滤波器的冲激响应h(n)只有N个点有值,这N个值称为滤波器的系数。滤波器的输出Y(n)只与当前的输入x(n)和有限个过去的输入x(n-1),X(n-2),…X(n-(N-1))有关,其表达式为:
Y(n)=h(O)X(n)+h(1)X(n-1)+h(2)X(n-2)+h(N-1)x(n-(N-1))
和此表达式对应的实现结构可用图2-1来表示。
2、MATLAB仿真
MATLAB仿真FIR:
% 生成方波信号
Fs = 1000; % 采样频率
T = 1/Fs; % 采样周期
t = 0:T:1-T; % 时间向量
f = 10; % 方波频率
x = square(2*pi*f*t); % 生成方波信号
% 设计FIR滤波器
N = 101; % 滤波器阶数
fc = 20; % 截止频率
b = fir1(N, fc/(Fs/2)); % 设计FIR滤波器
% 输出滤波器系数
disp('FIR滤波器系数:');
disp(b);
% 应用滤波器
y = filter(b, 1, x);
% 绘制结果
subplot(2,1,1);
plot(t, x);
title('Square Wave');
xlabel('Time (s)');
ylabel('Amplitude');
subplot(2,1,2);
plot(t, y);
title('Filtered Wave');
xlabel('Time (s)');
ylabel('Amplitude');
MATLAB仿真IIR:
% 生成方波信号
Fs = 1000; % 采样率
t = 0:1/Fs:1; % 时间向量
f_square = 10; % 方波频率
square_wave = square(2*pi*f_square*t); % 生成方波信号
% 设计IIR滤波器
[b, a] = butter(4, 2*f_square/Fs, 'low');
% 对方波信号进行滤波
filtered_signal = filter(b, a, square_wave);
% 绘制结果
figure;
subplot(2,1,1);
plot(t, square_wave);
title('Square Wave Signal');
xlabel('Time (s)');
ylabel('Amplitude');
subplot(2,1,2);
plot(t, filtered_signal);
title('Filtered Signal (Sinusoidal)');
xlabel('Time (s)');
ylabel('Amplitude');
仿真结果:
求得滤波器系数 :
第二步设计一个FIR滤波器把方波变成正弦波。
3、流程图
首先我们在 RAM区设置两组连续的存储区,一组存放采样数据,-组存放滤波器系数,如图2-2所示。在初始化时,存放采样数据的存储区先清零。系数存储区存放的滤波器的系数在matlab的仿真环境中求得,通过修改截止频率、阻带最小衰减以及窗函数来修正截止频率,以达到最好的滤波效果。
其次,用汇编语言设计一个FIR滤波器把方波变成正弦波。具体流程图如下:
4、汇编实现
fir.asm:
.global _c_int00
.bss x,1024 ;设置未初始化段
.bss y,1024 ;设置未初始化段在flash里面
.sect "coff_tab"
fir_tab: .word -2,-8,-15,-20,-16,6,52,126,229,357,501,649,786,896,969,994,969,896,786,649,501,357,229,126 ,52,6,-16,-20,-15,-8,-2
fir1_tab .usect "fir2_tab",512 ;设置已初始化段
fir1_dat .usect "fir2_dat",512 ;设置已初始化段(滤波的数据)
.text
_c_int00:
MVK .S1 x,A0
MVK .S1 1,A1
MVK .S1 -1,A2
MVK .S2 8,B0
MVKL .S2 0X00000000,B1 ;清零AMR
MVKH .S2 0X00000000,B1
MVC .S2 B1,AMR
NOP 5
LOOP1:
MVK .S2 16,B1 ;取B1作为计数的寄存器
NOP 5
LOOP2:
STW .D1 A1,*A0++
NOP 5
SUB .L2 B1,1,B1
NOP 5
[B1]B LOOP2
NOP 5
MVK .S2 16,B1
NOP 5
LOOP3:
STW .D1 A2,*A0++
NOP 5
SUB .L2 B1,1,B1
NOP 5
[B1]B LOOP3
NOP 5
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP1 ;32个点一个周期(16个点变化一次),共8个周期。
NOP 5
MVK .S1 fir_tab,A3 ;将未初始化段送至内存
MVK .S1 fir1_tab,A4
MVK .S1 fir1_dat,A5
MVK .S2 128,B0
NOP 5
LOOP4: ;填充
LDW .D1 *A3++,A6
NOP 5
STW .D1 A6,*A4++
NOP 5
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP4
NOP 5
MVK .S2 51,B0
NOP 5
LOOP5:
LDW .D1 *A3--,A6
NOP 5
STW .D1 A6,*A4++
NOP 5
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP5
NOP 5
ZERO A0
MVK .S2 27,B0
NOP 5
LOOP6:
STW .D1 A2,*A5++
NOP 5
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP6
NOP 5
MVK .S2 50,B0
NOP 5
LOOP7:
STW .D1 A2,*A4++
NOP 5
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP7
NOP 5
MVK .S1 x,A0 ;填充结束
MVK .S1 y,A1
MVK .S1 fir1_tab,A4
MVK .S1 fir1_dat,A5
MVKL .S2 0X00080005,B1
MVKH .S2 0X00080005,B1 ;循环寻址取A4和A5
MVC .S2 B1,AMR
MVK .S2 256,B0
NOP 5
LOOP8:
LDW .D1 *A0++,A2
NOP 5
STW .D1 A2,*--A5
NOP 5
MVK .S2 128,B1
NOP 5
LOOP: ;循环进行乘累加
LDW .D1 *A4++,A9
NOP 5
LDW .D1 *A5++,A10
NOP 5
MPY .M A9,A10,A11
NOP 5
ADD .L1 A3,A11,A3 ;A3中存放卷积结果(疑问:A3先前是否清零)
NOP 5
SUB .L2 B1,1,B1
NOP 5
[B1]B LOOP ;LOOP1
NOP 5
STW .D1 A3,*A1++ ;将乘累加的值放在y里面取
SUB .L2 B0,1,B0
NOP 5
[B0]B LOOP8
NOP 5
.end
fir.cmd
fir.obj
-o fir.out
MEMORY//给存储器分成两部分
{
PAGE 0: ROM: ORIGIN=00000010H, LENGTH=1000H
ROM1: ORIGIN=00002300H, LENGTH=500H
PAGE 1: DARAM: ORIGIN=00003000H, LENGTH=2000H
RAM1: ORIGIN=00006000H, LENGTH=200H
RAM2: ORIGIN=00007000H, LENGTH=1000H
}
SECTIONS//将不同的区分配到不同的段里
{
.text :>ROM PAGE 0
.bss :>DARAM PAGE 1
coff_tab :>ROM1 PAGE 0
fir2_tab :>RAM2 PAGE 1
fir2_dat :>RAM2 PAGE 1
}
5、运行结果
寄存器中x的值:
寄存器中y的值:
方波仿真图:
正弦波仿真图