设计背景:
呼吸灯广泛应用于手机之上,并成为各大品牌新款手机的卖点之一。如果手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会在控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸,起到一个通知提醒的作用。
设计原理:
关于呼吸灯设计实现的理论主要是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周期为2ms,所以每个模式包含1000个PWM周期,将每个PWM周期分为1000份,即每个时间段2us。
设计架构图:
时钟50M
设计代码:
设计模块
0 module huxi_led_state(clk,led,rst_n);
1 input clk;
2 input rst_n;
3
4 output reg led;
5
6 parameter T = 100_000;
7
8 localparam s0 = 1'b0;
9 localparam s1 = 1'b1;
10
11 reg [25:0] lw;
12 reg [25:0] hw;
13
14 reg [16:0] count;
15
16 // 产生2MS的脉冲
17 always @(posedge clk or negedge rst_n)
18 if(!rst_n)
19 begin
20 count <= 1'b0;
21 end
22 else
23 begin
24 if(count == T - 1)
25 begin
26 count <= 1'b0;
27 end
28 else
29 begin
30 count <= count + 1'b1;
31 end
32 end
33
34 wire flag;
35 assign flag =(count == T - 1) ? 1'b1:1'b0;
36
37 reg state;
38
39 // 通过在一个周期中加减高低电平的时间来产生PWM波
40 always @(posedge clk or negedge rst_n)
41 if(!rst_n)
42 begin
43 lw <= T - 100;
44 hw <= 100;
45 state <= 1'b0;
46 end
47 else
48 begin
49 case (state)
50 s0:begin
51 if(flag && (lw > 100)) //判断低电平的时间
52 begin
53 lw <= lw - 100;
54 hw <= hw + 100;
55 state <= s0;
56 end
57 else if(flag && (lw == 100))
58 begin
59 hw <= hw - 100;
60 lw <= lw + 100;
61 state <= s1;
62 end
63 else
64 begin
65 hw <= hw;
66 lw <= lw;
67 state <= s0;
68 end
69 end
70 s1:begin
71 if(flag && (hw > 100)) //判断高电平的时间
72 begin
73 hw <= hw - 100;
74 lw <= lw + 100;
75 state <= s1;
76 end
77 else if(flag && (hw ==100))
78 begin
79 hw <= hw + 100;
80 lw <= lw - 100;
81 state <= s0;
82 end
83 else
84 begin
85 hw <= hw;
86 lw <= lw;
87 state <= s1;
88 end
89 end
90 default : state <= s0;
91 endcase
92 end
93
94 reg [25:0] cnt;
95 reg sum;
96
97 //分频模块,产生不同占空比的LED亮的时间
98 always @(posedge clk or negedge rst_n)
99 if(!rst_n)
100 begin
101 sum <= 1'b0;
102 led <= 1'b1;
103 cnt <= 1'b0;
104 end
105 else
106 case (sum)
107 s0:begin
108 if(cnt < hw -1 ) //高电平的时间
109 begin
110 led <= 1'b0;
111 cnt <= cnt + 1'b1;
112 end
113 else
114 begin
115 cnt <= 1'b0;
116 sum <= s1;
117 end
118 end
119 s1:begin
120 if(cnt < lw -1) //低电平的时间
121 begin
122 led <= 1'b1;
123 cnt <= cnt + 1'b1;
124 end
125 else
126 begin
127 cnt <= 1'b0;
128 sum <= s0;
129 end
130 end
131 default:sum <= s0;
132 endcase
133
134 endmodule
测试模块
0 `timescale 1ns/1ps
1 module huxi_led_state_tb();
2 reg clk;
3 reg rst_n;
4
5 wire led;
6
7 parameter T = 100_000;
8
9 initial begin
10 clk = 1'b1;
11 rst_n = 1'b0;
12
13 #200.1 rst_n = 1'b1;
14
15
16 end
17
18 always #10 clk = ~ clk;
19
20
21
22 huxi_led_state huxi_led_state_date( //例化设计
23 .clk(clk),
24 .led(led),
25 .rst_n(rst_n)
26 );
27 endmodule
仿真图:
仿真中可以看到点亮led等高电平在不停的增高,然后会降低,通过验证我们的设计是正确的。
全部0条评论
快来发表一下你的评论吧 !