资讯详情

FPGA—按键控制呼吸灯的时间

呼吸灯和人的呼吸频率一样led灯光熄灭的表现。我们通常看到的基本上是瞬间的开启和关闭。当然,它也有一定的开启和关闭时间,但我们无法用肉眼区分。因此,我们实验的主要困难在于使我们led慢慢变亮,变亮后慢慢变灭。我们看到这一点的第一个想法是控制电流的大小,但在Quartus它似乎不容易实现,所以我们可以改变我们的想法。

这里引入了一个新名词,占空比(DutyCycleorDutyRatio),空比控制又称电控脉宽调制技术。它是通过电子控制单元调添加到工作执行器上的一定频率的电压信号的脉冲宽度,即空比控制,以实现元器件工作条件的准确和连续控制。一般来说,它是指电路连接时间占整个电路工作周期的百分比。例如,如果一个电路在一个工作周期中连接了一半,则其空间占50%。工作元件上的信号电压为5V,则实际的工作电压平均值或电压有效值就是2.5V。假设该元件为电子阀,当电路完全连接时,阀门完全打开;当空间占50%时,阀门状态为半开。同样,当占空比设置为20%时,阀门的开度明显应为20%。这样,阀门可以在0%(全闭)到100%(全开)范围内任意调节。

在此次实验中,我们就可以采用这个原理,假设刚开始时占空比为1%,慢慢的占空比为2%、3%、4%……98%,99%,100%。这就是LED在灯亮的过程中,我们可以让占空比为1%LED灯亮,剩下的让LED灭,慢慢占空比越来越大,亮部也越来越多,这是一个从灭到亮的过程。

相反,我们假设一开始占100%,慢慢占99%、98%、97%……2%,1%,0%。LED在灯灭的过程中,我们可以让占空比达到99%LED灯灭,剩下的让LED亮,慢慢占空比越来越小,灭部也越来越多,这是一个从亮到灭的过程。

这里我们用两个按钮控制led呼吸灯的时间,按键1,让它在一秒钟内从暗变亮,然后从一秒钟内从亮变暗;按键2,让它在三秒钟内从暗变亮,再从三秒钟内从亮变暗。

用三个计数器单独计数,思路是把1s拆分为1000ms,再将1ms拆分为1000us;第一个计数器cnt_us用来实现对us第二个计数器cnt_ms实现对ms计数,第三个计数器cnt_s实现s计数,具体过程可见下面的代码。

4.1 顶层模块

module led_huxi (     input  clk,     input  rst_n,     input  [1:0]  key_in,      output [3:0] led_out );     wire  [1:0]  key_out  ;  key u_key1(     .clk    (clk),     .rst_n  (rst_n),     .key_in (key_in[0]),      .key_out (key_out[0]) );  key u_key2(     .clk    (clk),     .rst_n  (rst_n),     .key_in (key_in[1]),      .key_out(key_out[1]) );  led_control u_led_control(     .clk        (clk    ),     .rst_n      (rst_n  ),     .key_in     (key_out),      .led        (led_out) ); endmodule

4.2 按钮抖动模块,在前面的文章中,不具体介绍。

