数字滤波器是指通过一定的数据逻辑构成的可以滤除输入信号中的特定的噪声的算法,这里所指的数字滤波器主要包括平均值滤波、FIR滤波、CIC滤波等,在之后的实验中,我们将介绍不同数字滤波器的原理,通过MATLAB和FPGA分别实现不同数字滤波器,为之后工程中的应用打下基础。
2.1 滑动平均滤波原理
若输入采样点的个数为N个,假设采用8倍的滑动平均滤波,其滑动平均滤波的原理如下:
2.2 MATLAB实现
%%N倍滑动滤波算法 clear; clc; %数据输入 fileID = fopen('gnd_ch3.txt'); data = textscan(fileID,'%s'); data = data{1,1}; k = 1; for i = 1 : length(data)-11 if strcmp(data(i),'61') && strcmp(data(i+1),'64') Ain(k) = (((hex2dec(strcat(data(i+5),data(i+6),data(i+7)))*20/2^24)-10)*1e6)/50; k = k + 1; end end %变量定义 N = 8;%滑动滤波倍数 M = length(Ain);%输入数据个数 INIT_NUM = 0;%初始数据和 INIT_AVE = 0;%初始数据均值 NUM = 0;%数据和 AVE = 0;%数据均值 Aout = zeros(1,M);%数据输出 %初始均值 %求初始和 for i = 1:1:N-1 INIT_NUM = INIT_NUM + Ain(1,i); end %求初始均值 INIT_AVE = INIT_NUM / N; Aout(1,N) = INIT_AVE; AVE = INIT_AVE; %滑动均值 for i = 1:1:M-N NUM = (AVE * (N-1)) + Ain(1,i + N); AVE = NUM / N; Aout(1,i + N) = AVE; end figure plot(Ain(N+100:M)); hold on; plot(Aout(N+100:M));
绘图结果:
8倍滑动滤波
16倍滑动滤波
64倍滑动滤波
2.3 FPGA实现
1. 代码实现参考Move_Mean_filter工程
`timescale 1ns / 1ps /****************************************************************************************************** **Author :CKM **E-mail :15594951527@163.com **Times :2022/4/10 **Editor :vs_code/notepad++ **EDATools :vivado 2017.4 **Module_name :move_mean_filter **Functions :实现输入数据DATA_NUM位,MUL_NUM倍滑动滤波算法 *******************************************************************************************************/ module move_mean_filter#( parameter DATA_NUM = 24 ,//数据位宽 parameter MUL_NUM = 8 ,//滑动倍数 parameter MOV_NUM = 3 )( input clk_i , input rst_n , input [DATA_NUM-1 : 0] Ain , output reg [DATA_NUM-1 : 0] Aout ); /*---------------------------------------------常量定义------------------------------------------------*/ localparam IDLE = 6'b000_001 ;//空闲状态 localparam INIT_NUM = 6'b000_010 ;//初始化赋值状态 localparam INIT_MEAN = 6'b000_100 ;//初始化赋值缓冲状态 localparam NUM = 6'b001_000 ;//滑动滤波状态 localparam NUM_BUFF = 6'b010_000 ;//滑动滤波缓冲状态 localparam MEAN = 6'b100_000 ;//等待状态 /*---------------------------------------------变量定义------------------------------------------------*/ reg [ 5 : 0] current_state ;//现态 reg [ 5 : 0] next_state ;//次态 reg [DATA_NUM - 1 : 0] Ain_temp1 ;//输入数据缓冲1 reg [DATA_NUM - 1 : 0] Ain_temp2 ;//输入数据缓冲2 reg [31 : 0] init_cnt ;//初始化计数器 reg [ 7 : 0] buffer_cnt ;//初始化计数器 reg [47 : 0] init_num ;//初始化数据和 reg [47 : 0] num ;//数据和 reg [24 : 0] A ; reg [ 7 : 0] B ; reg [24 : 0] C ; wire [47 : 0] P ; wire [47 : 0] PCOUT ; /*---------------------------------------------程序开始------------------------------------------------*/ //输入数据缓冲 always @(posedge clk_i or negedge rst_n) begin if(!rst_n)begin Ain_temp1 <= 0; Ain_temp2 <= 0; end else begin Ain_temp1 <= Ain; Ain_temp2 <= Ain_temp1; end end //滑动滤波算法 //1.状态确定 always @(posedge clk_i or negedge rst_n) begin if(!rst_n)begin current_state <= 0; end else begin current_state <= next_state; end end //2.状态切换 always @(*)begin if(!rst_n)begin next_state <= IDLE; end else begin case(current_state) IDLE :begin if(Ain_temp2 != Ain_temp1)begin next_state <= INIT_NUM; end else begin next_state <= IDLE; end end INIT_NUM :begin if(init_cnt == MUL_NUM)begin next_state <= INIT_MEAN; end else begin next_state <= INIT_NUM; end end INIT_MEAN:begin next_state <= NUM; end NUM :begin if(Ain_temp2 != Ain_temp1)begin next_state <= NUM_BUFF; end else begin next_state <= NUM; end end NUM_BUFF:begin next_state <= MEAN; end MEAN :begin next_state <= NUM; end default :begin end endcase end end //3.各状态逻辑 always @(posedge clk_i or negedge rst_n) begin if(!rst_n)begin init_cnt <= 0; buffer_cnt <= 0; init_num <= 0; num <= 0; Aout <= 0; A <= 0; B <= 0; C <= 0; end else begin case(next_state) IDLE :begin init_cnt <= 0; buffer_cnt <= 0; if(Ain_temp2 != Ain_temp1)begin init_num <= Ain; end else begin init_num <= init_num; end num <= 0; Aout <= Ain; A <= 0; B <= 0; C <= 0; end INIT_NUM :begin if(Ain_temp2 != Ain_temp1)begin init_cnt <= init_cnt + 1; init_num <= init_num + Ain; end else begin init_cnt <= init_cnt; init_num <= init_num; end buffer_cnt <= 0; num <= 0; Aout <= Aout; A <= 0; B <= 0; C <= 0; end INIT_MEAN:begin init_cnt <= init_cnt; buffer_cnt <= 0; init_num <= init_num; num <= 0; if(init_cnt == MUL_NUM)begin Aout <= init_num >> MOV_NUM; end else begin Aout <= Aout; end A <= 0; B <= 0; C <= 0; end NUM :begin init_cnt <= init_cnt; buffer_cnt <= 0; init_num <= init_num; num <= num; Aout <= Aout; A <= Aout; B <= MUL_NUM - 1; C <= Ain; end NUM_BUFF :begin init_cnt <= init_cnt; buffer_cnt <= buffer_cnt + 1; init_num <= init_num; num <= P; Aout <= Aout; A <= A; B <= B; C <= C; end MEAN :begin init_cnt <= init_cnt; buffer_cnt <= 0; init_num <= init_num; num <= num; Aout<= num >> MOV_NUM; A <= A; B <= B; C <= C; end default :begin end endcase end end //乘加器例化 xbip_multadd_0 your_instance_name ( .CLK (clk_i ) ,// input wire CLK .CE (1'b1 ) ,// input wire CE .SCLR (1'b0 ) ,// input wire SCLR .A (A ) ,// input wire [23 : 0] A .B (B ) ,// input wire [7 : 0] B .C (C ) ,// input wire [23 : 0] C .SUBTRACT (1'b0 ) ,// input wire SUBTRACT .P (P ) ,// output wire [47 : 0] P .PCOUT (PCOUT ) // output wire [47 : 0] PCOUT ); endmodule
2. 功能仿真结果:
(1)4倍滑动滤波
(2)8倍滑动滤波
(3)16倍滑动滤波
3. 将该滑动滤波模块应用于AD7734数据采集,AD7734采集到的数据进行滑动平均滤波,测试该算法与理论分析是否一致
(1)64倍滑动滤波效果
在线抓取信号
将串口接收到的数据利用matlab画图得
(2)16倍滑动滤波效果
在线抓取信号
将串口接收到的数据利用matlab画图得
(3)8倍滑动滤波效果
在线抓取信号
将串口接收到的数据利用matlab画图得
通过以上的实验可以看出,虽然滑动平均滤波的算法十分简单,但是以上的实验可以充分的理解了该算法的内涵与实现。滑动滤波倍数设置的越小,滤波效果越不好,但反应信号变化的实时性却很好;滑动滤波倍数设置的越大,滤波效果越很好,但反应信号变化的实时性变差。因此在实际应用中,如要用到该算法,需要权衡滤波效果和信号实时性这两个对立的性能,从而选择最优的滑动滤波倍数。
联系客服