• 正文
  • 相关推荐
申请入驻 产业图谱

源码系列:基于FPGA的呼吸灯设计(附源工程)

01/16 14:40
1173
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。

今天给大侠带来基于FPGA的呼吸灯设计,附源码,获取源码,请在“FPGA技术江湖”公众号内回复“呼吸灯设计源码”,可获取源码文件。话不多说,上货。

设计背景

呼吸灯广泛应用于手机之上,并成为各大品牌新款手机的卖点之一。如果手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会在控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸,起到一个通知提醒的作用。

设计原理

关于呼吸灯设计实现的理论主要是PWM有关知识。PWM(Pluse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波占空比被调制用来对一个具体模拟信号的电平进行编码。并广泛应用在从测量、通信、功率控制与变换及LED照明等许多领域中。顾名思义,就是占空比可调的信号,那么什么是占空比呢?

占空比(Duty Cycle or Duty Ratio),可以解释为,在一脉冲序列中(方波),正脉冲序列的持续时间与脉冲总周期的比值。也可理解为,电路释放能量的有效时间与总释放时间的比值。

PWM是怎样实现调光呢?想要调节LED的亮度变化,实则是调节控制流经LED的电流。电流增大则LED亮度增强,反之减弱。但由于电流为模拟信号,所以这时就用到了PWM。正如下图所示:

使用一系列等幅不等宽的脉冲来代替一个正弦波,脉冲的宽度根据正弦波a的幅度变化,幅度高,则脉冲宽,反之。

多数负载需要的PWM调制频率都高于10Hz,要想实现呼吸灯的效果,必须提高调制频率,通常调制频率为1Khz~200Khz之间。在LED控制中PWM作用于电源部分,脉宽调制的脉冲频率通常大于100Hz,人眼就不会感到闪烁。这里我们取PWM调制频率为1KHz,PWM周期为1ms。

脉冲频率一定时,输出脉冲的占空比越大,相当于输出的有效电平越大,随着占空比的不同,LED的亮度也将不同。如占空比为0时,则LED不亮,为100%时,则LED最亮,我们让占空比从0~100%变化,再从100%~0不断变化,则就可实现呼吸灯效果。

本设计呼吸灯的一个周期为2s,分为占空比增“吸”和占空比减“呼”两种模式,每个为1s,一个PWM周期为2ms,所以每个模式包含1000个PWM周期,将每个PWM周期分为1000份,即每个时间段2us。

设计框架

设计框架图:50M时钟

设计代码

设计模块huxi_led_state代码:

module huxi_led_state(clk,led,rst_n);  input clk;  input rst_n;    output reg led;    parameter T = 100_000;    localparam s0 = 1'b0;  localparam s1 = 1'b1;    reg [25:0] lw;  reg [25:0] hw;    reg [16:0] count;    // 产生2MS的脉冲  always @(posedge clk or negedge rst_n)    if(!rst_n)      begin        count <= 1'b0;      end    else      begin        if(count == T - 1)          begin            count <= 1'b0;          end        else          begin            count <= count + 1'b1;          end      end        wire flag;  assign flag =(count == T - 1) ? 1'b1:1'b0;    reg state;    // 通过在一个周期中加减高低电平的时间来产生PWM波  always @(posedge clk or negedge rst_n)    if(!rst_n)      begin        lw <= T - 100;        hw <= 100;        state <= 1'b0;      end    else      begin        case (state)          s0:begin              if(flag && (lw > 100))   //判断低电平的时间                begin                  lw <= lw - 100;                  hw <= hw + 100;                  state <= s0;                end              else if(flag && (lw == 100))                begin                  hw <= hw - 100;                  lw <= lw + 100;                  state <= s1;                end              else                begin                  hw <= hw;                  lw <= lw;                  state <= s0;                end            end          s1:begin              if(flag && (hw > 100))   //判断高电平的时间                begin                  hw <= hw - 100;                  lw <= lw + 100;                  state <= s1;                end              else if(flag && (hw ==100))                begin                  hw <= hw + 100;                  lw <= lw - 100;                  state <= s0;                end              else                begin                  hw <= hw;                  lw <= lw;                  state <= s1;                end            end        default : state <= s0;        endcase      end        reg [25:0] cnt;  reg sum;    always @(posedge clk or negedge rst_n)    if(!rst_n)      begin        sum <= 1'b0;        led <= 1'b1;        cnt <= 1'b0;       end    else        case (sum)          s0:begin              if(cnt < hw -1 )                begin                  led <= 1'b0;                  cnt <= cnt + 1'b1;                end              else                begin                  cnt <= 1'b0;                  sum <= s1;                end            end          s1:begin              if(cnt < lw -1)                begin                  led <= 1'b1;                  cnt <= cnt + 1'b1;                end              else                begin                  cnt <= 1'b0;                  sum <= s0;                end            end          default:sum <= s0;        endcase  endmodule 

仿真测试

测试模块代码:

`timescale 1ns/1ps   module huxi_led_state_tb();  reg clk;  reg rst_n;    wire led;    parameter T = 100_000;    initial begin      clk = 1'b1;      rst_n = 1'b0;            #200.1 rst_n = 1'b1;                end        always #10 clk = ~ clk;         huxi_led_state  huxi_led_state_date(          .clk(clk),          .led(led),          .rst_n(rst_n)          );  endmodule 

仿真图:

仿真中可以看到点亮led等高电平在不停的增高,然后会降低,通过验证我们的设计是正确的。

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。