IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 脉冲参数测量仪的设计与实现(2)频率计测频 -> 正文阅读

[嵌入式]脉冲参数测量仪的设计与实现(2)频率计测频

测频在fpga中是非常常见也是非常经典的问题,原因在于利用EDA技术可以测出毫赫兹到百兆赫兹范围的频率。

通常常见的测频方法有:直接测,等周期,等精度。

直接测频法原理:在一定时间内,对信号的脉冲计数,然后算出1s内有几个脉冲就是几赫兹,可以想到的是,如果开始数的时候不是从方波的上升沿或者下降沿开始数,而是在高电平持续时间或者低电平持续时间开始数,理论分析就知道一定存在误差。

等周期法:测出一个脉冲的时间,周期分之一即为频率。

等精度法:等精度测频法就是通过控制闸门信号与被测信号Fx同步从而消除了计数误差,其原理电路如图1所示,将闸门信号G作为边沿D触发器的输入,被测信号Fx作为D触发器的时钟脉冲时,D触发器输出的新闸门信号SG与Fx同步

图一

等精度测频法的工作原理是:当闸门信号G跳变为高电平时,只有当被测信号Fx的上升沿到来时D触发器输出的新闸门信号SG才能跳变为高电平;当闸门信号G跳变为低电平时,同样只有当被测信号Fx的上升沿到来时D触发器输出的新闸门信号SG才能跳变为低电平。因此,D触发器输出的新闸门信号SG与被测信号Fx严格同步,所以用新闸门信号控制计数器时,能够消除计数误差。但是,由于新闸门信号SG的作用时间受被测信号Fx的控制,虽然取原闸门信号G的作用时间为1秒,但新闸门信号的作用时间不一定为1秒,因而计数器N中的计数值并不能代表被测信号的频率值。改进的方法是,再添加一套与门和计数器,在新闸门信号SG的作用时间内同时对被测信号Fx和一个标准频率信号Fs进行计数,应用两个计数器的计数时间完全相同的关系推算出被测信号的频率值。

等精度测频法被测信号频率的计算原理如图2所示。若将新闸门信号SG的作用时间记为TD,标准频率信号Fs的周期记为Ts,被测信号Fx的周期记为Tx,在TD时间内对标准频率信号和被测信号的计数值分别记为N,和N;,则闸门信号SG的作用时间TD可以精确地表示为

TD=Nx×Tx

图二

等精度法更适合测量高频信号,但题目要求10HZ-2MHZ,跨度比较大,所以我选择在低频时选择用等周期,高频选择用等精度,利用按键做切换显示。

等周期代码如下:

