呼吸灯——FPGA

article/2025/10/27 22:52:33

文章目录

  • 前言
  • 一、呼吸灯是什么?
    • 1、介绍
    • 2、占空比调节示意图
  • 二、系统设计
    • 1、系统框图
    • 2、RTL视图
  • 三、源码
  • 四、效果
  • 五、总结
  • 六、参考资料


前言

环境:
1、Quartus18.0
2、vscode
3、板子型号:EP4CE6F17C8
要求:
将四个LED灯实现循环从亮到灭、灭到亮的过程。下面我使用了两种方法供大家阅读。


一、呼吸灯是什么?

呼吸灯其实是在微处理器的控制下,由暗渐亮、然后再由亮渐暗,模仿人呼吸方式的 LED 灯。

1、介绍

呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。PWM(Pulse Width Modulation),即脉冲宽度调制,它利用微处理器输出的 PWM 信号,实现对模拟电路控制的一种非常有效的技术,广泛应用于测量、通信、功率控制等领域。

在由计数器产生的固定周期的 PWM 信号下,如果其占空比为 0,则 LED 灯不亮;如果其占空比为100%,则 LED 灯最亮。所以将占空比从 0 到 100%,再从 100%到 0 不断变化,就可以实现 LED 灯的“呼吸”效果。

2、占空比调节示意图

在这里插入图片描述

二、系统设计

1、系统框图

在这里插入图片描述

2、RTL视图

  • 方法一:
    在这里插入图片描述
  • 方法二:
    在这里插入图片描述

三、源码

  • 方法一:
module BREATH_LED(input   sys_clk , //时钟信号 50Mhzinput   sys_rst_n , //复位信号output  [3:0] led //LED
);//reg define
reg [15:0] period_cnt ; //周期计数器频率:1khz 周期:1ms 计数值:1ms/20ns=50000
reg [15:0] duty_cycle ; //占空比数值
reg inc_dec_flag ; //0 递增 1 递减//*****************************************************//** main code//*****************************************************//根据占空比和计数值之间的大小关系来输出 LEDassign led = (period_cnt >= duty_cycle) ? 4'b1111 : 4'b0000;//周期计数器always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)period_cnt <= 16'd0;else if(period_cnt == 16'd50000)period_cnt <= 16'd0;elseperiod_cnt <= period_cnt + 1'b1;end//在周期计数器的节拍下递增或递减占空比always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n) beginduty_cycle <= 16'd0;inc_dec_flag <= 1'b0;endelse beginif(period_cnt == 16'd50000) begin //计满 1msif(inc_dec_flag == 1'b0) begin //占空比递增状态if(duty_cycle == 16'd50000) //如果占空比已递增至最大inc_dec_flag <= 1'b1; //则占空比开始递减 else //否则占空比以 25 为单位递增elseduty_cycle <= duty_cycle + 16'd25;endelse begin //占空比递减状态if(duty_cycle == 16'd0) //如果占空比已递减至 0inc_dec_flag <= 1'b0; //则占空比开始递增else //否则占空比以 25 为单位递减duty_cycle <= duty_cycle - 16'd25;endendendendendmodule
  • 方法二:
