• 正文
    • 設計背景
    • 設計原理
    • 設計框架
    • 設計代碼
    • 仿真測試
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

源碼系列:基于FPGA的呼吸燈設計(附源工程)

01/16 14:40
1464
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

大俠好,歡迎來到FPGA技術(shù)江湖,江湖偌大,相見即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。

今天給大俠帶來基于FPGA的呼吸燈設計,附源碼,獲取源碼,請在“FPGA技術(shù)江湖”公眾號內(nèi)回復“呼吸燈設計源碼”,可獲取源碼文件。話不多說,上貨。

設計背景

呼吸燈廣泛應用于手機之上,并成為各大品牌新款手機的賣點之一。如果手機里面有未處理的通知,比如說未接來電,未查收的短信等等,呼吸燈就會在控制之下完成由亮到暗的逐漸變化,感覺好像是人在呼吸,起到一個通知提醒的作用。

設計原理

關(guān)于呼吸燈設計實現(xiàn)的理論主要是PWM有關(guān)知識。PWM(Pluse Width Modulation)脈沖寬度調(diào)制,是一種對模擬信號電平進行數(shù)字編碼的方法。通過高分辨率計數(shù)器的使用,方波占空比被調(diào)制用來對一個具體模擬信號的電平進行編碼。并廣泛應用在從測量、通信、功率控制與變換及LED照明等許多領(lǐng)域中。顧名思義,就是占空比可調(diào)的信號,那么什么是占空比呢?

占空比(Duty Cycle or Duty Ratio),可以解釋為,在一脈沖序列中(方波),正脈沖序列的持續(xù)時間與脈沖總周期的比值。也可理解為,電路釋放能量的有效時間與總釋放時間的比值。

PWM是怎樣實現(xiàn)調(diào)光呢?想要調(diào)節(jié)LED的亮度變化,實則是調(diào)節(jié)控制流經(jīng)LED的電流。電流增大則LED亮度增強,反之減弱。但由于電流為模擬信號,所以這時就用到了PWM。正如下圖所示:

使用一系列等幅不等寬的脈沖來代替一個正弦波,脈沖的寬度根據(jù)正弦波a的幅度變化,幅度高,則脈沖寬,反之。

多數(shù)負載需要的PWM調(diào)制頻率都高于10Hz,要想實現(xiàn)呼吸燈的效果,必須提高調(diào)制頻率,通常調(diào)制頻率為1Khz~200Khz之間。在LED控制中PWM作用于電源部分,脈寬調(diào)制的脈沖頻率通常大于100Hz,人眼就不會感到閃爍。這里我們?nèi)WM調(diào)制頻率為1KHz,PWM周期為1ms。

脈沖頻率一定時,輸出脈沖的占空比越大,相當于輸出的有效電平越大,隨著占空比的不同,LED的亮度也將不同。如占空比為0時,則LED不亮,為100%時,則LED最亮,我們讓占空比從0~100%變化,再從100%~0不斷變化,則就可實現(xiàn)呼吸燈效果。

本設計呼吸燈的一個周期為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;    // 產(chǎn)生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;    // 通過在一個周期中加減高低電平的時間來產(chǎn)生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等高電平在不停的增高,然后會降低,通過驗證我們的設計是正確的。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

任何技術(shù)的學習就好比一個江湖,對于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。