module key(     input   clk,     input   rst_n,     input   key_in,      output  reg  key_out );  parameter TIME_DELAY = 1_000_000;  reg    [19:0]   cnt       ; wire            add_cnt; wire            end_cnt; wire            nedge     ; reg            cnt_flag  ; reg            key_r0    ; reg            key_r1    ; reg            key_r2    ;  always @(posedge clk or negedge rst_n) begin     if(!rst_n) begin         key_r0 <= 1'd1;         key_r1 <= 1'd1;         key_r2 <= 1'd1;     end      else begin         key_r0 <= key_in;         key_r1 <= key_r0;         key_r2 <= key_r1;     end  end  assign nedge = ~key_r1 && key_r2;  always @(posedge clk or negedge rst_n) begin     if(!rst_n)begin         cnt_flag <= 1'b0;     end      else if (nedge)begin         cnt_flag <= 1'b1;     end     else if (end_cnt)begin         cnt_flag <= 1'b0;     end     else begin         cnt_flag <= cnt_flag;     end  end    always @(posedge clk or negedge rst_n) begin     if(!rst_n)begin         cnt <= 'd0;     end      else if (add_cnt)begin         if (end_cnt) begin             cnt <= 'd0;         end          else begin             cnt <= cnt   1'b1;         end      end  end   assign add_cnt = cnt_flag; assign end_cnt = add_cnt && cnt == TIME_DELAY - 1;  always @(posedge clk or negedge rst_n) begin     if(!rst_n)begin         key_out <= 1'b0;     end      else if(end_cnt)begin         key_out <= ~key_r2;     end      else begin         key_out <= 1'b0;     end  end   endmodule

4.3 占空比的核心代码和led灯的控制模块

module led_control (     input           clk,     input           rst_n,     input   [1:0]   key_in,         output   reg  [3:0 ]  led );  reg     [7:0]  cnt_us  ; wire           add_cnt_us; wire           end_cnt_us;  reg     [9:0]  cnt_ms  ; wire           add_cnt_ms; wire           end_cnt_ms;  reg     [9:0]  cnt_s   ; wire           add_cnt_s; wire           end_cnt_s;  reg            flag; reg     [7:0]  num ; parameter cnt_us_max = 8'd50; parameter cnt_us_max_1 = 8'd150; parameter cnt_ms_max = 10'd999; parameter cnt_s_max  = 10'd999;   //1us always@( posedge clk or negedge rst_n) begin     if(!rst_n)begin         cnt_us <= 8'd0;      end     else if (add_cnt_us) begin         if(end_cnt_us)begin             cnt_us <= 8'd0;         end         else begin            cnt_us <= cnt_us   1'b1;          end     end end  assign  add_cnt_us = 1'b1; assign  end_cnt_us = add_cnt_us && cnt_us == num -1;  //1ms always@( posedge clk or negedge rst_n) begin     if(!rst_n) begin         cnt_ms <= 10'd0;     end     else if (add_cnt_ms)begin         if(end_cnt_ms)begin             cnt_ms <= 10'd0;          end         else begin             cnt_ms <= cnt_ms   1'b1;         end     en
end

assign add_cnt_ms = end_cnt_us;
assign end_cnt_ms = add_cnt_ms && cnt_ms == cnt_ms_max ;

// 1s
always@( posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_s <= 10'd0;
    end
    else if (add_cnt_s)begin
        if(end_cnt_s)begin
            cnt_s <= 10'd0; 
        end
        else begin
        cnt_s <= cnt_s + 1'b1;
        end
    end
end

assign add_cnt_s = end_cnt_ms;
assign end_cnt_s = add_cnt_s && cnt_s == cnt_s_max  ;

//flag标志
always @(posedge clk or negedge rst_n)begin
    if(!rst_n) begin
        flag <= 1'b0;
    end
    else if (cnt_s== cnt_s_max && cnt_us == num-1 && cnt_ms == cnt_ms_max ) begin
        flag <= ~flag;
    end
    else begin
        flag <= flag;  
    end
end

//led
always@( posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        led <= 4'b1111;
    end
    else if ((flag == 1'b1 && cnt_ms < cnt_s)||(flag == 1'b0 && cnt_s < cnt_ms))
	 begin
        led <= 4'b1111;
    end
    else begin
        led <= 4'b0000;
    end
end

//按键
always@( posedge clk or negedge rst_n) begin
    if (!rst_n)begin
        num <= 8'd0;
    end
     else if (key_in[0]==1&&key_in[1]==0) begin
       num <= cnt_us_max ;
     end
    else if (key_in[1]==1&&key_in[0]==0) begin
       num <=  cnt_us_max_1 ;
    end

end
 

endmodule

4.4  视频演示

呼吸灯

 

标签: d150steel连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台