《基于FPGA的便携式PWM方波信号发生器》论文分析(三)——数码管稳定显示与系统调试

news2024/11/27 6:01:01

一、论文概述

        基于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) begin
    if (!rst_n) begin
        counter <= 0;
        pwm_out <= 0;
    end else begin
        counter <= counter + 1;
        if (counter >= period) begin
            counter <= 0;
            pwm_out <= ~pwm_out;  // 切换输出状态
        end
    end
end

// 根据频率和占空比更新周期和高电平时间
always @(posedge clk) begin
    if (counter == 0) begin
        period <= (CLOCK_FREQ / (freq + 1)) - 1;  // 计算周期
        high_time <= (period * duty) / 100;  // 计算高电平时间
    end
end

endmodule

为了使基于FPGA的PWM方波信号发生器更加复杂和功能丰富,我们可以考虑添加以下功能:

  1. 可配置的频率和占空比:允许通过外部输入动态调整频率和占空比。
  2. 多位频率和占空比控制:使用更多的位数来控制频率和占空比,以提高分辨率。
  3. 多位输出:生成多个PWM通道,每个通道可以独立控制。
  4. 同步和异步复位:提供同步和异步复位选项,以提高系统的灵活性和可靠性。
  5. 死区时间控制:在PWM波形中添加死区时间,以防止短路和电磁干扰。
  6. 中断和事件标志:在特定的PWM事件(如周期结束)时生成中断或事件标志。
  7. 可编程输出极性:允许用户选择PWM输出的高电平或低电平为活动电平。
  8. 动态调整和实时更新:在运行时动态调整频率和占空比,而不需要复位。

以下是一个扩展的示例代码,实现了上述部分功能:

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) begin
    if (!rst_n) begin
        counter <= 0;
        pwm_out <= 0;
    end else if (!sync_rst_n) begin
        counter <= 0;
        pwm_out <= 0;
    end else begin
        counter <= counter + 1;
        if (counter >= period) begin
            counter <= 0;
            pwm_out <= pwm_out << 1;  // 左移一位,为下一个通道腾出空间
            if (channel_enable & (1 << 0)) pwm_out[0] <= ~pwm_out[0];  // 通道0
            if (channel_enable & (1 << 1)) pwm_out[1] <= ~pwm_out[1];  // 通道1
            // 继续为其他通道添加逻辑
        end
    end
end

// 根据频率和占空比更新周期和高电平时间
always @(posedge clk) begin
    if (counter == 0) begin
        period <= (CLOCK_FREQ / (freq + 1)) - 1;  // 计算周期
        high_time <= (period * duty) / 100;  // 计算高电平时间
        high_time_array <= high_time;  // 更新高电平时间数组
    end
end

// 动态调整频率和占空比
always @(posedge clk) begin
    if (counter == 0) begin
        period <= (CLOCK_FREQ / (freq + 1)) - 1;
        high_time <= (period * duty) / 100;
        for (int i = 0; i < 8; i++) begin
            if (channel_enable & (1 << i)) begin
                high_time_array[i] <= (period * duty) / 100;
            end
        end
    end
end

endmodule

        这个扩展的示例代码提供了一个更复杂的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) begin
    if (!rst_n) begin
        counter <= 0;
        pwm_out <= 0;
        pwm_state <= 0;
    end else if (!sync_rst_n) begin
        counter <= 0;
        pwm_state <= 0;
    end else begin
        counter <= counter + 1;
        case (pwm_state)
            0: begin // 斜坡上升
                if (counter < ramp_up) pwm_out <= pwm_out | (1 << pwm_state);
                else begin
                    pwm_state <= pwm_state + 1;
                    counter <= 0;
                end
            end
            1: begin // 高电平
                if (counter < high_time) ;
                else begin
                    pwm_state <= pwm_state + 1;
                    counter <= 0;
                end
            end
            2: begin // 死区时间
                if (counter < dead_time) ;
                else begin
                    pwm_state <= pwm_state + 1;
                    counter <= 0;
                end
            end
            3: begin // 低电平
                if (counter < low_time) ;
                else begin
                    pwm_state <= pwm_state + 1;
                    counter <= 0;
                end
            end
            4: begin // 斜坡下降
                if (counter < ramp_down) pwm_out <= pwm_out & ~(1 << (pwm_state - 1));
                else begin
                    pwm_state <= 0;
                    counter <= 0;
                end
            end
            default: pwm_state <= 0;
        endcase
    end
end

