基于Xilinx vivado FFT ip进行信号频谱测量

这篇具有很好参考价值的文章主要介绍了基于Xilinx vivado FFT ip进行信号频谱测量。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文章使用Xilinx的fft ip完成了经过参数化的任意个信号的基频测量,完整代码以及代码解释在文章中给出。如有错误,希望指出。

	SIGNAL_NUM = 2,   //*需要检测的信号个数
    FFT_LEN    = 8192,//*fft运算采样长度
    FFT_WIDTH = 32,   //*fft ip输出数据宽度,实部和虚部位宽为FFT_WIDTH/2
    SAMPLE_RATE = 50, //*ADC采样率,单位Mhz,比如此时为50Mhz
    ADC_WIDTH = 16,   //*ADC数据位宽
    FFT_CONFIG_WIDTH = 8 //*FFT ip的配置信号位宽(未使用)

ps:只使用了fft ip进行频率测量未测量幅度,为防止错误不对幅度测量进行讲解,且幅度测量因为未使用其中获得的幅度是未经处理的原始数据,直接使用应该会出现问题。该代码无法满足所有场景需求,仅起到抛砖引玉的作用。

1.FFT ip的配置

对于FFT ip核的各个配置的介绍在网上已经有很多,故不再详细解释各个配置定义,直接附上我对这个ip的配置。

基于Xilinx vivado FFT ip进行信号频谱测量,算法,fpga开发,傅里叶分析,信号处理
因为使用ADC为20M采样率,需要测到kHz级别的精度,所以这里目标时钟速率为20Mhz,采样点数为8192。这里根据自己需求设定即可。
基于Xilinx vivado FFT ip进行信号频谱测量,算法,fpga开发,傅里叶分析,信号处理

2.FFT ip的使用介绍

FFT ip输入为时域信息,而输出为信号的频域信号,所以需要自己针对频域信号来分析出傅里叶变换后的结果,在FFT ip配置中勾选了XK_INDEX这里后面将配合测试出信号的频率。
对于fft ip直接输出的实部数据和虚部数据是不可以直接进行频率的获取,需要经过一部分处理才可以得到信号的频谱,傅里叶变换的结果是一个复数,包括实部和虚部,信号的频谱是通过计算复数的模得到的。对于信号频谱的计算,按以下公式: abs(fft_P)= sqrt(实部的平方+虚部的平方)
然后根据这个得到的频谱,得到最大值的点,这个点转换后对应的频率,就是信号的频率,比如对于20k的信号,会在x_index指代20k的地方幅度达到最大值,而对于多个信号,比如一个混合信号(20k的正弦波+50k的正弦波),这样就检查这个频谱的两个最大值的位置,就可以得到这两个信号的频率。
得到实部虚部的平方和并使用vivado的cordic ip进行求根获得绝对值:

always @(posedge clk) begin : re2_im2_end
   if(rst) begin
       fft_im_end <= 'd0;
       fft_re_end <= 'd0;
       fft_end    <= 'd0;
   end
   else if(m_axis_data_tvalid) begin
       fft_im_end <= $signed(fft_im[ADC_WIDTH-1:0])*$signed(fft_im[ADC_WIDTH-1:0]);  //*one
       fft_re_end <= $signed(fft_re[ADC_WIDTH-1:0])*$signed(fft_re[ADC_WIDTH-1:0]);
       fft_end    <= fft_im_end + fft_re_end;          //*two
   end
end

cordic_0 u_cordic (
   .aclk                              (clk                       ),// input wire aclk
   .aresetn                           (~rst                      ),// input wire aresetn
   .s_axis_cartesian_tvalid           (cordic_valid_reg[1]       ),// input wire s_axis_cartesian_tvalid
   .s_axis_cartesian_tdata            (fft_end                   ),// input wire [39 : 0] s_axis_cartesian_tdata

   .m_axis_dout_tvalid                (cordic_valid              ),// output wire m_axis_dout_tvalid
   .m_axis_dout_tdata                 (cordic_data               ) // output wire [23 : 0] m_axis_dout_tdata
);

获得检测频率使用的频谱后,传到下面一个自定义的信号处理部分,这部分主要是根据信号的频谱,获取频谱的最大值位置(如果有多个信号就获取多个极值点),之后根据这个位置对应的x_index来计算出信号的频率。

