数字滤波算法(一)——滑动平均滤波算法

本文介绍了数字滤波器的基本类型,包括平均值滤波、FIR滤波和CIC滤波,并详细讲解了滑动平均滤波的原理和MATLAB实现。通过MATLAB代码展示了不同倍数滑动平均滤波的效果。此外,还提供了FPGA实现滑动平均滤波的Verilog代码,并给出了功能仿真结果,对比了不同滤波倍数对信号滤波效果和实时性的影响。最后,讨论了在实际应用中如何权衡滤波效果和信号实时性。
摘要由CSDN通过智能技术生成

一、数字滤波器简介

数字滤波器是指通过一定的数据逻辑构成的可以滤除输入信号中的特定的噪声的算法,这里所指的数字滤波器主要包括平均值滤波、FIR滤波、CIC滤波等,在之后的实验中,我们将介绍不同数字滤波器的原理,通过MATLAB和FPGA分别实现不同数字滤波器,为之后工程中的应用打下基础。

二、滑动平均滤波

2.1 滑动平均滤波原理

若输入采样点的个数为N个,假设采用8倍的滑动平均滤波,其滑动平均滤波的原理如下:

  1. 滤波器输出的第一个数据在8个采样周期之后,即首先对输入的8个数据进行平均,平均结果为x_0=(x0+x1+…+x7)/8
  2. 8个周期之后即可以实现数据的滑动输入,并且滤波器输出为x_i=((7*x_i-1)+xi+7)/8 , i=1,2……

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画图得

       通过以上的实验可以看出,虽然滑动平均滤波的算法十分简单,但是以上的实验可以充分的理解了该算法的内涵与实现。滑动滤波倍数设置的越小,滤波效果越不好,但反应信号变化的实时性却很好;滑动滤波倍数设置的越大,滤波效果越很好,但反应信号变化的实时性变差。因此在实际应用中,如要用到该算法,需要权衡滤波效果和信号实时性这两个对立的性能,从而选择最优的滑动滤波倍数。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值