赛灵思
直播中

李葛葛

7年用户 163经验值
私信 关注
[问答]

使用PWM控制LED实现呼吸灯的效果

本文主要讲解使用PWM控制LED,实现呼吸灯的效果。

回帖(3)

李兵

2021-1-26 14:45:56
  实验原理
  如下图所示,用一个N比特的计数器,最大值可以表示为2的N次方,最小值0,计数器以“period”为步进值累加,加到最大值后会溢出,进入下一个累加周期。当计数器值大于“duty”时,脉冲输出高,否则输出低,这样就可以完成图中红色线所示的脉冲占空比可调的脉冲输出,同时“period”可以调节脉冲频率,可以理解为计数器的步进值。
  
  PWM脉宽调制示意图
  不同的脉冲占空比的方波输出后加在LED上,LED灯就会显示不同的亮度,通过不断地调节方波的占空比,从而实现LED灯亮度的调节。
举报

李芳

2021-1-26 14:46:47
实验设计

PWM模块设计非常简单,在上面的原理中已经讲到,这里不再说原理。
信号名称方向说明
clkin时钟输入
rstin异步复位输入,高复位
periodinPWM脉宽周期(频率)控制。period = PWM输出频率 * (2 的N次方) / 系统时钟频率。显然N越大,频率精度越高。
dutyin占空比控制,占空比 = duty / (2的N次方)* 100%
  PWM模块(ax_pwm)端口
  `timescale1ns/1ps
  moduleax_pwm
  #(
  parameterN=16//pwmbitwidth
  )
  (
  inputclk,
  inputrst,
  input[N-1:0]period, //pwmstepvalue
  input[N-1:0]duty, //dutyvalue
  outputpwm_out //pwmoutput
  );
  reg[N-1:0]period_r; //periodregister
  reg[N-1:0]duty_r; //dutyregister
  reg[N-1:0]period_cnt; //periodcounter
  regpwm_r;
  assignpwm_out=pwm_r;
  always@(posedgeclkorposedgerst)
  begin
  if(rst==1)
  begin
  period_r《={N{1‘b0}};
  duty_r《={N{1’b0}};
  end
  else
  begin
  period_r《=period;
  duty_r《=duty;
  end
  end
  //periodcounter,stepisperiodvalue
  always@(posedgeclkorposedgerst)
  begin
  if(rst==1)
  period_cnt《={N{1‘b0}};
  else
  period_cnt《=period_cnt+period_r;
  end
  always@(posedgeclkorposedgerst)
  begin
  if(rst==1)
  begin
  pwm_r《=1’b0;
  end
  else
  begin
  if(period_cnt》=duty_r) //ifperiodcounteri***iggerorequalstodutyvalue,thensetpwmvaluetohigh
  pwm_r《=1‘b1;
  else
  pwm_r《=1’b0;
  end
  end
  那么如何实现呼吸灯的效果呢?我们知道呼吸灯效果是由暗不断的变亮,再由亮不断的变暗的过程,而亮暗效果是由占空比来调节的,因此我们主要来控制占空比,也就是控制duty的值。
  在下面的测试代码中,通过设置period的值,设定PWM的频率为200Hz,PWM_PLUS状态即是增加duty值,如果增加到最大值,将pwm_flag置1,并开始将duty值减少,待减少到最小的值,则开始增加duty值,不断循环。其中PWM_GAP状态为调整间隔,时间为100us。
  `timescale1ns/1ps
  modulepwm_test(
  inputclk,//25MHz
  inputrst_n,//lowactive
  outputled//high-off,low-on
  );
  localparamCLK_FREQ=25;//25MHz
  localparamUS_COUNT=CLK_FREQ;//1uscounter
  localparamMS_COUNT=CLK_FREQ*1000;//1mscounter
  localparamDUTY_STEP=32‘d100000;//dutystep
  localparamDUTY_MIN_VALUE=32’h6fffffff;//dutyminimumvalue
  localparamDUTY_MAX_VALUE=32‘hffffffff;//dutymaximumvalue
  localparamIDLE=0;//IDLEstate
  localparamPWM_PLUS=1;//PWMdutyplusstate
  localparamPWM_MINUS=2;//PWMdutyminusstate
  localparamPWM_GAP=3;//PWMdutyadjustmentgap
  wirepwm_out;//pwmoutput
  reg[31:0]period;//pwmstepvalue
  reg[31:0]duty;//dutyvalue
  regpwm_flag;//dutyvalueplusandminusflag,0:plus;1:minus
  reg[3:0]state;
  reg[31:0]timer;//dutyadjustmentcounter
  assignled=~pwm_out;//ledlowactive
  always@(posedgeclkornegedgerst_n)
  begin
  if(rst_n==1’b0)
  begin
  period《=32‘d0;
  timer《=32’d0;
  duty《=32‘d0;
  pwm_flag《=1’b0;
  state《=IDLE;
  end
  else
  case(state)
  IDLE:
  begin
  period《=32‘d17179;//Thepwmstepvalue,pwm200Hz(period=200*2^32/50000000)
  state《=PWM_PLUS;
  duty《=DUTY_MIN_VALUE;
  end
  PWM_PLUS:
  begin
  if(duty》DUTY_MAX_VALUE-DUTY_STEP)//ifdutyi***iggerthanDUTYMAXVALUEminusDUTY_STEP,begintominusdutyvalue
  begin
  pwm_flag《=1’b1;
  duty《=duty-DUTY_STEP;
  end
  else
  begin
  pwm_flag《=1‘b0;
  duty《=duty+DUTY_STEP;
  end
  state《=PWM_GAP;
  end
  PWM_MINUS:
  begin
  if(duty《DUTY_MIN_VALUE+DUTY_STEP)//ifdutyislittlethanDUTYMINVALUEplusdutystep,begintoadddutyvalue
  begin
  pwm_flag《=1’b0;
  duty《=duty+DUTY_STEP;
  end
  else
  begin
  pwm_flag《=1‘b1;
  duty《=duty-DUTY_STEP;
  end
  state《=PWM_GAP;
  end
  PWM_GAP:
  begin
  if(timer》=US_COUNT*100)//adjustmentgapis100us
  begin
  if(pwm_flag)
  state《=PWM_MINUS;
  else
  state《=PWM_PLUS;
  timer《=32’d0;
  end
  else
  begin
  timer《=timer+32‘d1;
  end
  end
  default:
  begin
  state《=IDLE;
  end
  endcase
  end
  //Instantiatepwmmodule
  ax_pwm
  #(
  .N(32)
  )
  ax_pwm_m0(
  .clk(clk),
  .rst(~rst_n),
  .period(period),
  .duty(duty),
  .pwm_out(pwm_out)
  );
  endmodule
举报

王建军

2021-1-26 14:46:59
  下载验证
  生成bitstream,并下载bit文件,可以看到PL LED1灯产生呼吸灯效果。PWM是比较常用的模块,比如风扇转速控制,电机转速控制等等。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分