基于PWM的呼吸灯设计
呼吸灯广泛应用于手机之上,并成为各大品牌新款手机的卖点之一。如果手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会在控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸,起到一个通知提醒的作用。 关于呼吸灯设计实现的理论主要是PWM有关知识。PWM(Pluse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。并广泛应用在从测量、通信、功率控制与变换及LED照明等许多领域中。顾名思义,就是占空比可调的信号,那么什么是占空比呢?占空比(Duty Cycle or Duty Ratio),可以解释为,在一脉冲序列中(方波),正脉冲序列的持续时间与脉冲总周期的比值。也可理解为,电路释放能量的有效时间与总释放时间的比值。
PWM是怎样实现调光呢?想要调节LED的亮度变化,实则是调节控制流经LED的电流。电流增大则LED亮度增强,反之减弱。但由于电流为模拟信号,所以这时就用到了PWM。
使用一系列等幅不等宽的脉冲来代替一个正弦波,脉冲的宽度根据正弦波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。可以理解为变化的程度每次递增或者递减千分之一。占空比增时,则实现由暗变亮,将其取反,则可得到占空比减,实现由亮变暗。
在本设计中需要三个计数器,分别为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由暗变亮。 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 cnt_us;//us计数器
10 reg cnt_ms;//ms计数器
11 reg 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
83endmodule
本设计的仿真代码如下:为了便于观察,我们采用参数传递的方式,将参数T1us设为5,T1ms设为10,T1s设为10。 `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
29endmodule
三个计数器的计数方式与我们设计的一致,并且led的占空比也由小到大,再由大到小,一直循环,进行实际下板验证,也实现了呼吸灯的效果。 基于PWM的呼吸灯设计 """学好FPGA,海阔天空,人生能有几回从事FPGA,天高菜鸟飞,电路任我构,把电路用语言描述出来,综合成逻辑关系,然后在芯片中利用已有的触发器和LUT构成实际电路, 目前来说半定制FPGA芯片主要应用在军工领域较多,一些尖端科技领域,航天航空,以及日常通讯与图像处理算法,复杂工控FPGA也能得到很好应用,这就是FPGA的的本质。
钢铁石油在国家经济发展到一定程度,量就会减少,然后集成电路使用永远都在增加,随着中国的发展,集成电路将越来越发挥巨大作用,FPGA的前景一片大好。
学习技术的过程就是把脑海中的思想用语言表达出来,好的创意是编出好的程序的基石,多多扩大几自己专业知识背景,学习别人好的创意,这是如何学好FPGA的要领。
---札记(飞翔)""
"
页:
[1]
2