> 文档中心 > 利用PWM原理实现调光灯

利用PWM原理实现调光灯

一、PWM原理
PWM(Pulse Width Modulation)即脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种技术。PWM是一种对模拟信号电平进行数字编码的方法。通过使用高分辨率计数器,对方波的占空比进行调制,从而对一个具体模拟信号的电平进行编码。
二、设计思想
本实验利用pynq-z2平台,要求对led灯实现4挡亮度,同时4个led灯要顺序流转起来。led灯只有高低电平2个挡位,如何实现led的4挡亮度呢?可以想到利用pwm技术,对信号周期的占空比进行控制,从而对电平编码,实现4挡亮度控制。
假设周期为1ms,则4挡亮度占空比分别为250us、500us、750us和1000us。定义一个2位计数器cnt1ms对4种状态进行编码。
在这里插入图片描述
此时已经实现led灯的4挡亮度。那么下面如何实现led灯的流转呢。定义一个每1s的计数器cnt,每过1秒led灯的状态变化一次,4s是一个周期。4个led灯的状态表如下所示。
在这里插入图片描述
根据状态表,对每个led灯的每个cnt时刻亮度挡位状态进行一一对应,即可实现led灯的流转。模块示意图如下所示。
在这里插入图片描述三、代码实现
设计代码如下所示。

modulepwm(inputsclk,inputs_rst,outputreg  [ 3:0]led);localparamDELAY_250US='d31249;localparamDELAY_1MS='d3;localparamDELAY_1S='d999;reg[ 14:0]cnt_250us;  reg[ 1:0]cnt_1ms;reg     [ 9:0]   cnt_1s      ; //1s的计数器reg[ 1:0]cnt;//1s的计数器,共4salways@(posedge sclk or posedge s_rst) begin //250us 计数器if(s_rst == 1'b1)  cnt_250us <='d0;else if(cnt_250us == DELAY_250US)cnt_250us <='d0;elsecnt_250us <=cnt_250us + 1'b1;endalways@(posedge sclk or posedge s_rst) begin  //1ms 计数器if(s_rst == 1'b1)  cnt_1ms <='d0;else if(cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1ms <='d0;else if(cnt_250us == DELAY_250US)cnt_1ms <=cnt_1ms + 1'b1;endalways @(posedge sclk or posedge s_rst)//1s 计数器beginif(s_rst == 1'b1)cnt_1s <= 10'd0  ;else if(cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1s <= 10'd0  ;else if(cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1s <= cnt_1s + 1'b1  ;end//计数器cntalways @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)cnt <= 2'd0  ;else if(cnt == 2'd3 && cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt <= 2'd0  ;else if(cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt <= cnt + 1'b1  ;end//led0always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[0] <= 1'b0     ;else if(cnt == 0 )   //cnt == 0 时,亮度1beginif (cnt_1ms == 2'b00)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelseled[0] <= 1'b0     ;end//led1always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[1] <= 1'b0     ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 3)   beginif (cnt_1ms == 2'b00)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelseled[1] <= 1'b0     ;end//led2always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[2] <= 1'b0     ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 2)   beginif (cnt_1ms == 2'b00)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelseled[2] <= 1'b0     ;end//led3always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[3] <= 1'b0     ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 1)   beginif (cnt_1ms == 2'b00)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelseled[3] <= 1'b0     ;endendmodule

测试代码如下所示。

`timescale1ns/1nsmodule tb_pwm;regsclk;regs_rst;wire [3:0]  led;initial beginsclk =1;s_rst <= 1 ;#100s_rst <= 0 ;endalways  #4sclk = ~sclk ;pwmpwm_inst(.sclk(sclk),.s_rst    (s_rst    ),reset, active low.led(led));endmodule

四、实验结果
利用testbench仿真的结果如下所示:
在这里插入图片描述
实验结果如下所示:
在这里插入图片描述