整体功能:实现正弦波(方波)的频率和周期测量,并测量方波信号占空比
测量方法:
1.频率测量:使用等精度测量方法:等精度测量,由于设置的门控时间是5000个待测的信号的周期,所以当输入信号频率较低,会导致测量的时间过长。
2.占空比测量:这里借鉴了基于FPGA的简易频率计设计这篇文章的测量方法。通过门控时间内,对PLL倍频的200MHz时钟clk_200计数,读出待测信号连续的四个边沿的计数值,通过计算可以得到高电平的时间和待测信号的周期。然后计算可得到占空比。此外在输入频率较低的情况,上述测量得到的周期的倒数,可以作为低频信号的频率测量值。
整形电路
将待测信号整形变成FPGA可以识别到的TTL电平。具体实现由硬件实现的小伙伴完成,也没太操心@_@。
FPGA测频模块
//频率测量(等精度)
module freq
#(parameter CLK_FS = 26'd50_000_000,// 基准时钟频率
parameter MAX = 10'd32) // 定义数据位宽
( //system clock
input clk_fs , // 时钟信号
input rst_n , // 复位信号
//cymometer interface
input clk_fx , // 待测信号
input gate, // 门控信号(与待测时钟同步)
input gate_fs, // 与基准时钟同步的门控信号
input neg_gate_fx,//
input neg_gate_fs,//
output reg [32-1:0] fs_cnt , //门控时间内基准时钟信号的个数
output reg [32-1:0] fx_cnt , // 门控时间内待测信号的个数
output reg [32-1:0] data_fx_temp // 待测信号的频率值
);
reg [32-1:0] fs_cnt_temp ; // fs_cnt 计数
reg [32-1:0] fx_cnt_temp ; // fx_cnt 计数
//门控时间内待测信号的计数,设置的为5000个,这里重新计数,只是用于检验信号是否正确
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) begin
fx_cnt_temp <= 32'd0;
fx_cnt <= 32'd0;
end
else if(gate)begin
fx_cnt_temp <= fx_cnt_temp + 1'b1;
end
else if(neg_gate_fx) begin
fx_cnt_temp <= 32'd0;
fx_cnt <= fx_cnt_temp;
end
end
//门控时间内基准时钟的计数
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) begin
fs_cnt_temp <= 32'd0;
fs_cnt <= 32'd0;
end
else if(gate_fs)
begin
fs_cnt_temp <= fs_cnt_temp + 1'b1;
end
else if(neg_gate_fs) begin
fs_cnt_temp <= 32'd0;
fs_cnt <= fs_cnt_temp;
data_fx_temp<=fs_cnt;
end
end
//计算待测信号的频率值
//always @(posedge clk_fs or negedge rst_n) begin
// if(!rst_n) begin
// data_fx_temp <= 64'd0;
// end
// else if(gate_fs == 1'b0)
// data_fx_temp <=CLK_FS*fx_cnt/fs_cnt;
//end
endmodule
//频率、占空比测量模块(测周法)
module duty_ratio(
clk,
rst_n,
gate,sig,
fre_count,
duty_count
);
input clk;
input rst_n;
input gate;
input sig;
output [31:0] fre_count;
output [31:0] duty_count;
wire clk_200;
wire locked;
clk_200 pll_module(
.areset(!rst_n),
.inclk0(clk),
.c0(clk_200)
);
reg [31:0] counter; //32位计数器
always @(posedge clk_200 or negedge rst_n)
begin
if(!rst_n)
begin
counter <= 1'b0;
end
else
begin
if(gate == 1'b1)
begin
counter <= counter + 1'b1;
end
else
begin
counter <= 32'b0;
end
end
end
reg [1:0] en_sig_edge;
reg [1:0] en_sig_edge_n;
always @(posedge clk_200 or negedge rst_n)
begin
if(!rst_n)
begin
en_sig_edge <= 2'b0;
end
else
begin
en_sig_edge <= en_sig_edge_n;
end
end
always @(*)
begin
if(!rst_n)
begin
en_sig_edge_n = 2'b0;
end
else
begin
en_sig_edge_n = {en_sig_edge[0],sig};
end
end
wire edge_turn;
assign edge_turn = en_sig_edge[0] ^ en_sig_edge[1]; //检测双边沿
reg [31:0] time_record[3:0];
always @(posedge clk_200 or negedge rst_n)
begin
if(!rst_n)
begin
time_record[0] <= 32'b0;
time_record[1] <= 32'b0;
time_record[2] <= 32'b0;
time_record[3] <= 32'b0;
end
else if(gate == 1'b0 )
begin
time_record[0] <= 32'b0;
time_record[1] <= 32'b0;
time_record[2] <= 32'b0;
time_record[3] <= 32'b0;
end
else
begin
if(edge_turn)
begin
time_record[0] <= counter;
time_record[1] <= time_record[0];
time_record[2] <= time_record[1];
time_record[3] <= time_record[2];
end
else
begin
time_record[0] <= time_record[0];
time_record[1] <= time_record[1];
time_record[2] <= time_record[2];
time_record[3] <= time_record[3];
end
end
end
reg [31:0] pipe_add_1;
reg [31:0] pipe_add_2;
reg [31:0] pipe_result;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
pipe_add_1 <= 32'b0;
pipe_add_2 <= 32'b0;
end
else
begin
pipe_add_1 <= time_record[0] + time_record[1];
pipe_add_2 <= time_record[2] + time_record[3];
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
pipe_result <= 32'b0 ;
end
else
begin
pipe_result <= pipe_add_1 - pipe_add_2;
end
end
reg [31:0] duty_count_reg;
always @(posedge sig or negedge rst_n)
begin
if(!rst_n)
begin
duty_count_reg <= 32'b0 ;
end
else
begin
if(gate == 1'b1)
duty_count_reg <= time_record[0] - time_record[1];
else
duty_count_reg <= 32'b0;
end
end
assign duty_count = duty_count_reg;
assign fre_count = pipe_result;
endmodule
由上述测频模块产生三组测量值,高电平时间计数值duty_count,2个待测信号周期计数值fre_count,门控时间内基准时钟的计数值data_fx。然后通过SPI 接口将这3组数据发给单片机进行处理。
MCU模块
通过SPI串口接收FPGA发送的三组数据。
根据公式可以算出
占
空
比
:
d
u
t
y
=
d
u
t
y
c
o
u
n
t
/
f
r
e
c
o
u
n
t
∗
2.0
占空比:duty ={duty_{count}}/{fre_{count}} *2.0
占空比:duty=dutycount/frecount∗2.0
频
率
1
:
f
r
e
q
1
=
c
l
k
200
M
H
z
∗
2.0
/
f
r
e
c
o
u
n
t
频率1:freq 1 =clk_{200MHz}*2.0/{fre_{count}}
频率1:freq1=clk200MHz∗2.0/frecount
频
率
2
:
f
r
e
q
2
=
c
l
k
50
M
H
z
∗
5000
/
d
a
t
a
f
x
频率2:freq 2 =clk_{50MHz}*5000/{data_{fx}}
频率2:freq2=clk50MHz∗5000/datafx
当测量频率较低时,采用频率1freq1作为输出结果
但测量频率较高时,采用频率2freq2作为输出结果
最后通过LCD频显示。
实际测量
输入信号频率(Hz) / 占空比(%) | 测量频率 (单位:Hz) / 占空比(%) |
---|---|
1.234000 / 80 | 1.234014 /79.996 |
1000 /64 | 1000.10009/64.144 |
10000000/40 | 10000400.967295 /40.0 |
实测图片:
如有错误或者言语不恰当的地方可在评论区指出,谢谢!
实验源码
https://download.csdn.net/download/Cauchy_Z/20555477?spm=1001.2014.3001.5501