FPGA学习系列:15. 呼吸灯(pwm)设计

描述

设计背景:

    呼吸灯广泛应用于手机之上,并成为各大品牌新款手机的卖点之一。如果手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会在控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸起到一个通知提醒的作用。

 

设计原理: 

    关于呼吸灯设计实现的理论主要是PWM有关知识。PWMPluse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。并广泛应用在从测量、通信、功率控制与变换及LED照明等许多领域中。顾名思义,就是占空比可调的信号,那么什么是占空比呢?

    占空比(Duty Cycle or Duty Ratio),可以解释为,在一脉冲序列中(方波),正脉冲序列的持续时间与脉冲总周期的比值。也可理解为,电路释放能量的有效时间与总释放时间的比值。

    PWM是怎样实现调光呢?想要调节LED的亮度变化,实则是调节控制流经LED的电流。电流增大则LED亮度增强,反之减弱。但由于电流为模拟信号,所以这时就用到了PWM。正如下图所示:

    FPGA

    使用一系列等幅不等宽的脉冲来代替一个正弦波,脉冲的宽度根据正弦波a的幅度变化,幅度高,则脉冲宽,反之。    

    多数负载需要的PWM调制频率都高于10Hz,要想实现呼吸灯的效果必须提高调制频率,通常调制频率为1Khz~200Khz之间。在LED控制中PWM作用于电源部分,脉宽调制的脉冲频率通常大于100Hz,人眼就不会感到闪烁。这里我们取PWM调制频率为1KHzPWM周期为1ms

    脉冲频率一定时,输出脉冲的占空比越大,相当于输出的有效电平越大,随着占空比的不同,LED的亮度也将不同。如占空比为0时,则LED不亮,为100%时,则LED最量,我们让占空比从0~100%变化,再从100%~0不断变化,则就可实现呼吸灯效果。

    本设计呼吸灯的一个周期为2s,分为占空比增“吸”和占空比减“呼”两种模式,每个为1s,一个PWM周期为2ms,所以每个模式包含1000PWM周期,将每个PWM周期分为1000份,即每个时间段2us

 

设计架构图:

    时钟50M

    FPGA

设计代码:

设计模块

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 

 

仿真图:

FPGA


    

    仿真中可以看到点亮led等高电平在不停的增高,然后会降低,通过验证我们的设计是正确的。


 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分