首页 > 其他分享 >17-呼吸灯

17-呼吸灯

时间:2023-06-09 14:55:13浏览次数:30  
标签:cnt led 17 1ms 1s 呼吸 低电平 占空比

1.呼吸灯

呼吸灯在我们的生活中很常见,在手机上多作为消息提醒指示灯而被广泛使用,其效果是小灯在一段时间内从完全熄灭的状态逐渐变到最亮,再在同样的时间段内逐渐达到完全熄灭的状态,并循环往复。这种效果就像“呼吸”一样,有张有弛,而且给人一种很舒服的感觉。其工作原理是利用 PWM 来控制小灯在相同时间段内的不同占空比,即在同样小时间段内,小灯亮的时间依次增加到最大后再依次减小,从而实现渐亮到渐灭的“呼吸”效果

2.PWM介绍

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。 ​

2.1 PWM频率/周期/占空比/脉冲时间

  • PWM频率:是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);也就是说一秒钟PWM有多少个周期
  • PWM周期:上升沿到上升沿(下降沿到下降沿的时间)
  • 脉冲时间:高电平时间
  • 占空比(duty cycle):一个周期内,高电平时间占整个周期的比例

2.2 占空比运算

  • 50M时钟,时钟周期为20ns,占空比50%,高电平时间为20*50% = 10ns
  • 周期是10ms,脉冲时间是8ms,占空比8/10 = 80%

2.3 占空比原理

  • 以单片机为例,我们知道,单片机的IO口输出的是数字信号,IO口只能输出高电平和低电平。假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号
  • 电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压,比方说 占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V
  • PWM的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降,也就是,在一定的频率下,通过不同的占空比 即可得到不同的输出模拟电压,PWM就是通过这种原理实现D/A转换的。
  • PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压

2.4 PWM控制呼吸灯

  • 人眼对于80Hz以上的刷新频率完全没有闪烁感,刷新频率太低看起来就回闪烁。对于LED灯,当其频率大于50Hz的时候,基本看不到闪烁(常亮)’
    * 频率很高时,看不到闪烁,占空比越大,LED越亮;
  • 频率很低时,可看到闪烁,占空比越大,LED越亮。
  • 所以,在频率一定下,可以用不同占空比改变LED灯的亮度。 使其达到一个呼吸灯的效果

3.FPGA设计

  • 使用LED灯实现呼吸的效果,LED灯电平点亮

3.1 模块框图和波形图

  • 整个呼吸灯“呼吸”的效果分为两部分,一个过程是从灭到亮,另一个过程是从亮到灭。为了把复杂的问题简单化,我们把 led 整个“呼吸”的动作进行分解,先分析从灭到亮的过程,而从亮到灭则是与之相反的一个过程。
  • 假设灯从熄灭到完全点亮的时间为1s,通过控制 PWM 的占空比来实现 led 灯
    越亮的效果。我们知道同一时间段内,如果供给 led 灯一个脉冲信号的低电平持续的时间越长(高电平持续的时间越短)led 灯就越亮,我们就是通过调整 PWM 实现高低电平的占空来调控 led 灯的亮度,我们取 n 个相同的时间段,然后让低电平的持续时间按照相等的时间间隔逐渐增多,这样子我们看上去的 led 灯就会越来越亮了。
  • 将亮灯的1s分为等长的时间段,每一段时间内低电平的时间不断增加,实现灯的亮度依次增加,实现呼吸的效果,将1s分为1000份,每一份是1ms,在每一份的1ms内低电平的时间逐渐增加,每次增加1us
    第1个 1ms 1us
    第2个 1ms 2us
    第3个 3ms 3us
    .........
  • 需要三个计数器cnt_1s、cnt_1ms、cnt_1us
  • cnt_1us - 时钟周期是20ns,1us需要50个时钟周期,最大计数到49
  • cnt_1us 0-49 0-49 0-49 0-49 0-49 0-49 ......
  • cnt_1ms - 1ms = 1000us = 1000个0-49计数时间,cnt_1us经过一个0-49的计数周期,cnt_1ms自加1
  • cnt_1ms需要计数1000个0-49,计数最大值是1000-1 = 999
  • cnt_1s - 1s = 1000ms = 1000个cnt_1ms计数周期(0-999),cnt_1ms每经历一个0-999计数,cnt_1s自加1

如何在1ms内控制低电平时间不断增加?

