前言
以下思路及代码均为本人学习总结,其中有不妥之处请见谅!若出现bug大家一起探讨!
一、PWM
脉冲宽度调制技术(Pulse Width Modelation,PWM)是利用微处理器/FPGA的数字输出对模拟电路进行控制的一种有效技术,其广泛应用于测量、通信、功率控制与变换等众多领域。PWM数字信号从处理器到被控系统都采用数字形式,无需进行数模转换。通俗来说,PWM是连续的、具有一定比例占空比的脉冲信号,可以通过控制占空比来对其进行改变。简单来说,可以认为PWM就是一种方波。
二、原理
原理:呼吸灯的控制可以通过控制占空比来控制LED灯的亮度。
假设刚开始时占空比为1%,慢慢的占空比为2%、3%、4%.......56%、57%......98%、99%、100%。这就是LED灯亮的一个过程,我们可以让占空比为1%时,令LED灯亮,其余的部分让LED灭,慢慢的占空比越来越大,亮的部分也越来越多,这就是一个由灭到亮的一个过程。
假设刚开始时占空比为100%,慢慢的占空比为99%、98%、97%.....4%、63%.....2%、1%、0%。这就是LED灯灭的一个过程,我们可以让占空比为99%时,令LED灯灭,其余的部分让LED亮,慢慢的占空比越来越小,灭的部分也越来越多,这就是一个由亮到灭的一个过程。
三、时序图
四、代码实现
`timescale 1ns / 1ps
module led_breathe
#
(
parameter TIME_1ms = 50_000,//1ms
parameter TIME_1us = 50 ,//1us 单位:clk
parameter T = 2000 //呼吸灯周期
)
(
input clk ,
input rst_n ,
output reg [3:0] led
);
reg [31:0] ms; //记录ms加了多少次
reg [31:0] us; //记录us加了多少次
reg [31:0] cnt_ms; //记录ms的时间
reg [31:0] cnt_us; //记录us的时间
reg flag;//0灭 1亮
//1ms计时器
always@(posedge clk)
if(!rst_n)
cnt_ms <= 0;
else if(cnt_ms < TIME_1ms)
cnt_ms <= cnt_ms + 1;
else
cnt_ms <= 0;
//ms计数器
always@(posedge clk)
if(!rst_n)
ms <= 0;
else if(cnt_ms == TIME_1ms - 1) begin
if(ms == T - 1)
ms <= 0;
else
ms <= ms + 1;
end
else
ms <= ms;
//1us计时器
always@(posedge clk)
if(!rst_n)
cnt_us <= 0;
else if(cnt_us == TIME_1us - 1)
cnt_us <= 0;
else
cnt_us <= cnt_us + 1;
//us计数器
always@(posedge clk)
if(!rst_n)
us <= 0;
else if(cnt_us == TIME_1us - 1) begin
if(us == T - 1)
us <= 0;
else
us <= us + 1;
end
else
us <= us;
LED输出
always@(posedge clk)
if(!rst_n)
flag <= 0;
else if(cnt_ms == TIME_1ms - 1 && ms == T -1)
flag <= ~flag;
else
flag <= flag;
always@(posedge clk)
if(!rst_n)
led <= 4'b0000;
else if(flag == 0)begin
if(ms > us)
led <= 4'b1111;
else if(ms <= us)
led <=4'b0000;
end
else if(flag == 1)begin
if(ms > us)
led <= 4'b0000;
else if(ms <= us)
led <=4'b1111;
end
endmodule
五、总结
呼吸灯实现方法有多种,本人使用了一种比较便于实现和理解的方式供大家参考。给大家再提供一种状态机写法的状态转换图供大家学习使用。