比如对于50Mhz的采样率,8192点的采样深度,这样的话每一个x_index值对应的频率便是50M/8192≈6.1kHz,这样的话FFT运算精度大概就在6kHz
,比如对于X_index值未2的点,该信号的频率就是12kHz。

下面为得到x_index后,根据采样率的参数定义来计算出具体的信号频率部分代码。

always @(posedge clk) begin : result
    if (rst) begin
        for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
            post_fft_freq[i] <= 0;
            post_fft_mag[i] <= 0;
            post_fft_index[i] <= 0;
        end
    end
    else if(max_valid) begin
        for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
            post_fft_freq[i]  <= SAMPLE_RATE*detect_index[i]*(1000>>($clog2(FFT_SIZE)-10)); 
            //乘1000为M转K单位,因为MHz相比于KHz后面多3个0,所以乘1000转换单位,其中FFT_SIZE为采样深度
            //右移的时候-10是为了左移10bit,左移十位为了表示为低10位代表小数,高位代表整数
            post_fft_mag[i]   <= detect_data[i];
            post_fft_index[i] <= detect_index[i];
        end
    end
end
always @(posedge clk) begin
    if(rst) begin
        for(integer i = 0;i < SIGNAL_NUM;i++) begin
            {fft_int[i],fft_real[i]} <= 0;
            fft_mag[i] <= 0;
        end
    end
    else if(post_fft_valid) begin
        for(integer i = 0;i < SIGNAL_NUM;i++) begin
            {fft_int[i],fft_real[i]} <= post_fft_freq[i];//*计算出信号频率后,高六位为整数部分,后面为小数部分
            fft_mag[i] <= post_fft_mag[i];
        end
    end
end

3.代码仿真

为了便于观察出仿真结果,所以使用了两个Xilinx的dds ip分别输出了20kHz的信号和50kHz的信号,然后将这两个信号的输出混合后作为输入,一次性测量两个信号的频率。参数配置如文章顶部的参数,未作更改。
下图为输入的20kHz和50kHz信号,混合信号为这两个信号之和:
基于Xilinx vivado FFT ip进行信号频谱测量,算法,fpga开发,傅里叶分析,信号处理
下图为获得的频谱实部和虚部以及将他们求绝对值后的结果,可以看出求出实部虚部的模之后即为两个尖峰,分别对应两个不同的频率:
基于Xilinx vivado FFT ip进行信号频谱测量,算法,fpga开发,傅里叶分析,信号处理
下图为经过处理后获得的信号频率,第一个为48.8kHz,第二个为18.3kHz,由于上面说明过在50M的采样率下,只有6.1kHz的精度,所以只能不会完全准确在这里,但是在当前精度下,精确测量出了50kHz和20kHz的信号。(要想提高精度需要提高采样深度或者降低采样率)
基于Xilinx vivado FFT ip进行信号频谱测量,算法,fpga开发,傅里叶分析,信号处理

4.完整代码

对于我认为可能比较难理解的地方在上面已做出解释。

module fft_trans 
#(
    SIGNAL_NUM = 2,
    FFT_LEN    = 8192,
    FFT_WIDTH = 32,
    SAMPLE_RATE = 50,
    ADC_WIDTH = 16,
    FFT_CONFIG_WIDTH = 8
)
(
    input  wire clk,//65m clk
    input  wire rst,

    input  wire                       [ADC_WIDTH-1:0]    adc_data ,
    input  wire                                          adc_valid,
    input  wire                                          adc_last ,

    output reg                  [$clog2(FFT_LEN)-1:0]   fft_index[SIGNAL_NUM-1:0],
    output reg                  [ 6:0]  fft_int  [SIGNAL_NUM - 1:0] ,
    output reg                  [ 9:0]  fft_real [SIGNAL_NUM - 1:0] ,
    output reg                  [16:0]  fft_mag  [SIGNAL_NUM - 1:0] ,//!需要根据cordic ip的变化而配置
    output reg                          fft_valid                  ,
    output wire                         fft_slave_ready            ,
    output wire                             freq_valid             ,
    output wire        [$clog2(FFT_LEN)-1:0]freq_index             ,
    output wire        [  16:0]             freq_data                  
);
// region:************parameter************
localparam FFT_SECTION = FFT_WIDTH/2;
// endregion:parameter

