集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 6761|回复: 17

基于PWM的呼吸灯设计

[复制链接]
星宇 发表于 2017-5-7 23:27:09 | 显示全部楼层 |阅读模式
呼吸灯广泛应用于手机之上,并成为各大品牌新款手机的卖点之一。如果手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会在控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸,起到一个通知提醒的作用。
 楼主| 星宇 发表于 2017-5-7 23:27:32 | 显示全部楼层
关于呼吸灯设计实现的理论主要是PWM有关知识。PWM(Pluse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。并广泛应用在从测量、通信、功率控制与变换及LED照明等许多领域中。顾名思义,就是占空比可调的信号,那么什么是占空比呢?
占空比(Duty Cycle or Duty Ratio),可以解释为,在一脉冲序列中(方波),正脉冲序列的持续时间与脉冲总周期的比值。也可理解为,电路释放能量的有效时间与总释放时间的比值。
PWM是怎样实现调光呢?想要调节LED的亮度变化,实则是调节控制流经LED的电流。电流增大则LED亮度增强,反之减弱。但由于电流为模拟信号,所以这时就用到了PWM。
 楼主| 星宇 发表于 2017-5-7 23:27:44 | 显示全部楼层
使用一系列等幅不等宽的脉冲来代替一个正弦波,脉冲的宽度根据正弦波a的幅度变化,幅度高,则脉冲宽,反之。
多数负载需要的PWM调制频率都高于10Hz,要想实现呼吸灯的效果,必须提高调制频率,通常调制频率为1Khz~200Khz之间。在LED控制中PWM作用于电源部分,脉宽调制的脉冲频率通常大于100Hz,人眼就不会感到闪烁。这里我们取PWM调制频率为1KHz,PWM周期为1ms。
脉冲频率一定时,输出脉冲的占空比越大,相当于输出的有效电平越大,随着占空比的不同,LED的亮度也将不同。如占空比为0时,则LED不亮,为100%时,则LED最量,我们让占空比从0~100%变化,再从100%~0不断变化,则就可实现呼吸灯效果。
        本设计呼吸灯的一个周期为2s,分为占空比增“吸”和占空比减“呼”两种模式,每个为1s,一个PWM周期为1ms,所以每个模式包含1000个PWM周期,将每个PWM周期分为1000份,即每个时间段1us。可以理解为变化的程度每次递增或者递减千分之一。占空比增时,则实现由暗变亮,将其取反,则可得到占空比减,实现由亮变暗。
 楼主| 星宇 发表于 2017-5-7 23:27:55 | 显示全部楼层
在本设计中需要三个计数器,分别为cnt_us,cnt_ms,cnt_s。由于系统时钟周期为20ns,所以cnt_us计数器实现1us的计时,计数到50;计数器cnt_us驱动计数器cnt_ms实现1ms的计时,计数到1000;计数器cnt_us和cnt_ms驱动计数器cnt_s实现1s的计时,计数到1000,最后用计数器cnt_ms和cnt_s作比较,从而调节占空比。如果cnt_s的值大于cnt_ms的值的时间段,当作点亮的时间,那么就可以实现LED由暗变亮。
 楼主| 星宇 发表于 2017-5-7 23:28:12 | 显示全部楼层
module breath_led (clk, rst_n, led);
1
2       input clk, rst_n;    //输入系统时钟,复位
3       output led;          //输出呼吸灯
4      
5       parameter T1us = 50;   //us计数参数
6       parameter T1ms = 1000; //ms计数参数
7       parameter T1s  = 1000; //s计数参数
8
9       reg [6:0] cnt_us;  //us计数器
10      reg [9:0] cnt_ms;  //ms计数器
11      reg [9:0] cnt_s;   //s计数器
12      
13      /*****通过计数器cnt_us,生成1us脉冲*****/
14      always @ (posedge clk or negedge rst_n)
15      begin
16          if (!rst_n)
17              cnt_us <= 7'd0;
18          else if (cnt_us == T1us - 1)
19              cnt_us <= 7'd0;
20          else
21              cnt_us <= cnt_us + 1'b1;
22      end
23      
24      /*****计数到1us时,产生一个同步脉冲,用来驱动cnt_ms*****/
25      wire flag_us;
26      assign flag_us = (cnt_us == T1us - 1) ? 1'b1 : 1'b0; //选择语句
27      
28      /*****通过计数器cnt_ms,生成1ms脉冲*****/
29      always @ (posedge clk or negedge rst_n)
30      begin
31          if (!rst_n)
32              cnt_ms <= 0;
33          else if ((cnt_ms == T1ms - 1) && flag_us)  //等待flag_us为1后,才可清零
34              cnt_ms <= 10'd0;
35          else if (flag_us)
36              cnt_ms <= cnt_ms + 1'b1;
37          else
38              cnt_ms <= cnt_ms;
39      end
40      
41      /*****计数到1ms时,产生一个同步脉冲,用来驱动cnt_s*****/
42      wire flag_ms;
43      assign flag_ms = (cnt_ms == T1ms - 1) ? 1'b1 : 1'b0; //选择语句
44      
45      
46      /*****通过计数器cnt_s,生成1s脉冲*****/
47      
48      reg change; //led灯由亮变暗和由暗变亮的切换
49      
50      always @ (posedge clk or negedge rst_n)
51      begin
52          if (!rst_n)
53              begin
54                  cnt_s <= 10'd0;
55                  change <= 0;  
56              end
57          else if ((cnt_s == T1s - 1) && flag_us && flag_ms)
58          /*等待flag_us和flag_ms为1后,才可清零*/
59              begin
60                  cnt_s <= 10'd0;
61                  change <= ~change;  
62              end
63          else if (flag_us && flag_ms)
64              cnt_s <= cnt_s + 1'b1;  //计数
65          else
66              cnt_s <= cnt_s;   //保持
67      end
68      
69      reg pwm_out; //占空比递增的脉冲
70      
71      always @ (posedge clk or negedge rst_n)
72      begin
73          if (!rst_n)
74              pwm_out <= 0;
75          else if (cnt_s > cnt_ms)  
76              pwm_out <= 1;   
77          else
78              pwm_out <= 0;
79      end
80      
81      assign led = (change == 1) ? ~pwm_out : pwm_out;
82
83  endmodule
 楼主| 星宇 发表于 2017-5-7 23:28:23 | 显示全部楼层
本设计的仿真代码如下:为了便于观察,我们采用参数传递的方式,将参数T1us设为5,T1ms设为10,T1s设为10。
 楼主| 星宇 发表于 2017-5-7 23:28:35 | 显示全部楼层
`timescale 1ns/1ps
1
2   module breath_led_tb;
3      
4       reg clk, rst_n;
5       wire led;
6      
7       initial begin
8           clk = 1;
9           rst_n = 0;
10          #200.1
11          rst_n = 1;
12          #50000 $stop;
13      end
14      
15      breath_led
16      #(
17          .T1us(5),
18          .T1ms(10),
19          .T1s(10)
20      )
21      breath_led_dut(
22          .clk(clk),
23          .rst_n(rst_n),
24          .led(led)
25      );
26
27      always #10 clk = ~clk;
28
29  endmodule
 楼主| 星宇 发表于 2017-5-7 23:28:47 | 显示全部楼层
三个计数器的计数方式与我们设计的一致,并且led的占空比也由小到大,再由大到小,一直循环,进行实际下板验证,也实现了呼吸灯的效果。
fpga_wuhan 发表于 2017-5-8 10:41:34 | 显示全部楼层
基于PWM的呼吸灯设计
fpga_feixiang 发表于 2017-5-9 11:51:59 | 显示全部楼层
"""学好FPGA,海阔天空,人生能有几回从事FPGA,天高菜鸟飞,电路任我构,把电路用语言描述出来,综合成逻辑关系,然后在芯片中利用已有的触发器和LUT构成实际电路, 目前来说半定制FPGA芯片主要应用在军工领域较多,一些尖端科技领域,航天航空,以及日常通讯与图像处理算法,复杂工控FPGA也能得到很好应用,这就是FPGA的的本质。
钢铁石油在国家经济发展到一定程度,量就会减少,然后集成电路使用永远都在增加,随着中国的发展,集成电路将越来越发挥巨大作用,FPGA的前景一片大好。
学习技术的过程就是把脑海中的思想用语言表达出来,好的创意是编出好的程序的基石,多多扩大几自己专业知识背景,学习别人好的创意,这是如何学好FPGA的要领。
---札记(飞翔)""      
      
      
      
      
"
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-29 06:12 , Processed in 0.071523 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表