?always @ (posedge clk or negedge rst_n)
? ? begin
? ? ? if (!rst_n)
? ? ? ? begin
? ? ? ? low_cnt <= 25'd0;
? ? ? ? high_cnt <= 25'd0;
? ? ? ? low_time <= 25'd0;
? ? ? ? high_time <= 25'd0;
? ? ? ? state <= high_state;
? ? ? ? end
? ? ? else
? ? ? begin
? ? ? ? case (state)
? ? ? ? ? high_state : begin
? ? ? ? ? ? ? if (wave == 1'b1) ? ? ? //判断输入为高电平
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? high_cnt <= high_cnt + 1'b1;
? ? ? ? ? ? ? ? ? state <= high_state;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? high_cnt <= 25'd0;
? ? ? ? ? ? ? ? ? high_time <= high_cnt;
? ? ? ? ? ? ? ? ? state <= low_state;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? end
? ? ? ? ? ??
? ? ? ? ? low_state : begin
? ? ? ? ? ? ? if (wave == 1'b0) ?//判断输入为低电平
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? low_cnt <= low_cnt + 1'b1;
? ? ? ? ? ? ? ? ? state <= low_state;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? low_cnt <= 25'd0;
? ? ? ? ? ? ? ? ? low_time <= low_cnt;
? ? ? ? ? ? ? ? ? state <= high_state;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? end
? ? ? ? ? default : state <= low_state;
? ? ? ? ? endcase
? ? ? end
? ? end

频率:assign freq = 1_000_000_000/(low_time * 20 + high_time * 20);??

解释一下这个公式,因为板载晶振是50MHZ,周期就是20ns,分母为ns,分子也为ns,算出来的频率单位才是HZ,所以分子1s=1_000_000_000ns。

同时也很好求出占空比:assign duty_cycle = (high_time * 100)/(high_time + low_time);

等精度需要详细解释,可以去看正点原子代码或者参考其他大佬

module cymometer
? ?#(parameter ? ?CLK_FS = 32'd50_000_000) // 基准时钟频率值
? ? (? ?
? ? ? ? input ? ? ? ? ? ? ? ? clk_fs , ? ? // 基准时钟信号
? ? ? ? input ? ? ? ? ? ? ? ? rst_n ?, ? ? // 复位信号


? ? ? ? input ? ? ? ? ? ? ? ? clk_fx , ? ? // 被测时钟信号
? ? ? ? output ? reg [20:0] ? data_fx ? ? ?// 被测时钟频率输出
);


localparam ? MAX ? ? ? = ?10'd64; ? ? ? ? ? // 定义fs_cnt、fx_cnt的最大位宽
localparam ? GATE_TIME = 16'd5_000; ? ? ? ?// 门控时间设置


reg ? ? ? ? ? ? ? ?gate ? ? ? ?; ? ? ? ? ? // 门控信号
reg ? ? ? ? ? ? ? ?gate_fs ? ? ; ? ? ? ? ? // 同步到基准时钟的门控信号
reg ? ? ? ? ? ? ? ?gate_fs_r ? ; ? ? ? ? ? // 用于同步gate信号的寄存器
reg ? ? ? ? ? ? ? ?gate_fs_d0 ?; ? ? ? ? ? // 用于采集基准时钟下gate下降沿
reg ? ? ? ? ? ? ? ?gate_fs_d1 ?; ? ? ? ? ? //?
reg ? ? ? ? ? ? ? ?gate_fx_d0 ?; ? ? ? ? ? // 用于采集被测时钟下gate下降沿
reg ? ? ? ? ? ? ? ?gate_fx_d1 ?; ? ? ? ? ? //?
reg ? ?[ ? 15:0] ? gate_cnt ? ?; ? ? ? ? ? // 门控计数
reg ? ?[MAX-1:0] ? fs_cnt ? ? ?; ? ? ? ? ? // 门控时间内基准时钟的计数值
reg ? ?[MAX-1:0] ? fs_cnt_temp ; ? ? ? ? ? // fs_cnt 临时值
reg ? ?[MAX-1:0] ? fx_cnt ? ? ?; ? ? ? ? ? // 门控时间内被测时钟的计数值
reg ? ?[MAX-1:0] ? fx_cnt_temp ; ? ? ? ? ? // fx_cnt 临时值


wire ? ? ? ? ? ? ? neg_gate_fs; ? ? ? ? ? ?// 基准时钟下门控信号下降沿
wire ? ? ? ? ? ? ? neg_gate_fx; ? ? ? ? ? ?// 被测时钟下门控信号下降沿

//边沿检测,捕获信号下降沿
assign neg_gate_fs = gate_fs_d1 & (~gate_fs_d0);
assign neg_gate_fx = gate_fx_d1 & (~gate_fx_d0);

//门控信号计数器,使用被测时钟计数
always @(posedge clk_fx or negedge rst_n) begin
? ? if(!rst_n)
? ? ? ? gate_cnt <= 16'd0;?
? ? else if(gate_cnt == GATE_TIME + 5'd20)
? ? ? ? gate_cnt <= 16'd0;
? ? else
? ? ? ? gate_cnt <= gate_cnt + 1'b1;
end

//门控信号,拉高时间为GATE_TIME个实测时钟周期
always @(posedge clk_fx or negedge rst_n) begin
? ? if(!rst_n)
? ? ? ? gate <= 1'b0;
? ? else if(gate_cnt < 4'd10)
? ? ? ? gate <= 1'b0; ? ??
? ? else if(gate_cnt < GATE_TIME + 4'd10)
? ? ? ? gate <= 1'b1;
? ? else if(gate_cnt <= GATE_TIME + 5'd20)
? ? ? ? gate <= 1'b0;
? ? else?
? ? ? ? gate <= 1'b0;
end

//将门控信号同步到基准时钟下
always @(posedge clk_fs or negedge rst_n) begin
? ? if(!rst_n) begin
? ? ? ? gate_fs_r <= 1'b0;
? ? ? ? gate_fs ? <= 1'b0;
? ? end
? ? else begin
? ? ? ? gate_fs_r <= gate;
? ? ? ? gate_fs ? <= gate_fs_r;
? ? end
end

//打拍采门控信号的下降沿(被测时钟下)
always @(posedge clk_fx or negedge rst_n) begin
? ? if(!rst_n) begin
? ? ? ? gate_fx_d0 <= 1'b0;
? ? ? ? gate_fx_d1 <= 1'b0;
? ? end
? ? else begin
? ? ? ? gate_fx_d0 <= gate;
? ? ? ? gate_fx_d1 <= gate_fx_d0;
? ? end
end

//打拍采门控信号的下降沿(基准时钟下)
always @(posedge clk_fs or negedge rst_n) begin
? ? if(!rst_n) begin
? ? ? ? gate_fs_d0 <= 1'b0;
? ? ? ? gate_fs_d1 <= 1'b0;
? ? end
? ? else begin
? ? ? ? gate_fs_d0 <= gate_fs;
? ? ? ? gate_fs_d1 <= gate_fs_d0;
? ? end
end

//门控时间内对被测时钟计数
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)
? ? ? ? fx_cnt_temp <= fx_cnt_temp + 1'b1;
? ? 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)
? ? ? ? fs_cnt_temp <= fs_cnt_temp + 1'b1;
? ? else if(neg_gate_fs) begin
? ? ? ? fs_cnt_temp <= 32'd0;
? ? ? ? fs_cnt <= fs_cnt_temp;
? ? end
end

//计算被测信号频率
always @(posedge clk_fs or negedge rst_n) begin
? ? if(!rst_n) begin
? ? ? ? data_fx <= 32'd0;
? ? end
? ? else if(gate_fs == 1'b0)
? ? ? ? data_fx <= (CLK_FS* fx_cnt ) / fs_cnt ;
end

endmodule?

至此第一问就做完了。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-29 23:14:49  更:2022-01-29 23:15:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:37:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码