cnt_1s 1 2 3
cnt_1ms 0 1 .... 999 0 1 .... 999 0 1 2 ... 999
第1个周期cnt_1ms有1个周期的数值小于cnt_1s
第2个周期cnt_1ms有2个周期的数值小于cnt_1s
第3个周期cnt_1ms有3个周期的数值小于cnt_1s
.............
第999个周期cnt_1ms有999个周期的数值小于cnt_1s

  • 发现 led_out 为低电平时间时 cnt_1s 计数器的计数值总是小于 cnt_1ms 计数器的计数值,所以得出控制低电平时间的关键条件:led_out,当cnt_1ms<=cnt_1s,保持低电平,其他为高电平
  • 熄灭信号就是led_out进行取反


    要使 cnt_1s 计数器的计数值总是大于 cnt_1ms 计数器的计数值才能实现每一个 1ms 的时间小段的低电平持续时间都不一样且渐渐减小的效果。为了区分从灭到亮和从亮到灭两个过程我们使用一个标志信号,这个标志信号不是脉冲,而是一个电平,更准确的来讲应该叫使能信号,这里我们取名为 cnt_1s_en

3.2 RTL

module breath_led
#(
	parameter CNT_1US_MAX = 6'd49 ,
	parameter CNT_1MS_MAX = 10'd999 ,
	parameter CNT_1S_MAX = 10'd999
)
(
	input wire sys_clk , //系统时钟 50MHz
	input wire sys_rst_n , //全局复位
 
	output reg led_out //输出信号,控制 led 灯
 );
 
	//reg define
 
	reg [5:0] cnt_1us ;
	reg [9:0] cnt_1ms ;
	reg [9:0] cnt_1s ;
	reg cnt_1s_en ;

	//cnt_1us:1us 计数器
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_rst_n == 1'b0)
			cnt_1us <= 6'b0;
		else if(cnt_1us == CNT_1US_MAX)
			cnt_1us <= 6'b0;
		else
			cnt_1us <= cnt_1us + 1'b1;
	
	//cnt_1ms:1ms 计数器
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_rst_n == 1'b0)
			cnt_1ms <= 10'b0;
		else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX)
			cnt_1ms <= 10'b0;
		else if(cnt_1us == CNT_1US_MAX)
			cnt_1ms <= cnt_1ms + 1'b1;
	
	//cnt_1s:1s 计数器
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_rst_n == 1'b0)
			cnt_1s <= 10'b0;
		else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX 
									&& cnt_1us == CNT_1US_MAX)
			cnt_1s <= 10'b0;
		else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX)
			cnt_1s <= cnt_1s + 1'b1;
	
	//cnt_1s_en:1s 计数器标志信号
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_rst_n == 1'b0)
			cnt_1s_en <= 1'b0;
	else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX 
								&& cnt_1us == CNT_1US_MAX)
		cnt_1s_en <= ~cnt_1s_en;
	
	//led_out:输出信号连接到外部的 led 灯
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_rst_n == 1'b0)
			led_out <= 1'b0;
		else if((cnt_1s_en == 1'b1 && cnt_1ms < cnt_1s) || 
				(cnt_1s_en == 1'b0 && cnt_1ms > cnt_1s))
			led_out <= 1'b0;
		else
			led_out <= 1'b1;
	
endmodule

3.3 Testbench

`timescale 1ns/1ns
module tb_breath_led();


//wire define
	wire led_out ;

 //reg define
	reg sys_clk ;
	reg sys_rst_n ;
 
 //********************************************************************/
 //***************************** Main Code ****************************//
 //********************************************************************//
 //初始化系统时钟、全局复位
	initial begin
		sys_clk = 1'b1;
		sys_rst_n <= 1'b0;
		#20
		sys_rst_n <= 1'b1;
	end
 
 //sys_clk:模拟系统时钟,每 10ns 电平翻转一次,周期为 20ns,频率为 50MHz
	always #10 sys_clk = ~sys_clk;


	breath_led
	#(
		.CNT_1US_MAX(6'd4 ),
		.CNT_1MS_MAX(10'd9 ),
		.CNT_1S_MAX (10'd9 )
	)
	breath_led_inst
	(
		.sys_clk (sys_clk ), //input sys_clk
		.sys_rst_n (sys_rst_n ), //input sys_rst_n
	
		.led_out (led_out ) //output led_out
	);
	
 endmodule

标签:cnt,led,17,1ms,1s,呼吸,低电平,占空比
From: https://www.cnblogs.com/Icer-newer/p/17468228.html

相关文章

  • win10 vs2022 搭建 cocos2d-x 3.17 开发环境
    引擎下载地址https://cocos2d-x.org/download/也可以在github下载https://github.com/cocos2d/cocos2d-x/tags手册地址https://docs.cocos2d-x.org/cocos2d-x/v3/zh/api文档地址https://docs.cocos2d-x.org/api-ref/cplusplus/v3x/index.htmlhelloworld安装注意事项......
  • 8.17 Object类简介
    classPerson{}和classPersonextendsObject是一样的。前面extendsObject被省略了如果一个程序的方法要求可以接收所有类对象的时候,就可以利用Object类实现。demo1classPerson{}publicclassHelloWorld{publicstaticvoidmain(Stringargs[]){......
  • Kali安装JDK8以及JDK11、JDK17切换
    声明:本文分享的安全工具和项目均来源于网络,仅供安全研究与学习之用,如用于其他用途,由使用者承担全部法律及连带责任,与工具作者和本公众号无关。 瓜神学习网络安全公众号   背景 很久之前更新了一次kali,今天用的时候发现JDK变成17了 安装J......
  • DSPC174 3BSE005461R1嵌入式卡件ABB
    DSPC1743BSE005461R1嵌入式卡件ABBDSPC1743BSE005461R1嵌入式卡件ABB 为您的过程选择PLC或控制器非常重要,因为它有助于成本优化。要确定最适合用于自动化任务的PLC,需要考虑几个基本因素:必要的输入/输出能力所需的I/O类型所需内存大小CPU和指令集所需的速度和功率......
  • 【解决问题】libevent 编译时报错 Makefile:1708: test/.deps/test_regress-tinytest.
    1开发环境linux版本:统信UOS1030(可以认为是特殊的ubuntu)开发语言:C++2报错现象截图:报错语句:make:进入目录“/home/depend/libevent-2.1.11-stable”Makefile:1708:test/.deps/test_regress-tinytest.Po:没有那个文件或目录make:***没有规则可制作目标“te......
  • P1751 贪吃虫 题解
    题意:题目传送门在一棵n个结点的树上,有k个贪吃虫去吃食物。每个贪吃虫都走到达食物的唯一路径。当一条贪吃虫通向食物的道路上有另一条贪吃虫,则较远的那只停止移动。多条贪吃虫要进入同一节点时,编号最小的才能进入,其他的停止移动。贪吃虫的移动速度皆为1。一只贪吃虫吃......
  • LDGRB-01 3BSE013177R1 ABB模块 DCS S800I/O 全新
    LDGRB-013BSE013177R1ABB模块DCSS800I/O全新LDGRB-013BSE013177R1ABB模块DCSS800I/O全新 什么是仪器仪表中的基金会现场总线?与传统概念相比,现场总线有哪些优势?什么是仪器仪表中的基金会现场总线? 基础现场总线是一种串行、双向、全数字网络,用作工厂或工厂自动......
  • 记录一次.NET6环境使用Visual Studio 2022 V17.6.2版本的异常
    开发环境C#开发环境VisualStudio2022V17.6.2版本。目标框架:.NET6.0错误内容:系统是BlazorServer框架的系统页面,在使用VisualStudio2022V17.6.2版本编译后,执行出现:TimeStamp:2023/6/613:35:07MachineName:Light.YangAppDomainName:SajetServerAppOS:Microsoft......
  • Luogu P3605 [USACO17JAN]Promotion Counting P
    [USACO17JAN]PromotionCountingP题目描述Thecowshaveonceagaintriedtoformastartupcompany,failingtorememberfrompastexperiencethatcowsmaketerriblemanagers!Thecows,convenientlynumbered\(1\ldotsN\)(\(1\leqN\leq100,000\)),o......
  • LeetCode 1790.仅执行一次字符串交换能否使两个字符串相等
    LeetCode1790.仅执行一次字符串交换能否使两个字符串相等思路暴力模拟,根据题目思路直接写代码即可,依次遍历字符串的每一位,如果相等则继续,如果不相同则分别储存在记录量flag1,flag2中,如果不同的位置超过两个或者只有一个则返回false,如果不存在不同位置或者不同的位置相同就返回tru......