脉冲宽度调制(PWM)——以呼吸灯项目为例

一、PWM简介

        PWM(Pulse Width Modulation,脉冲宽度调制)是一种用于控制模拟信号的数字技术。它通过改变脉冲信号的宽度来表示模拟信号的幅度。PWM常用于电子设备中,如电机驱动、LED调光、音频放大器等应用。

        他的基本原理是产生一系列脉冲信号,其宽度(脉冲持续时间)可以调整。通常,PWM信号是由一个固定频率的周期性脉冲和一个可变的占空比组成。

        频率:在1秒钟内,信号从高电平到低电平再回到高电平的次数。

        占空比:指在一个脉冲周期内,高电平的时间占整个周期时间的比例。

        脉冲宽度:在一个脉冲周期内,信号高电平所占的时间。

二、呼吸灯项目

        呼吸灯是一种特殊的 LED 灯效果,模拟人类呼吸的渐变效果。这种效果通常通过改变 LED 的亮度来实现,使得灯光在周期性的增强和减弱之间变化,就像人类呼吸时胸腔的起伏一样。本文使用PWM方法,编写适当的算法来调整 PWM 信号的占空比,从而实现呼吸灯效果的时间变化。当占空比越高时,LED灯越亮。实现原理框图如下所示。

        主要包括计数器和占空比调节部分。设一个完整的呼吸周期为100ms,设置两个计数器cnt和duty_cycle(占空比),当cnt计数到5_000_000时(也就是100ms),占空比变化一次。duty_cycle=duty_cycle+25(duty_cycle的自增可以根据需要调整)。当duty_cycle增加到5_000_000时,将其重新置零。于是当cnt>duty_cycle时,我们让LED灯亮,这样随着duty_cycle的增加LED的亮度就会逐渐减弱。assign led = (cnt > duty_cycle) ? 1'b1 : 1'b0; 

        同时还需要考虑到呼吸灯变亮的情况,因此引入inc_dec,当inc_dec为1时,占空比增加,呼吸灯逐渐变亮,为0时,占空比减少,呼吸灯逐渐变暗。在每一个呼吸周期结束后,也即cnt增加到5_000_000时,inc_dec翻转。

        实现代码如下:

module breath_led(

input sys_clk  ,
input sys_rst_n,

output wire led     
);

reg [19:0] cnt       ;
reg [19:0] duty_cycle;
reg        inc_dec   ;//inc_dec为1时,占空比增加,为0时,占空比减少
wire       add_cnt   ;
wire       end_cnt   ;

//计数器
always @(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		cnt <= 20'd0;
	else if(add_cnt)
		if(end_cnt)
			cnt <= 20'd0;
		else
			cnt <= cnt+1'b1;
end
assign add_cnt = (cnt != 20'd5_000_000) ? 1'b1 : 1'b0;
assign end_cnt = (cnt == 20'd5_000_000) ? 1'b1 : 1'b0;

//PWM实现
always @(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		duty_cycle <= 20'd0;
		inc_dec    <= 1'b0 ;
	end
	else begin
		if(cnt == 20'd5_000_000)
			begin
				if(inc_dec == 1'b1)begin
					if (duty_cycle == 20'd5_000_000)
						inc_dec <= 1'b0;
					else 
						inc_dec <= inc_dec;
						duty_cycle <= duty_cycle + 16'd50;
				end
				else begin
					if(duty_cycle == 20'd0)
						inc_dec <= 1'b1;
					else 
						inc_dec <= inc_dec;
						duty_cycle <= duty_cycle - 16'd50;
			    end 
			end 
	end
end 

//对LED灯赋值
assign led = (cnt > duty_cycle) ? 1'b1 : 1'b0; 

endmodule

        当cnt计到5_000_000(100ms)时,inc_dec=1占空比呈递增状态,如果占空比已经增加到最大值(5_000_000),则inc_dec=0,让其变为递减状态,否则占空比以50为单位递增;inc_dec=0时,占空比呈递减状态,如果占空比已递减到0,则inc_dec=1,让其变为递增状态,否则以50为单位递减。

        测试代码如下:

`timescale 1 ns/ 1 ps
module breath_led_vlg_tst();
reg sys_clk;
reg sys_rst_n;
                                            
wire led;
                       
breath_led i1 (
	.led(led),
	.sys_clk(sys_clk),
	.sys_rst_n(sys_rst_n)
);
initial  begin
	sys_clk       = 1'b0;
	sys_rst_n     = 1'b0;                                            
    
	#80 sys_rst_n = 1'b1;

                    
end                                                    
always #10 sys_clk = ~sys_clk;                                              
                                                                         
endmodule

        为了方便看仿真波形,cnt最大值设为50,duty_cycle每次自增5,波形图如下:

三、QuartusII与ModelSim联合仿真

        在联合仿真之前需要将仿真工具设置为ModelSim。

        assignment——settings——Simulations,将Tool name设为ModelSim,地址指向ModelSim下载地址中的win64,Complie中找到test bench文件,然后点击Apply,OK。

        点击Tools——options——EDA Tool Options,同样将地址指向ModelSim下载地址中的win64。

        然后点击Tools——Run Simulation Tool——RTL Simulation,就可以调出ModelSim直接看到波形图了。

##本文参考正点原子视频,如有侵权,请联系删除。

  • 15
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值