当前位置:   article > 正文

ZYNQ学习笔记(六)---呼吸灯实验_呼吸灯占空比怎么变化效果最好

呼吸灯占空比怎么变化效果最好

这两天做了呼吸灯实验,今天和大家分享一下。我们采用PWM脉冲宽度调制输出连续的、占空比变化的脉冲信号来实现LED由灭到亮,再由亮到灭。

1.呼吸灯的原理

首先我们要知道,影响呼吸灯亮灭有2个因素:1.PWM波的占空比;2.PWM波的周期。

需要两者配合,方能实现效果较佳的呼吸灯。

我们假设占空比为50%,周期为2s,那么我们看到的就是LED亮一秒,灭一秒。但是如果我们把周期缩小到10ms,占空比仍然是50%。由于人眼的视觉残留效应,那么我们看见的就是LED的亮度会低一些,并不会出现亮一会灭一会的情况。

所以,根据上述分析,我们可以把PWM波的周期缩小到一个很小的值(比如10ms),然后让占空比每个周期都产生变化。(比如:从灭到亮时,每10ms占空比增加1%,增加到100%时再每10ms占空比减小1%,实现从亮到灭。这样整个亮灭过所需时间就是2s=10ms*100+10ms*100。)

2.源文件

首先我们需要两个计数器,一个10ms计数,另一个其实只要统计10ms的次数,200次就是2s。

然后因为在1s时我们需要将状态从灭到亮改为从亮到灭,所以我们需要一个用来切换状态的标志位及相应代码。

剩下就是占空比的调节和pwm的输出。

占空比在相应状态下,通过每次步进5000的计数值来每10ms改变一次1%的占空比;另外,我们要注意到PWM的信号输出应该和10ms计数器同步,10ms计数值小于dutycycle时,pwm输出0。反之,输出1。

  1. `timescale 1ns / 1ps
  2. module BreathLed(clk,rst_n,led);
  3. input wire clk;
  4. input wire rst_n;
  5. output wire led;
  6. //定义一些常量,时钟主频50M,计满10ms需要计数50_0000次,计数满2s,只要重复200次即可
  7. parameter CLK_10ms = 500000-1;
  8. parameter Times_2s = 200-1;
  9. parameter ChangeTime =100-1;
  10. //每次占空比改变整个周期的1%,0.01*500000
  11. parameter pwm_offset = 5000;
  12. //需要两个计数器,一个工作状态改变标志位
  13. reg [19:0] CLK_10MS;
  14. reg [7:0] Times2s;
  15. reg pwm;
  16. reg [19:0] dutyCycle;
  17. reg changeflag;
  18. assign led = ~pwm;
  19. /*--------10ms计数器---*/
  20. always @(posedge clk or negedge rst_n)
  21. begin
  22. if(rst_n==1'b0)
  23. begin
  24. CLK_10MS <='d0;
  25. end
  26. else if(CLK_10MS==CLK_10ms) CLK_10MS <='d0;
  27. else begin
  28. CLK_10MS <= CLK_10MS+1'b1;
  29. end
  30. end
  31. /*-----2s计数器----*/
  32. always @(posedge clk or negedge rst_n)
  33. begin
  34. if(rst_n==1'b0) Times2s <='d0;
  35. else if(CLK_10MS==CLK_10ms)begin
  36. if(Times2s==Times_2s) Times2s <='d0;
  37. else Times2s <= Times2s+1'b1;
  38. end
  39. end
  40. //-------亮灭状态管理切换----
  41. always @(posedge clk or negedge rst_n)
  42. begin
  43. if(rst_n==1'b0)
  44. changeflag <= 'b0;
  45. else if(Times2s==ChangeTime && CLK_10MS==CLK_10ms)
  46. begin
  47. changeflag <= 1'b1;//状态改为:从亮到灭
  48. end
  49. else if(Times2s==Times_2s && CLK_10MS==CLK_10ms)
  50. begin
  51. changeflag <= 1'b0;//状态改为:从灭到亮
  52. end
  53. end
  54. //-----占空比调节
  55. always @(posedge clk or negedge rst_n)
  56. begin
  57. if(rst_n==1'b0)dutyCycle='d0;
  58. else if(changeflag==1'b0)
  59. begin
  60. if(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle+pwm_offset;
  61. else dutyCycle <= dutyCycle;
  62. end
  63. else if(changeflag ==1'b1)
  64. begin
  65. if(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle-pwm_offset;
  66. else dutyCycle <= dutyCycle;
  67. end
  68. end
  69. always @(posedge clk or negedge rst_n)
  70. begin
  71. if(rst_n==1'b0) pwm <= 1'b0;
  72. else if(CLK_10MS < dutyCycle) pwm <= 1'b0;
  73. else pwm <= 1'b1;
  74. end
  75. endmodule

3.Testbench代码

  1. /*-------testbench编写基本流程------*/
  2. //* module Test_bench();
  3. //通常无输入出 通常无输入出
  4. //信号或变量声明定义
  5. //逻辑设计中输入对应 reg型
  6. //逻辑设计中输出对应 wire 型
  7. //使用 initial 或 always语句产生激励 语句产生激励
  8. //例化待测试模块
  9. //监控和比较输出响应
  10. //
  11. module BreathLed_simul();
  12. //变量和信号的声明
  13. reg clk;
  14. reg rst_n;
  15. wire led;
  16. parameter CLK_10ms = 500000-1;
  17. parameter Times_2s = 200-1;
  18. parameter ChangeTime =100-1;
  19. //每次占空比改变整个周期的1%,0.01*500000
  20. parameter pwm_offset = 5000;
  21. //例化一个我们之前写的模块
  22. BreathLed #(.CLK_10ms(CLK_10ms),
  23. .Times_2s(Times_2s),
  24. .ChangeTime(ChangeTime),
  25. .pwm_offset(pwm_offset))
  26. u1(
  27. .clk(clk),
  28. .rst_n(rst_n),
  29. .led(led)
  30. );
  31. initial
  32. begin
  33. //初始化激励(时钟和复位信号)
  34. clk=1'b0;
  35. rst_n=1'b0;
  36. #10
  37. rst_n=1'b1;
  38. end
  39. always #(10) clk=~clk;
  40. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/791241
推荐阅读
  

闽ICP备14008679号