// region:************logic define************
//*fft signal
wire                   [$clog2(FFT_LEN)-1:0]x_index                ;
wire              [FFT_CONFIG_WIDTH-1:0]s_axis_config_tdata  = 'd1 ;
wire                                   s_axis_config_tvalid  = 1'b1;
wire                                    s_axis_config_tready       ;
wire                   [FFT_SECTION-1:0]fft_im,fft_re              ;
wire                                    m_axis_data_tvalid         ;
wire                                    m_axis_data_tlast          ;
//*fft end
reg                    [ADC_WIDTH*2-1:0]fft_im_end,fft_re_end      ;
reg                    [ADC_WIDTH*2:0]  fft_end                    ;
reg                                     cordic_valid_reg [1:0]     ;

reg                                     sync_index_en [17:0]       ;
//*detect signal
wire                                    post_fft_valid             ;
wire                   [16:0]           post_fft_freq  [SIGNAL_NUM - 1:0];
wire                   [16:0]           post_fft_mag   [SIGNAL_NUM - 1:0];
wire            [$clog2(FFT_LEN)-1:0] post_fft_index [SIGNAL_NUM - 1:0]  ;

wire                                    cordic_valid               ;
wire                   [  16:0]         cordic_data                ;
wire                   [$clog2(FFT_LEN)-1:0]x_index_sync               ;
// endregion:logic define
// region:************assign************
assign freq_data = cordic_data;   //*freq_data
assign freq_index = x_index_sync;
assign freq_valid = cordic_valid;
assign fft_index[0] =( post_fft_index[0]>post_fft_index[1]) ? post_fft_index[0] : post_fft_index[1];
assign fft_index[1] = (post_fft_index[1]<post_fft_index[0]) ? post_fft_index[1] : post_fft_index[0];
// endregion:assign
always @(posedge clk) begin : re2_im2_end
    if(rst) begin
        fft_im_end <= 'd0;
        fft_re_end <= 'd0;
        fft_end    <= 'd0;
    end
    else if(m_axis_data_tvalid) begin
        fft_im_end <= $signed(fft_im[ADC_WIDTH-1:0])*$signed(fft_im[ADC_WIDTH-1:0]);  //*one
        fft_re_end <= $signed(fft_re[ADC_WIDTH-1:0])*$signed(fft_re[ADC_WIDTH-1:0]);
        fft_end    <= fft_im_end + fft_re_end;          //*two
    end
end
always @(posedge clk) begin:cordic_valid_generate
    if(rst) begin
        for(integer i = 0;i < 2;i++) begin
            cordic_valid_reg[i] <= 'd0;
        end
    end
    else begin
        cordic_valid_reg[1] <= cordic_valid_reg[0];
        cordic_valid_reg[0] <= m_axis_data_tvalid;
    end
end
always @(posedge clk) begin:sync_index
    if(rst) begin
        for(integer i = 0;i < 18;i++) begin
            sync_index_en[i] <= 'd0;
        end
    end
    else begin
        for(integer i = 0;i < 18;i++) begin
            if (i== 0) begin
                sync_index_en[i] <= m_axis_data_tvalid;
            end
            else begin
                sync_index_en[i] <= sync_index_en[i-1];
            end
        end
    end
end
//*out signals
always @(posedge clk) begin
    if(rst) begin
        for(integer i = 0;i < SIGNAL_NUM;i++) begin
            {fft_int[i],fft_real[i]} <= 0;
            fft_mag[i] <= 0;
        end
    end
    else if(post_fft_valid) begin
        for(integer i = 0;i < SIGNAL_NUM;i++) begin
            {fft_int[i],fft_real[i]} <= post_fft_freq[i];
            fft_mag[i] <= post_fft_mag[i];
        end
    end
end
always @(posedge clk) begin
    if(rst) begin
        fft_valid <= 1'b0;
    end
    else begin
        fft_valid <= post_fft_valid;
    end
end


