《基于FPGA的便携式PWM方波信号发生器》论文分析(三)——数码管稳定显示与系统调试
一、论文概述
基于FPGA的便携式PWM方波信号发生器是一篇由任青颖、庹忠曜、黄洵桢、李智禺和张贤宇 等人发表的一篇期刊论文。该论文主要研究了一种新型的信号发生器,旨在解决传统PWM信号发生器在移动设备信号调控中存在的精准度低和便携性差的问题 。其基于现场可编程门阵列(FPGA)技术,设计了一款便携式PWM信号发生器。该设备能够实现占空比以1%的步长可调,频率通过四个按键分别控制实现100 Hz、1 kHz、10 kHz、100 kHz的四个频率脉宽可调的方波信号发生器。系统能够以10 μs的最小分辨率在数码管上进行显示 。对于电子工程和信号处理领域的专业人士提供了一种新的解决方案,有助于提高信号发生器的性能和便携性 。
二、数码管稳定显示
由于脉宽测量过程中所测量的为所在时刻时的测量脉冲个数,其属于始终变化的动态值,若将其直接显示,数码管的数据会以时钟信号的频率进行跳变。为确保数据的稳定与准确,需保证所显示的数据为输出信号下降沿那一刻时的测量信号个数,即需要对测量数据进行稳定处理,其数码管稳定显示电路图如图6所示:

由于FD4CE仅在输入上升沿时工作,将输出信号F进行翻转得到FEI,原有的F下降沿即成了FEI的上升沿,此时的Q0、Q1、Q2、Q3被置为输出信号高电平截止时的测量信号个数,将OUT19至OUT0按照从高位到低位的顺序排序即可实现在数码管上的稳定输出。
四、系统性能调试
依照上述原理搭建可控门电路,对信号产生功能与信号检测功能进行调试检测:先通过占空比按键将占空比调制至所需数据,观察数码管显示;再调制信号频率开关,观察数码管显示;最终调节多信号转换开关,用示波器观察其产生信号,其中50%占空比下脉宽测量实物图如图7所示:

在四种不同频率的情况下,信号发生器的数码管显示均稳定无误。但在实际的加减调控测试过程中,偶尔存在波动一次开关,同时进行多次加减的情况,根据多次测试我们发现:该情况与按键波动速率存在一定关联,拨动速率越快,该情况出现的概率与跳动的幅度越小,反之则越大。
五、问题分析与改善
对便携式信号发生器的所有元器件进行逐一检测,发现占空比跳动的根源在于按键开关自身闭合的不灵敏。当其从低电平置为高电平(即按键操作一次)时,应该仅有一次上升沿,其如图8a所示;但因技术以及操作失误等原因,按键开关在实际操作时存在抖动现象,即在短时间内产生多次上升沿,其如图8b所示:

依照上述设计,可控门电路每捕获一次占空比按键的上升沿,其自身即进行一次相应功能。其中置数功能默认调整至50%,故而在实际操作并无明显变化,而当捕获到多次加减上升沿时,占空比即一次进行多次跳动,即出现了4.1所述之问题。
为尽可能减少此类因硬件自身缺陷,而对便携式信号发生器性能的影响,特对按键信号进行消抖处理,将按键输入的电平信号置于时钟信号之后,保证系统所读取的仅为已稳定后的加减值,其电路设计如图9所示:

FDC作为D型触发器,其与加减信号和置数信号相连,将其延迟一个输入周期信号的周期时间,使模100可逆置数模块无法读取抖动部分的信号电平,从而实现对数控模块的消抖。
六、实际信号检测
将修改后的便捷式信号发生器接入示波器,针对其加减数控开关进行信号测试,将四个频率下的占空比分别调节至30%、50%、70%,其示波器PWM波检测图像如图10所示:

每进行一次“+”“-”按键调控,占空比分别增加或减少1%,上述问题得到完美解决,并由示波器检测数据可知,该便携式PWM信号发生器的输出信号稳定且精准,并没有出现明显失真,且实际性能满足系统电气指标所需,该便携式信号发生器性能良好。
围绕FPGA进行相关电路设计,并根据实物情况进行相关改进,可通过频率按键开关组实现PWM波,并可通过“+”“-”按键与一键置位开关,对占空比进行相关调控。同时,它能够测量自身所产生的信号以及外界输入信号的频率与占空比,并在数码管上的最小分辨率进行显示。经过标准示波器的信号检测可知该便携式PWM信号发生器的输出信号稳定且精准,并没有出现明显失真,具有精度高、便携性好、性能稳定的优点。
七、代码示例分析
此处提供一个基于FPGA的便携式PWM方波信号发生器的示例代码的大致框架和分析。这个示例代码将使用Verilog HDL编写,这是FPGA设计中常用的硬件描述语言。
module PWM_Generator(input clk, // 时钟信号input rst_n, // 复位信号,低电平有效input [15:0] freq, // 频率控制输入input [15:0] duty, // 占空比控制输入output reg pwm_out // PWM输出
);// 定义参数
parameter CLOCK_FREQ = 50_000_000; // FPGA时钟频率
parameter MAX_COUNT = CLOCK_FREQ / 100; // 最大计数器值// 计数器变量
reg [31:0] counter = 0;
reg [31:0] period = 0;
reg [31:0] high_time = 0;// 计算周期和高电平时间
always @(posedge clk or negedge rst_n) beginif (!rst_n) begincounter <= 0;pwm_out <= 0;end else begincounter <= counter + 1;if (counter >= period) begincounter <= 0;pwm_out <= ~pwm_out; // 切换输出状态endend
end// 根据频率和占空比更新周期和高电平时间
always @(posedge clk) beginif (counter == 0) beginperiod <= (CLOCK_FREQ / (freq + 1)) - 1; // 计算周期high_time <= (period * duty) / 100; // 计算高电平时间end
endendmodule
为了使基于FPGA的PWM方波信号发生器更加复杂和功能丰富,我们可以考虑添加以下功能:
- 可配置的频率和占空比:允许通过外部输入动态调整频率和占空比。
- 多位频率和占空比控制:使用更多的位数来控制频率和占空比,以提高分辨率。
- 多位输出:生成多个PWM通道,每个通道可以独立控制。
- 同步和异步复位:提供同步和异步复位选项,以提高系统的灵活性和可靠性。
- 死区时间控制:在PWM波形中添加死区时间,以防止短路和电磁干扰。
- 中断和事件标志:在特定的PWM事件(如周期结束)时生成中断或事件标志。
- 可编程输出极性:允许用户选择PWM输出的高电平或低电平为活动电平。
- 动态调整和实时更新:在运行时动态调整频率和占空比,而不需要复位。
以下是一个扩展的示例代码,实现了上述部分功能:
module PWM_Generator_Advanced(input clk, // 时钟信号input rst_n, // 复位信号,低电平有效input sync_rst_n, // 同步复位信号,低电平有效input [15:0] freq, // 频率控制输入input [15:0] duty, // 占空比控制输入input [7:0] channel_enable, // 通道使能控制output reg [7:0] pwm_out // 多位PWM输出
);// 定义参数
parameter CLOCK_FREQ = 50_000_000; // FPGA时钟频率
parameter MAX_COUNT = CLOCK_FREQ / 100; // 最大计数器值// 计数器变量
reg [31:0] counter = 0;
reg [31:0] period = 0;
reg [31:0] high_time = 0;
reg [7:0] high_time_array = 0;// 动态调整频率和占空比
always @(posedge clk or negedge rst_n) beginif (!rst_n) begincounter <= 0;pwm_out <= 0;end else if (!sync_rst_n) begincounter <= 0;pwm_out <= 0;end else begincounter <= counter + 1;if (counter >= period) begincounter <= 0;pwm_out <= pwm_out << 1; // 左移一位,为下一个通道腾出空间if (channel_enable & (1 << 0)) pwm_out[0] <= ~pwm_out[0]; // 通道0if (channel_enable & (1 << 1)) pwm_out[1] <= ~pwm_out[1]; // 通道1// 继续为其他通道添加逻辑endend
end// 根据频率和占空比更新周期和高电平时间
always @(posedge clk) beginif (counter == 0) beginperiod <= (CLOCK_FREQ / (freq + 1)) - 1; // 计算周期high_time <= (period * duty) / 100; // 计算高电平时间high_time_array <= high_time; // 更新高电平时间数组end
end// 动态调整频率和占空比
always @(posedge clk) beginif (counter == 0) beginperiod <= (CLOCK_FREQ / (freq + 1)) - 1;high_time <= (period * duty) / 100;for (int i = 0; i < 8; i++) beginif (channel_enable & (1 << i)) beginhigh_time_array[i] <= (period * duty) / 100;endendend
endendmodule
这个扩展的示例代码提供了一个更复杂的PWM信号发生器,支持多位输出和动态调整频率和占空比。在实际应用中,可以根据具体需求进一步扩展和优化。
module Advanced_PWM_Generator(input wire clk, // 主时钟input wire rst_n, // 异步复位input wire sync_rst_n, // 同步复位input wire [15:0] freq, // 频率控制输入input wire [15:0] duty, // 占空比控制输入input wire [15:0] phase, // 相位控制输入input wire [15:0] dead_time, // 死区时间控制输入input wire [7:0] channel_enable, // 通道使能控制output reg [7:0] pwm_out // 多位PWM输出
);// 定义参数
parameter CLOCK_FREQ = 50_000_000; // FPGA时钟频率
parameter MAX_COUNT = CLOCK_FREQ / 100; // 最大计数器值// 内部变量
reg [31:0] counter = 0;
reg [31:0] period = 0;
reg [31:0] high_time = 0;
reg [31:0] low_time = 0;
reg [31:0] dead_count = 0;
reg [31:0] ramp_up = 0;
reg [31:0] ramp_down = 0;
reg [7:0] pwm_state = 0;// 计算周期、高电平时间和低电平时间
always @(posedge clk or negedge rst_n) beginif (!rst_n) begincounter <= 0;pwm_out <= 0;pwm_state <= 0;end else if (!sync_rst_n) begincounter <= 0;pwm_state <= 0;end else begincounter <= counter + 1;case (pwm_state)0: begin // 斜坡上升if (counter < ramp_up) pwm_out <= pwm_out | (1 << pwm_state);else beginpwm_state <= pwm_state + 1;counter <= 0;endend1: begin // 高电平if (counter < high_time) ;else beginpwm_state <= pwm_state + 1;counter <= 0;endend2: begin // 死区时间if (counter < dead_time) ;else beginpwm_state <= pwm_state + 1;counter <= 0;endend3: begin // 低电平if (counter < low_time) ;else beginpwm_state <= pwm_state + 1;counter <= 0;endend4: begin // 斜坡下降if (counter < ramp_down) pwm_out <= pwm_out & ~(1 << (pwm_state - 1));else beginpwm_state <= 0;counter <= 0;endenddefault: pwm_state <= 0;endcaseend
end// 根据频率、占空比、相位和死区时间更新周期、高电平时间和低电平时间
always @(posedge clk) beginif (counter == 0) beginperiod <= (CLOCK_FREQ / (freq + 1)) - 1;high_time <= (period * duty) / 100;low_time <= period - high_time - dead_time;ramp_up <= (high_time * phase) / 100;ramp_down <= (low_time * phase) / 100;dead_count <= dead_time;end
endendmodule
这个示例代码提供了一个高度复杂的PWM信号发生器,支持多位输出、相位控制、死区时间和斜坡控制。
相关文章:
《基于FPGA的便携式PWM方波信号发生器》论文分析(三)——数码管稳定显示与系统调试
一、论文概述 基于FPGA的便携式PWM方波信号发生器是一篇由任青颖、庹忠曜、黄洵桢、李智禺和张贤宇 等人发表的一篇期刊论文。该论文主要研究了一种新型的信号发生器,旨在解决传统PWM信号发生器在移动设备信号调控中存在的精准度低和便携性差的问题 。其基于现场可编…...
VsCode 插件推荐(个人常用)
VsCode 插件推荐(个人常用)...
路由策略与路由控制实验
AR1、AR2、AR3在互联接口、Loopback0接口上激活OSPF。AR3、AR4属于IS-IS Area 49.0001,这两者都是Level-1路由器,AR3、AR4的系统ID采用0000.0000.000x格式,其中x为设备编号 AR1上存在三个业务网段A、B、C(分别用Loopback1、2、3接…...
训练的decoder模型文本长度不一致,一般设置为多大合适,需要覆盖最长的文本长度么
在训练解码器模型时,文本长度不一致是常见的情况,需要根据任务的特性和数据集的长度分布来设置合理的最大长度 (max_length)。以下是一些指导原则,帮助你设置合适的最大长度: 1. 是否需要覆盖最长文本长度 覆盖最长文本长度: 如果任务对完整性要求很高(例如生成数学公式、…...
过滤条件包含 OR 谓词,如何进行查询优化——OceanBase SQL 优化实践
这篇博客涉及两个点,一个是 “OR Expansion 改写”,另一个是 “基于代价的改写”。 背景 在写SQL查询时,难以避免在过滤条件中使用 OR 谓词,但其往往会导致索引利用效率下降的问题 。本文将分享如何通过查询改写的2种方式进行优化…...
通过异步使用消息队列优化秒杀
通过异步使用消息队列优化秒杀 同步秒杀流程异步优化秒杀异步秒杀流程基于lua脚本保证Redis操作原子性代码实现阻塞队列的缺点 同步秒杀流程 public Result seckillVoucher(Long voucherId) throws InterruptedException {SeckillVoucher seckillVoucher iSeckillVoucherServi…...
AI产业告别“独奏”时代,“天翼云息壤杯”高校AI大赛奏响产学研“交响乐”
文 | 智能相对论 作者 | 陈泊丞 人工智能产业正在从“独奏”时代进入“大合奏”时代。 在早期的AI发展阶段,AI应用主要集中在少数几个领域,如语音识别、图像处理等。这些领域的研究和开发工作往往由少数几家公司或研究机构即可独立完成,犹…...
Hot100 - 字母异位词分组
Hot100 - 字母异位词分组 最佳思路:排序 时间复杂度: O(nmlogm),其中 n 为 strs 数组的长度,m 为每个字符串的长度。 代码: class Solution {public List<List<String>> groupAnagrams(String[] strs) …...
力扣hot100-->排序
排序 1. 56. 合并区间 中等 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 1: 输…...
【VRChat 全身动捕】VIVE 手柄改 tracker 定位器教程,低成本光学动捕解决方案(持续更新中2024.11.26)
更新 0.0.1(2024/11/26): 1.解决了内建蓝牙无法识别、“steamVR 蓝牙不可用” 的解决方案 2.解决了 tracker 虽然建立了连接但是在 steamVR 界面上看不到的问题 3.解决了 VIVE 基站1.0 无法被蓝牙识别 && 无法被 steamVR 搜索到 &…...
【Nginx】核心概念与安装配置解释
文章目录 1. 概述2. 核心概念2.1.Http服务器2.2.反向代理2.3. 负载均衡 3. 安装与配置3.1.安装3.2.配置文件解释3.2.1.全局配置块3.2.2.HTTP 配置块3.2.3.Server 块3.2.4.Location 块3.2.5.upstream3.2.6. mine.type文件 3.3.多虚拟主机配置 4. 总结 1. 概述 Nginx是我们常用的…...
Qt界面篇:QMessageBox高级用法
1、演示效果 2、用法注意 2.1 设置图标 用于显示实际图标的pixmap取决于当前的GUI样式。也可以通过设置icon pixmap属性为图标设置自定义pixmap。 QMessageBox::Icon icon(...
【二叉树】【2.1遍历二叉树】【刷题笔记】【灵神题单】
关注二叉树的三个问题: 什么情况适合自顶向下?什么时候适合用自底向上?一般来说,DFS的递归边界是空节点,什么情况下要额外把叶子节点作为递归边界?在什么情况下,DFS需要有返回值?什…...
Mongo数据库 --- Mongo Pipeline
Mongo数据库 --- Mongo Pipeline 什么是Mongo PipelineMongo Pipeline常用的几个StageExplanation with example:MongoDB $matchMongoDB $projectMongoDB $groupMongoDB $unwindMongoDB $countMongoDB $addFields Some Query Examples在C#中使用Aggreagtion Pipeline**方法一: …...
Adobe Illustrator 2024 安装教程与下载分享
介绍一下 下载直接看文章末尾 Adobe Illustrator 是一款由Adobe Systems开发的矢量图形编辑软件。它广泛应用于创建和编辑矢量图形、插图、徽标、图标、排版和广告等领域。以下是Adobe Illustrator的一些主要特点和功能: 矢量绘图:Illustrator使用矢量…...
javax.xml.ws.soap.SOAPFaultException: ZONE_OFFSET
javax.xml.ws.soap.SOAPFaultException 表示 SOAP 调用过程中发生了错误,并且服务端返回了一个 SOAP Fault。 错误信息中提到的 ZONE_OFFSET 可能指的是时区偏移量。在日期和时间处理中,时区偏移量是指格林威治标准时间 (GMT) 的偏移量。如果服务期望特…...
常用的数据结构
队列(FIFO) 栈(LIFO) 链表 hash表 hash冲突处理 开放式寻址 线性探测 表示依次检查索引为 hash(key) + 1、hash(key) + 2 ... 的位置。i 是冲突后的探查步数。公式:hash(i) = (hash(key) + i) % TableSize二次探查 规则:冲突后探查的步长是平方递增的,例如,检查位置为 hash…...
javaweb-day01-html和css初识
html:超文本标记语言 CSS:层叠样式表 1.html实现新浪新闻页面 1.1 标题排版 效果图: 1.2 标题颜色样式 1.3 标签内颜色样式 1.4设置超链接 1.5 正文排版 1.6 页面布局–盒子 (1)盒子模型 (2)页面布局…...
C++11特性(详解)
目录 1.C11简介 2.列表初始化 3.声明 1.auto 2.decltype 3.nullptr 4.范围for循环 5.智能指针 6.STL的一些变化 7.右值引用和移动语义 1.左值引用和右值引用 2.左值引用和右值引用的比较 3.右值引用的使用场景和意义 4.右值引用引用左值及其一些更深入的使用场景分…...
基于Springboot的心灵治愈交流平台系统的设计与实现
基于Springboot的心灵治愈交流平台系统 介绍 基于Springboot的心灵治愈交流平台系统,后端框架使用Springboot和mybatis,前端框架使用Vuehrml,数据库使用mysql,使用B/S架构实现前台用户系统和后台管理员系统,和不同级别…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
