16. 呼吸灯

您所在的位置:网站首页 nova3e呼吸灯 16. 呼吸灯

16. 呼吸灯

2024-07-15 11:13| 来源: 网络整理| 查看: 265

16.3.3. 程序设计¶ 16.3.3.1. 模块框图¶

我们给模块取名为breath_led,同样本例我们也会用到计数器,所以时钟和复位信号也是必须有的,且输入只有时钟和复位信号。我们只需要控制一个led灯进行“呼吸”就可以了,所以输出是一个名为led_out的输出信号。根据上面的分析设计出的Visio框图如图 22‑3所示。

图 22‑3 呼吸灯模块框图

端口列表与功能总结如表格 22‑1所示。

表格 22‑1 呼吸灯模块输入输出信号描述

信号

位宽

类型

功能描述

sys_clk

1Bit

Input

工作时钟,频率50MHz

sys_rst_n

1Bit

Input

复位信号,低电平有效

led_out

1Bit

Output

输出控制led灯

16.3.3.2. 波形图绘制¶

在画波形之前,我们先分析一下该如何才能让 led灯实现“呼吸”的效果。整个呼吸灯“呼吸”的效果分为两部分,一个过程是从灭到亮,另一个过程是从亮到灭。为了把复杂的问题简单化,我们把led整个“呼吸”的动作进行分解,先分析从灭到亮的过程,而从亮到灭则是与之相反的一个过程。

为了让“呼吸”的效果表达的比较完美,我们把从灭到亮的时间设置为1s,也就是led灯在1s的时间内完成从灭到亮的效果,同理从亮到灭也是一样的时间。我们知道在安全范围内给led灯供的电压越大led灯也就越亮,难道这里我们要控制led灯的电压渐渐变大吗?显然这是不现实的,所以我们用另一种方法,通过控制PW M的占空比来实现led灯越亮的效果。我们知道同一时间段内,如果供给led灯一个脉冲信号的低电平持续的时间越长(高电平持续的时间越短)led灯就越亮,我们就是通过调整PWM实现高低电平的占空来调控led灯的亮度,我们取n个相同的时间段,然后让低电平的持续时间按照相等的时间间隔逐渐增多,这样子我们看上去 的led灯就会越来越亮了。

知道了原理后我们就要进一步分析该如何具体实现,首先我们需要在1s的时间内产生很多个时间相等的小段,然后控制每个时间小段中低电平持续的时间渐渐增加就可以了。为了让“呼吸”效果显得更加细腻,我们把1s的时间分成1000个时间相等的时间小段,每个小段的时间就是1ms,这1000个1ms的时间小段中低电平持 续的时间还不能相等,要有一个从少到多渐渐递增的关系,为了让1000个1ms的时间小段都不一样,我们就需要将1ms再分成1000个时间小段,那么每一个时间小段就是1us, 在逐渐变亮的过程中我们可以让led灯在第1个1ms的时间小段内亮0us,即全灭;第2个1ms的时间小段亮1us;第3个1ms的时间 小段亮2us,……,第998个1ms的时间小段亮997us,第999个1ms的时间小段亮998us,第1000个1ms的时间小段亮999us。在逐渐变灭的过程中同理,我们划分的等级越多,“呼吸”的就越顺畅,看上去的效果就越好,但是人眼的分辨率的有限的,当大于这个分辨率人眼就看不出来这种差异了。

下面我们开始进行波形的绘制,首先画出输入时钟和复位的波形,根据分析我们至少需要设计三个计数器,分别为用于计数从灭到亮1s时间的cnt_1s计数器、用于划分1000个1ms时间小段的cnt_1ms计数器和用于划分1000个1us时间小段的cnt_1us计数器。然后就是要确定每个计数器计数开始和清零的条 件。我们先画出cnt_1us计数器的波形,根据50MHz的时钟计算得需要计50个数,即计数器从0计数到49,只要不复位则计数器一直计数,cnt_1us计数器计数满即可清零。接下来就是产生cnt_1ms计数器的波形,我们想是不是可以利用已经产生好的cnt_1us计数器来产生cnt_1ms计数器呢?答案 是当然可以的,我们完全没有必要再重新产生一个计数1ms的计数器,而是利用已经做好的1us计数器,根据cnt_1us计数器的时间计算得每当cnt_1us计数器计数到49时cnt_1ms计数器加1,cnt_1ms计数器计数到999且cnt_1us计数器同时也计数到49时cnt_1ms计数器才能清零,如果 少了cnt_1us计数器计数到49这个条件,仿真时会发现最后一个1ms的时间小段是不够1ms时间的。我们也用同样的方法产生cnt_1s计数器,每当cnt_1ms计数器计数到999且cnt_1us计数器计数到49时cnt_1s计数器加1,cnt_1s计数器计数到999且cnt_1ms计数器计数到999 且cnt_1us计数器计数到49三个条件同时满足时cnt_1s计数器清零(条件如此多的原因和cnt_1us计数器的分析是相同的,编写代码仿真时可以观察效果)。设计好的三个计数器的波形如图 22‑4所示。

图 22‑4 计数器产生波形图

我们产生了所需要的三个计数器后新的问题来了,我们该如何才能让每一个1ms的时间小段的低电平持续时间都不一样且渐渐增加呢?这是本实验的一个难点所在,之所以说是难点在于需要我们仔细观察、联想才能找到答案,而且还涉及到一个小小的技巧问题。如图 22‑5所示,我们先画出呼吸灯从灭到亮时间段预期的led_ou t波形图,结合三个计数器我们发现led_out为低电平时间时cnt_1s计数器的计数值总是小于cnt_1ms计数器的计数值,这简直就是太完美的发现了,我们让cnt_1s计数器的计数值大于cnt_1ms计数器的计数值就可以实现每一个1ms的时间小段的低电平持续时间都不一样且渐渐增加的效果。同理呼吸灯从 亮到灭正好是相反的过程,如图 22‑6所示,要使cnt_1s计数器的计数值总是大于cnt_1ms计数器的计数值才能实现每一个1ms的时间小段的低电平持续时间都不一样且渐渐减小的效果。

图 22‑5 呼吸灯波形图(一)

图 22‑6 呼吸灯波形图(二)

为了区分从灭到亮和从亮到灭两个过程我们使用一个标志信号,这个标志信号不是脉冲,而是一个电平,更准确的来讲应该叫使能信号,这里我们取名为cnt_1s_en,如图 22‑7和图 22‑8所示,cnt_1s_en使能信号为低电平时实现呼吸灯从灭到亮的过程,cnt_1s_en使能信号为高的时候实现呼吸灯从亮到灭的过程,cnt_1s_en使能信号就这样来回取反就可以了,取反的条件和cnt_1s清零的条件相同即可,这样才能够表示完整的1s时间。

图 22‑7 呼吸灯波形图(三)

图 22‑8 呼吸灯波形图(四)

16.3.3.3. 代码编写¶

为了后面仿真和修改呼吸灯“呼吸”的时间,我们将计数器的计数个数用parameter进行定义。呼吸灯模块参考代码如下。

代码清单 22‑1 呼吸灯模块参考代码(breath_led.v)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72module 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灯 ); //// //\* Parameter and Internal Signal \// //// //reg define reg [5:0] cnt_1us ; reg [9:0] cnt_1ms ; reg [9:0] cnt_1s ; reg cnt_1s_en ; /// //\* Main Code \// //// //cnt_1us:1us计数器 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_1us


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3