FPGA处理编码信号进行毛刺滤波的方法实现

描述

一、前言

在利用处理编码信号时,一般在较为理想的环境下可以很方便进行计算,判断等。但是由于有时候受到电磁干扰等环境因素,会导致编码信号产生毛刺等,这时候如果不对编码信号进行预处理而是直接进行边缘判断等操作则极容易导致错误,所以需要提前对编码信号进行滤波。

二、滤波算法

电磁干扰

其算法思想也容易理解:如果有电平跳变,则立即进行计数,如果计数值超过设定阈值,则电平跳转有效,否则依然保持原电平不变。另外如果在计数时又发生电平跳转,则重新进行计数。滤波算法跳转图如下:

电磁干扰

电磁干扰

三、代码设计

首先我们需要确定编码信号的毛刺信号大概时间宽度为多少,这样我们才能设置阈值进行滤波。以Altera芯片设计为例,可以利用SigalTapII嵌入式逻辑观测毛刺的时间宽度。

电磁干扰

这样设计代码如下即可实现滤波效果:

module encoder_filter (

  input clk,

  input A,  //原始编码信号A

  output reg A_f, //滤波后的编码信号A_f

  output led,  //观测程序是否烧录成功

  output samp_clk_20us  //SigalTapII中采样时钟

);

pll_ippll_ip_inst (   //调用PLL_IP

.inclk0 ( clk ),

.c0 ( samp_clk_20us )

);

parameter [11:0] Cnt_20us=12'd1000; //20us/20ns=1000;  //毛刺的脉宽不会大于20us

parameter [1:0] S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;

reg [1:0] state;     //当前状态

reg [2:0] A_delay;   //延迟打拍

reg [11:0] count;   //电平跳转计数

reg last_level;     //A的上一个电平状态

reg A_sig_pos;

reg A_sig_neg;

reg [7:0] reset_counter=8'd0;

always@(posedge clk)  //软件不发复位信号,FPGA自己产生,逻辑加载起来后马上自己复位一次。 

begin 

 if (reset_counter != 8'h59 )

  reset_counter <= reset_counter + 8'h1;  

end

reg n_rst;

always@(posedge clk)  //软件不发复位信号,FPGA自己产生,逻辑加载起来后马上自己复位一次。 

begin

 if((reset_counter > 8'd1)&&(reset_counter < 8'd6))

  n_rst <= 1'b0;     

 else  

  n_rst <= 1'b1;

end

assign led=1'b0;

always @(posedge clk or negedge n_rst ) //将外部a信号进行时钟同步

begin

       if(n_rst==1'b0)

            A_delay <=2'b00;

       else

            A_delay <={A_delay[1:0],A};

end

wire A_risingedge=(A_delay[2:1]==2'b01);

wire A_fallingedge=(A_delay[2:1]==2'b10);

always @(posedge clk or negedge n_rst )

begin

    if(n_rst==1'b0)

        begin

            state<= S0;

            count<=12'b0;

            last_level<=1'b0;

            A_sig_neg<=1'b0;

            A_sig_pos<=1'b0;

        end

    else

        case(state)

            S0://空闲状态,判断电平是否变化

                begin

                   if(A_risingedge||A_fallingedge)

                    begin

                       state<= S1;

                       count<=12'b0;

                       last_level<=A_delay[2];

                    end

                end

            S1://计数状态

                begin

                    if(A_delay[2]==A_delay[1])

                        if(count==Cnt_20us)//判断计数是否达到20us

                            begin

                               count<=12'b0;

                               state<= S2;

                            end

                        else

                            count<=count+1'b1;

                    else

                        count<=12'b0;

                end

            S2://判决状态

                begin

                    state<= S3;

                    if(!last_level&&A_delay[1])//确定是由低电平---->高电平

                        begin

                            A_sig_pos<=1'b1;

                            A_sig_neg<=1'b0;

                        end

                    else if(last_level&&!A_delay[1])//确定是由高电平---->低电平

                        begin

                            A_sig_neg<=1'b1;

                            A_sig_pos<=1'b0;

                        end

                    else

                        begin

                            A_sig_neg<=1'b0;

                            A_sig_pos<=1'b0;

                        end

                end

            S3:

                begin

                    state<= S0;

                    count<=12'b0;

                end

            default:

                begin

                    state<= S0;

                    count<=12'b0;

                end

        endcase

end

always @(posedge clk or negedge n_rst )

begin

    if(n_rst==1'b0)

        A_f<=1'b0;

    else if(A_sig_pos==1'b1)

        A_f<=1'b1;

    else if(A_sig_neg==1'b1)

        A_f<=1'b0;

    else

        A_f<=A_f;

end

endmodule

值得注意的是:

1、需要根据实际毛刺Cnt_20us的时间宽度改变阈值

2、在程序使用了软复位,由于未设置按键这种异步复位,就实际程序随板子上电后在主时钟下进行软件同步复位。





审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分