module BREATH #(
parameter 
TIME_US = 6'd49,
TIME_MS = 10'd999,
TIME_S  = 10'd999)
(input  clk,input  rst_n,output reg [3:0]led
);// parameter TIME_US = 6'd49;
// parameter TIME_MS = 10'd999;
// parameter TIME_S  = 10'd999;reg [5:0] cnt_us;
reg [9:0] cnt_ms;
reg [9:0] cnt_s;
reg flag;wire add_cnt_us;
wire end_cnt_us;wire add_cnt_ms;
wire end_cnt_ms;wire add_cnt_s;
wire end_cnt_s;always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_us <= 6'd0;endelse if(add_cnt_us)beginif(end_cnt_us)begincnt_us <= 6'd0;endelse begincnt_us <= cnt_us + 1'd1;endendelse begincnt_us <= cnt_us;end
endassign add_cnt_us = 1'b1;
assign end_cnt_us = add_cnt_us && cnt_us == TIME_US;always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_ms <= 10'd0;endelse if(add_cnt_ms)beginif(end_cnt_ms)begincnt_ms <= 10'd0;endelse begincnt_ms <= cnt_ms + 1'd1;endendelse begincnt_ms <= cnt_ms ;end
endassign add_cnt_ms = end_cnt_us;
assign end_cnt_ms = add_cnt_ms && cnt_ms == TIME_MS;always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_s <= 10'd0;endelse if(add_cnt_s)beginif(end_cnt_s)begincnt_s <= 10'd0;endelse begincnt_s <= cnt_s + 1'd1;endendelse begincnt_s <= cnt_s ;end
endassign add_cnt_s = end_cnt_ms;
assign end_cnt_s = add_cnt_s && cnt_s == TIME_S;always @(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;endelse if(end_cnt_s)beginflag <= ~flag;endelse beginflag <= flag;end
end
//通过比较秒与毫秒的计数大小实现占空比的变化
//因为毫秒在秒每加一后,都会重新开始,使得高低电平的占比不同
//实际上呼吸灯周期就是秒计数周期,变换的占空比大小就是循环加1或减一
always @(posedge clk or negedge rst_n)beginif(!rst_n)beginled <= 4'b0000;endelse if(!flag)beginled <= (cnt_s > cnt_ms)?4'b0000:4'b1111;endelse if(flag)beginled <= (cnt_s > cnt_ms)?4'b1111:4'b0000;endelseled <= led;
end
endmodule

实际上我更喜欢第一种,代码简洁易懂。

四、效果

呼吸灯


五、总结

呼吸灯的实现过程并不难,在原有的stm32实现呼吸灯的理解下更加透彻,就是通过控制周期里占空比的变化来实现。但值得一提的是第一种实现方法确实比较精简。

六、参考资料

以上资料均来自正点原子的教学视频或开拓者2开发教程:
原子官方


http://chatgpt.dhexx.cn/article/ocOYODG4.shtml

相关文章

51单片机——实现呼吸灯程序代码

实现效果如图&#xff1a; 注&#xff1a;该51单片机led灯引脚为P2^ 0 - P2^7,实际代码按照引脚图实现。 代码如下&#xff1a; #include<reg52.h> typedef unsigned int uint; typedef unsigned char uchar; //--------------Delay--------------------void Delay(uin…

单片机开发—呼吸灯的三种实现方法

目录 一、前言1、什么是呼吸灯2、如何实现呼吸灯 二、利用for循环实现呼吸灯三、利用定时器实现呼吸灯1.利用定时器中断实现2.利用定时器输出PWM波实现 四、总结 一、前言 提示&#xff1a;本文使用的芯片并非STM32系列&#xff0c;利用定时器实现呼吸灯是从寄存器层面讲解的&…

【STM32】8.简单呼吸灯的制作教程,附代码、效果视频

目的&#xff1a; 实现呼吸灯。逐渐亮&#xff0c;逐渐灭。 一&#xff0e;呼吸灯原理分析 外设工作靠电流&#xff0c;因此要改变电流大小&#xff0c;所以要动电阻或电压。 电阻&#xff1a;阻值固定&#xff0c;不可更改。 电压&#xff1a;怎么改变电压大小呢&#xff1…

自适应滤波C语言实现

这里写目录标题 原理代码结果 原理 自适应滤波是近年以来发展起来的一种最佳滤波方法。它是在维纳滤波,Kalman滤波等线性滤波基础上发展起来的一种最佳滤波方法。由于它具有更强的适应性和更优的滤波性能。从而在工程实际中,尤其在信息处理技术中得到了广泛的应用。自适应滤波…

c语言实现图像滤波处理

#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include <math.h> /* 位图头结构 */ #pragma pack(1) typedef struct tagBITMAPFILEHEADER {unsigned char bfType[2];//文件格式unsigned long bfSize;//文件大小unsigned short bfReserve…

卡尔曼滤波一阶矩阵C语言实现

①估计时刻k的状态&#xff1a; ②误差相关矩阵P&#xff0c;度量估计值的精确程度 ③卡尔曼增益 ④更新误差相关矩阵 ⑤更新状态变量 ⑥最后输出 C语言代码&#xff1a; float X_pre,P_pre,X_kalman_last,P_kalman_last,X_kalman2500,P_kalman2; //赋初值 float H,Q…

卡尔曼滤波C语言实现

卡尔曼5条基本公式&#xff0c;参考https://wenku.baidu.com/view/8523cb6eaf1ffc4ffe47ac24.html #include "stdio.h" #include "stdlib.h" #include "math.h"#define kal_Q 0.001 /*过程噪声协方差,Q增大&#xff0c;动态响应变快&#xff0…

C语言实现简单卡尔曼滤波

https://www.bilibili.com/video/BV1ez4y1X7eR DR.CAN讲的真的很好 卡尔曼滤波的步骤 步骤说明Step 1计算卡尔曼增益Step 2更新本次迭代的估计值Step 3更新本次迭代的估计误差 具体请看上面DR.CAN的视频 代码 参数说明x_mea测量值x_est估计值e_mea固有的测量误差&#xf…

C语言实现双边滤波

参考博文 看不懂公式的先去看参考博文 一个3*3窗口的代码 /**双边法滤波 3*3窗口 *参数 data[][COL] 图像数据 *参数 row 图像数据行数 *参数 varD 空域核d的标准差 *参数 varR 值域核r的标准差 *需要引用头文件math.h *typedef unsi…

数字图像处理,读懂频域处理的“傅里叶变换”

转载自&#xff1a;https://blog.csdn.net/ebowtang/article/details/39004979 以下部分文字资料整合于网络&#xff0c;本文仅供自己学习用&#xff01; 这是一幅很绝的一维傅里叶变换动态图 一&#xff0c;读懂傅里叶变换 一个信号能表示成傅里叶级数的形式是有条件的&…

傅立叶变换和拉普拉斯变换

欧拉公式 证明过程如下 首先是泰勒展开 参考cosX和sinX的泰勒展开可以证明这个问题。 还有下面这个号称宇宙最美公式 “自然底数e&#xff0c;自然数1和0&#xff0c;虚数i还有圆周率pi&#xff0c;它是这么简洁&#xff0c;这么美丽啊&#xff01;” 傅立叶级数 傅立叶在…

Little’s Law 利特尔法则

1 A simple definition: Little’s Law states that the long-term average number of customers in a stable system L L L is equal to the long-term average effective arrival rate, λ \lambda λ, multiplied by the average time a customer spends in the system, …

勒让德符号的说明及作用

Legendre符号的用途 一、 二次剩余 勒让德符号的提出的意义是判断一个数是否是模n的二次剩余&#xff0c;所以研究勒让德符号之前应该了解一下二次剩余。 存在x使x的平方与a MOD (p)就称a为模p的二次剩余&#xff0c;其中p为素数&#xff0c;a>0且a<p。 通过勒让…

奈奎斯特准则的简洁证明

一般而言&#xff0c;发送滤波器和接收滤波器的冲激响应相同且关于原点对称&#xff0c;有用信号事实上经过了这两个滤波器&#xff0c;所以等效滤波器为&#xff1a; 为使无符号间干扰&#xff0c; 应满足&#xff1a; 奈奎斯特准则指出上式等价于&#xff1a; 其中 表示的傅里…

蒙蒂霍尔悖论

贝叶斯与频率主义对蒙蒂霍尔问题的解 在定义概率时&#xff0c;通常有两种思想流派&#xff1a;贝叶斯主义和频率主义。前者将概率视为我们对事件发生的信念程度&#xff0c;而后者则将其视为事件发生的相对频率。这篇文章介绍了使用贝叶斯和频率主义方法来解决著名的蒙蒂霍尔问…

信号 信号的线性放大

信号 1.信号 信号是信息的载体或表达形式 2. 信号的频谱 正弦信号 方波信号 满足狄里赫利条件&#xff0c;展开成傅里叶级数 附 狄里赫利条件: 1) 函数在任意有限区间内连续&#xff0c;或只有有限个第一类间断点&#xff08;当t从左或右趋于这个间断点时&#xff0c;函数有有限…

信号的频域描述

一、周期信号的频域描述 1. 狄里赫利条件 &#xff08;1&#xff09;函数在任意有限区间内连续&#xff0c;或只有有限个第一类间断点 &#xff08;2&#xff09;在一个周期内&#xff0c;函数有有限个 极大值或极小值 2. 傅里叶级数 &#xff08;1&#xff09;傅里叶级数…

【信号与系统】(十三)傅里叶变换与频域分析——周期信号的傅里叶级数

文章目录 周期信号的傅里叶级数1 周期信号三角形式的傅里叶级数1.1 三角形式的傅里叶级数1.2 狄里赫利(Dirichlet)条件1.3 .余弦形式的傅里叶级数1.4 吉布斯现象 2 周期信号波形对称性和谐波特性2.1 f ( t ) f(t) f(t)为偶函数2.2 f ( t ) f(t) f(t)为奇函数2.3 f ( t ) f(t…

连续时间傅立叶变换和拉普拉斯变换

连续时间傅里叶变换简称&#xff1a;CTFT 连续时间周期信号x(t)如果满足狄里赫利条件&#xff0c;则其存在傅立叶级数对&#xff1a; x(t)在任何有限区间内&#xff0c;有有限个不连续点&#xff0c;并且在每个不连续点都必须是有限值。 注意&#xff1a;狄里赫利条件是充分条…

狄利克雷条件

属于 傅里叶级数分析使用的条件&#xff1a; 傅里叶在提出 傅里叶级数时坚持认为&#xff0c;任何一个周期信号都可以展开成傅里叶级数&#xff0c;虽然这个结论在当时引起许多争议&#xff0c;但持异议者却不能给出有力的不同论据。直到20年后(1829年)狄里赫利才对这个问题作出…