// 根据频率、占空比、相位和死区时间更新周期、高电平时间和低电平时间
always @(posedge clk) begin
    if (counter == 0) begin
        period <= (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
end

endmodule

        这个示例代码提供了一个高度复杂的PWM信号发生器,支持多位输出、相位控制、死区时间和斜坡控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2248223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机操作系统——进程控制(Linux)

进程控制 进程创建fork&#xff08;&#xff09;函数fork() 的基本功能fork() 的基本语法fork() 的工作原理fork() 的典型使用示例fork() 的常见问题fork() 和 exec() 结合使用总结 进程终止与$进程终止的本质进程终止的情况正常退出&#xff08;Exit&#xff09;由于信号终止非…

【贪心算法第四弹——376.摆动序列】

目录 1.题目解析 题目来源 测试用例 2.算法原理 3.实战代码 代码解析 本题还可以使用动态规划的解法来解决&#xff0c;不过动态规划的时间复杂度为O(N^2)&#xff0c;而贪心解法的时间复杂度为O(N)&#xff0c;动态规划方法的博客链接: 动态规划-子序列问题——376.摆动…

我谈离散傅里叶变换的补零

有限序列的零延拓——零延拓不会改变离散傅里叶变换的形状的续篇。 L点序列可以做N点傅里叶变换&#xff0c;当 L ⩽ N L\leqslant N L⩽N时不会产生混叠。这部分内容在Rafael Gonzalez和Richard Woods所著的《数字图像处理》完全没有提到。 补零是序列末尾补零&#xff0c;不…

day18 结构体

有参宏和函数的区别 1.展开时机&#xff1a;有参宏而言&#xff0c;在预处理阶段展开&#xff0c;而函数在调用时才展开 2.内存使用&#xff1a;有参宏而言&#xff0c;占用的是所在函数的空间&#xff0c;而函数在调用时会单独开辟空间 3.效率上&#xff1a;有参宏的效率比…

C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术

C嘎嘎探索篇&#xff1a;栈与队列的交响&#xff1a;C中的结构艺术 前言&#xff1a; 小编在之前刚完成了C中栈和队列&#xff08;stack和queue&#xff09;的讲解&#xff0c;忘记的小伙伴可以去我上一篇文章看一眼的&#xff0c;今天小编将会带领大家吹奏栈和队列的交响&am…

Postman设置接口关联,实现参数化

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结果&#xff0c; 从而让后一个接口能正常执行&#xff0c;这…

大模型的RAG微调与Agent:提升智能代理的效率与效果

目录 ​编辑 引言 RAG模型概述 检索阶段 生成阶段 RAG模型的微调 数据集选择 损失函数设计 微调策略 超参数调整 RAG模型在智能代理中的应用 客户服务 信息检索 内容创作 决策支持&#xff1a; 结论 引言 在人工智能的快速发展中&#xff0c;大型预训练模型&a…

前端---CSS(部分用法)

HTML画页面--》这个页面就是页面上需要的元素罗列起来&#xff0c;但是页面效果很差&#xff0c;不好看&#xff0c;为了让页面好看&#xff0c;为了修饰页面---》CSS CSS的作用&#xff1a;修饰HTML页面 用了CSS之后&#xff0c;样式和元素本身做到了分离的效果。---》降低了代…

【R语言管理】Pycharm配置R语言及使用Anaconda管理R语言虚拟环境

目录 使用Anaconda创建R语言虚拟环境1. 安装Anaconda2. 创建R语言虚拟环境 Pycharm配置R语言1. 安装Pycharm2. R Language for IntelliJ插件 参考 使用Anaconda创建R语言虚拟环境 1. 安装Anaconda Anaconda的安装可参见另一博客-【Python环境管理工具】Anaconda安装及使用教程…

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中&#xff0c;原始视频码流首先被解码成原始图像数据&#xff0c;然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样&#xff0c;转换前后的码流可能遵循相同的视频编码标准&#xff0c;也可能不遵循。…

Linux Shell 脚本题目集

1、执行 ping 命令对指定主机进行测试&#xff0c;以确定该主机是否处于存活状态并输出相应结果。 #!/bin/bashread -p "请输入主机号&#xff1a;" pc # 读取用户输入的主机号if [ -z "$pc" ];then # 检查用户输入是否为空echo "主…

使用ENSP实现默认路由

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为2.2.2.1/24 ip address 2.2.2.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为1.…

【vue3实现微信小程序】每日专题与分页跳转的初步实现

快速跳转&#xff1a; 我的个人博客主页&#x1f449;&#xff1a;Reuuse博客 新开专栏&#x1f449;&#xff1a;Vue3专栏 参考文献&#x1f449;&#xff1a;uniapp官网 免费图标&#x1f449;&#xff1a;阿里巴巴矢量图标库 ❀ 感谢支持&#xff01;☀ 前情提要 &#x…

小程序-基于java+SpringBoot+Vue的网上花店微信小程序设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

Opencv+ROS实现颜色识别应用

目录 一、工具 二、原理 概念 本质 三、实践 添加发布话题 主要代码 四、成果 五、总结 一、工具 opencvros ubuntu18.04 摄像头 二、原理 概念 彩色图像&#xff1a;RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09; HSV图像&#xff1a;H&#xff0…

解决 java -jar 报错:xxx.jar 中没有主清单属性

问题复现 在使用 java -jar xxx.jar 命令运行 Java 应用程序时&#xff0c;遇到了以下错误&#xff1a; xxx.jar 中没有主清单属性这个错误表示 JAR 文件缺少必要的启动信息&#xff0c;Java 虚拟机无法找到应用程序的入口点。本文将介绍该错误的原因以及如何通过修改 pom.xm…

JavaWeb——SpringBoot原理

10.1. 配置优先级 10.1.1. 配置文件 properties > yml(推荐) > yaml 10.1.2. Java系统属性、命令行参数 命令行参数 > Java系统属性 > 配置文件 10.2. Bean管理 10.2.1. 手动获取bean ApplicationContext&#xff0c;IOC容器对象 10.2.2. bean作用域 10.2.3.…

【AI绘画】Midjourney进阶:色调详解(上)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney中的色彩控制为什么要控制色彩&#xff1f;为什么要在Midjourney中控制色彩&#xff1f; &#x1f4af;色调白色调淡色调明色调 &#x1f4af…

STM32F103外部中断配置

一、外部中断 在上一节我们介绍了STM32f103的嵌套向量中断控制器&#xff0c;其中包括中断的使能、失能、中断优先级分组以及中断优先级配置等内容。 1.1 外部中断/事件控制器 在STM32f103支持的60个可屏蔽中断中&#xff0c;有一些比较特殊的中断&#xff1a; 中断编号13 EXTI…

【Vue3+Pinia】Vue新一代状态管理器Pinia

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…