xfft_0 u_xfft_0(
    .aclk                              (clk                       ),
    .aresetn                           (~rst                      ),
    //*fft配置信号
    .s_axis_config_tdata               (s_axis_config_tdata       ),
    .s_axis_config_tvalid              (s_axis_config_tvalid      ),
    .s_axis_config_tready              (s_axis_config_tready      ),
    //*前级adc传入数据
    .s_axis_data_tdata                 ({{{FFT_WIDTH-ADC_WIDTH}{1'b0}},adc_data}),
    .s_axis_data_tvalid                (adc_valid                 ),
    .s_axis_data_tready                (fft_slave_ready           ),
    .s_axis_data_tlast                 (                  ),
    //*out channel
    .m_axis_data_tdata                 ({fft_im,fft_re}           ),
    .m_axis_data_tuser                 (x_index                   ),
    .m_axis_data_tvalid                (m_axis_data_tvalid        ),
    .m_axis_data_tlast                 (m_axis_data_tlast         ),
    //*status channel
    .m_axis_status_tdata               (                          ),
    .m_axis_status_tvalid              (                          ),
    //*event channel
    .event_frame_started               (                          ),
    .event_tlast_unexpected            (                          ),
    .event_tlast_missing               (                          ),
    .event_data_in_channel_halt        (                          ) 
);
//*17 latency
cordic_0 u_cordic (
    .aclk                              (clk                       ),// input wire aclk
    .aresetn                           (~rst                      ),// input wire aresetn
    .s_axis_cartesian_tvalid           (cordic_valid_reg[1]       ),// input wire s_axis_cartesian_tvalid
    .s_axis_cartesian_tdata            (fft_end                   ),// input wire [39 : 0] s_axis_cartesian_tdata

    .m_axis_dout_tvalid                (cordic_valid              ),// output wire m_axis_dout_tvalid
    .m_axis_dout_tdata                 (cordic_data               ) // output wire [23 : 0] m_axis_dout_tdata
);
fifo_generator_0 u_fifo_generator_0(
    .clk                               (clk                       ),
    .srst                              (rst                       ),
    .din                               (x_index                   ),
    .wr_en                             (m_axis_data_tvalid        ),
    .rd_en                             (sync_index_en[17]         ),//!根据cordic ip的变化而配置
    .dout                              (x_index_sync              ),
    .full                              (                          ),
    .empty                             (                          ) 
);

signal_detect
#(
    .FFT_SIZE                          (FFT_LEN                   ),
    .FFT_SIGNAL_NUM                    (SIGNAL_NUM                ),
    .SAMPLE_RATE                       (SAMPLE_RATE               ) 
)
u_signal_detect(
    .clk                               (clk                       ),
    .rst                               (rst                       ),
    .fft_data                          (cordic_data               ),
    .fft_index                         (x_index_sync              ),
    .fft_valid                         (cordic_valid              ),

    .post_fft_index                    (post_fft_index            ),
    .post_fft_valid                    (post_fft_valid            ),
    .post_fft_freq                     (post_fft_freq             ),
    .post_fft_mag                      (post_fft_mag              ) 
);

endmodule //fft_trans


在例化中除了signal_detect均为Xilinx的 ip,其中cordic_0 实现了求根,xfft_0 为fft ip,fifo_generator_0 为一个异步FIFO用于数据对齐,下面给出signal_detect代码

module signal_detect 
#(
    parameter FFT_SIZE = 4096,
    parameter FFT_SIGNAL_NUM = 1,
    parameter integer  SAMPLE_RATE = 'd100 //100MHz,用来计算频率
)
(
    input  wire  clk,
    input  wire  rst,

    input  wire  [16:0] fft_data,//!输入的cordic数据
    input  wire  [$clog2(FFT_SIZE)-1:0] fft_index,
    input  wire        fft_valid,

    output reg  [$clog2(FFT_SIZE)-1:0] post_fft_index [FFT_SIGNAL_NUM],
    output reg  post_fft_valid,
    output reg  [16:0] post_fft_freq [FFT_SIGNAL_NUM-1:0],     //*高16bit为整数,低10bit为小数
    output reg  [16:0] post_fft_mag  [FFT_SIGNAL_NUM-1:0]      //*低位最低,高位最高
);
localparam DETECT_RANGE = FFT_SIZE/2;

reg [$clog2(FFT_SIZE)-1:0] detect_index [FFT_SIGNAL_NUM-1:0]; 
//wire [$clog2(FFT_SIGNAL_NUM):0] detect_cnt;
reg [16:0] detect_data [FFT_SIGNAL_NUM-1:0];
reg [$clog2(DETECT_RANGE):0] cnt;
reg [4:0] state;
reg max_valid;

//*1 state design
always @(posedge clk) begin
    if (rst) begin
        cnt <= {$clog2(DETECT_RANGE){1'b0}};
        state <= 0;
    end
    else begin
        case (state)
            0:  if (fft_valid && (fft_index == 0)) begin//*one clk delay
                    cnt <= 0;
                    state <= 1;
                end
                else begin
                    state <= 0;
                end
            1:  if (fft_valid && (cnt < DETECT_RANGE)) begin
                    cnt <= cnt + 1;
                    state <= 1;
                end
                else if(cnt == DETECT_RANGE)begin
                    state <= 2;
                    cnt <= 0;
                end
            2:  begin
                state <= 0;
                cnt <= 0;
            end
            default: begin
                state <= 0;
                cnt <= 0;
            end
        endcase
    end
end
//*2 output design
generate if(FFT_SIGNAL_NUM == 1) begin
    always @(posedge clk) begin
    if (rst) begin
            detect_data[0] <= 0;
            detect_index[0] <= 0;
            max_valid <= 0;
    end
    else begin
        case (state)
            0:  begin
                    detect_data[0] <= 0;
                    detect_index[0] <= 0;
                    max_valid <= 0;
                end
            1: begin //*只捕获一个信号时
                    if (cnt == DETECT_RANGE-1) begin
                        max_valid <= 1'b1;
                    end
                    else begin
                        max_valid <= 0;
                    end

                    if (fft_data > detect_data[0]) begin
                        detect_data[0] <= fft_data;
                        detect_index[0] <= cnt+1;
                    end
                    
                end
            2:  begin
                max_valid <= 0;
                detect_data[0] <= 0;
                detect_index[0] <= 0;
            end
            default: begin
                max_valid <= 0;
                detect_data[0] <= 0;
                detect_index[0] <= 0;
            end
        endcase
    end
end
end
else begin //*捕获多个信号时
    always @(posedge clk) begin
    if (rst) begin
        max_valid <= 0;
        for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
            detect_data[i] <= 0;
            detect_index[i] <= 0;
        end
    end
    else begin
        case (state)
            0:  begin
                    for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
                        detect_data[i] <= 0;
                        detect_index[i] <= 0;
                    end
                    max_valid <= 0;
                end
            1: begin
                    if( fft_data > detect_data[0] && detect_data[0] <= detect_data[1]) begin
                        detect_data[0] <= fft_data;
                        detect_index[0] <= cnt + 'd1;
                    end
                    else if(fft_data > detect_data[1] && detect_data[1] <= detect_data[0]) begin
                        detect_data[1] <= fft_data;
                        detect_index[1] <= cnt + 'd1;
                    end
                    if (cnt == DETECT_RANGE-1) begin
                        max_valid <= 1'b1;
                    end
                    else begin
                        max_valid <= 0;
                    end
                end
            2:  begin
                max_valid <= 0;
                for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
                    detect_data[i] <= 0;
                    detect_index[i] <= 0;
                end
            end
            default: begin
                max_valid <= 0;
                for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
                    detect_data[i] <= 0;
                    detect_index[i] <= 0;
                end
            end
        endcase
    end
end
end
endgenerate
//*output
always @(posedge clk) begin : result
    if (rst) begin
        for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
            post_fft_freq[i] <= 0;
            post_fft_mag[i] <= 0;
            post_fft_index[i] <= 0;
        end
    end
    else if(max_valid) begin
        for(integer i = 0;i < FFT_SIGNAL_NUM;i++) begin
            post_fft_freq[i]  <= SAMPLE_RATE*detect_index[i]*(1000>>($clog2(FFT_SIZE)-10)); //<<10/1024 //*1000为M转K单位
            post_fft_mag[i]   <= detect_data[i];
            post_fft_index[i] <= detect_index[i];
        end
    end
end
always @(posedge clk) begin : valid
    if (rst) begin
        post_fft_valid <= 0;
    end
    else if(max_valid) begin
        post_fft_valid <= 1;
    end
    else begin
        post_fft_valid <= 0;
    end
end

endmodule //signal_detect

如有疑问或者文章中有错误,请在评论区指出💕。

参考链接:利用Vivado的 FFT IP 核估计信号的幅度和频率
文章来源地址https://www.toymoban.com/news/detail-809501.html

到了这里,关于基于Xilinx vivado FFT ip进行信号频谱测量的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Matlab中利用FFT实现信号频谱搬移

    在fft的理论中,fft的频移特性表示为: 也就是说,要想对信号f(t)实现频域的频谱搬移,只要在时域乘以一个矩阵,即可实现频谱的搬移。常用的振幅调制和解调就是如此,频谱搬移前后对比如下: 其特点就是仅频谱搬移,不产生新的频谱分量。利用欧拉公式: e^(ix)可以

    2024年01月20日
    浏览(55)
  • Python中利用FFT(快速傅里叶变换)进行频谱分析

    本文将从实例的角度出发讲解fft函数的基本使用,不包含复杂的理论推导。 要对一个信号进行频谱分析,首先需要知道几个基本条件。 采样频率fs 信号长度N(信号的点数) 采样频率fs: 根据采样定理可知,采样频率应当大于等于被测信号里最高频率的2倍,才能保证不失真

    2024年01月17日
    浏览(52)
  • Simulink HDL Coder FPGA初级开发实践(五)FFT以及CORDIC算法进行信号相位校正

    前言: 本栏目除特别说明以外,均采用的黑金AX7103开发板,该开发板时钟频率为200M,并且是双端时钟,因此在每个项目中都有一段原语将双端时钟变成200MHz的单端时钟。文章仅作为学习记录,如有不足请在评论区指出,博主不会对各位的问题作出解答,请谅解。博主深知网

    2024年02月06日
    浏览(50)
  • 基于FPGA的信号处理算法,FFT法相差检测verilog实现

    基于FPGA的信号处理算法,FFT法相差检测verilog实现 。 1.硬件平台:altera芯片 2.软件平台:Quartusii 13.1 Verilog 3.实现功能:检测两路正弦波的相位差 基于FPGA的信号处理算法,FFT法相差检测verilog实现 引言 在现代通信系统中,信号处理算法在实时性和精度方面面临着巨大的挑战。

    2024年04月16日
    浏览(60)
  • Xilinx 的FFT IP核使用方法(配置为FFT 、IFFT两种模式)

    Configuration 配置通道数和FFT长度 时钟频率以及数据吞吐速率 FFT的结构选择 Srteaming , 可以对数据进行流水处理 Radix-4 , 基4的迭代算法,使用资源比流水线结构多,但是转换时间长 Radix-2, Radix-2 lite 都为基2的迭代算法,Radix-2 lite的资源占用更少,但是转换时间也更长。 Run Time

    2024年02月04日
    浏览(41)
  • 基于vivado DDS ip核的DDS信号发生器(可调频调相)

    基于Vivado DDS ip核的DDS信号发生器: 在Vivado软件中调出DDS ip核进行设置,很多参数可以参考xilinx官方手册,比较重要的是System Clock系统时钟和Phase Widh相位宽度的设置,这是最终得到波形的频率和相位所需要的基础参数,在这里我分别设置为50Mhz和16bit。 在implementation页面设置频

    2024年02月12日
    浏览(38)
  • 基于stm32f407的示波器+FFT频谱分析

    1 设计思路 2 DMA传输ADC采样值 使用DMA直接将ADC-DR中的数据传输到ADC数据缓存区,节省cpu资源,高速AD采集,代码如下: 3 ADC定时器触发(可修改ADC采样率) 为了实现ADC采样率可调,我将AD的出发方式设置为定时器触发,使用TIM3来触发adc采集,首先初始化定时器,先预设几种初

    2024年02月05日
    浏览(54)
  • Vivado_FFT IP核 使用详解

    本文介绍Vivado中Fast Fourier Transform V9.1的使用方法。 参考资料:pg109 FFT是用于计算样本大小为2的正整数幂的离散傅里叶变换(DFT)的高效计算方法。序列的DFT定义为 X ( k ) = ∑ n = 0 N − 1 x ( n ) e − j n k 2 π / N    k = 0 , … N − 1 X(k) = sum_{n=0}^{N-1}x(n)e^{-jnk2pi /N} k = 0,dots N-1

    2023年04月15日
    浏览(48)
  • Vivado中的FFT IP核使用(含代码)

    本文介绍了Vidado中FFT IP核的使用,具体内容为:调用IP核配置界面介绍IP核端口介绍MATLAB生成测试数据测试verilogHDLTestBench仿真结果验证FFT运算。 该IP核对应手册pg109_xfft.pdf,首先按照图片找到IP核: 本小节主要介绍Fast Fourier Transform9.1这个IP核配置界面的一些选项: 第1页:Con

    2023年04月13日
    浏览(43)
  • 基于STM32&FFT(快速傅里叶变换)音频频谱显示功能实现

    + v hezkz17进数字音频系统研究开发交流答疑 一实验效果   二 设计过程 要用C语言实现STM32频谱显示功能,可以按照以下步骤进行操作: 1 确保已经安装好了适当的开发环境和工具链,例如Keil MDK或者GCC工具链。 2 创建一个新的STM32项目,并选择适合的MCU型号。 3 配置GPIO引脚用

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包