按键控制led变化

按键控制led变化

一、简介

使用按键控制开发板上一个led灯的亮灭,当按键按下的时候led灯就亮,当再一次按下按键的时候led就不亮了。由于按键存在抖动,按键松开的时候led灯就不亮,所以需要一个消抖模块对按键消抖

二、代码

module key_led (
    input wire clk,
    input wire rst_n,
    input wire[3:0] key,
     
    output reg[3:0] led
);
parameter TIME_0_2S = 10_000_000;  //
reg[24:0] cnt_0_2S;
reg[1:0] state;
//=================0.2s计时====================//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_0_2S<=24'd0;
    end
    else if(cnt_0_2S == TIME_0_2S - 1)begin
        cnt_0_2S<=24'd0;
    end
    else begin
        cnt_0_2S<=cnt_0_2S+1'b1;
    end
end


//=================state=================//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        state<=2'b00;
    end
    else if(cnt_0_2S == TIME_0_2S - 1) begin
        state<=state+1'b1;
    end
    else begin
        state<=state;
    end
end
//================按键控制流水灯===============//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        led<=4'b0000;
    end
    else if(~key[0]) begin
        case (state)
            2'd0:led<=4'b0001;
            2'd1:led<=4'b0010;
            2'd2:led<=4'b0100;
            2'd3:led<=4'b1000;
        endcase
    end
    else if(~key[1]) begin
        case (state)
            2'd0:led<=4'b1000;
            2'd1:led<=4'b0100;
            2'd2:led<=4'b0010;
            2'd3:led<=4'b0001;
        endcase
    end
    else if(~key[2]) begin
        case (state)
            2'd0:led<=4'b1111;
            2'd1:led<=4'b0000;
            2'd2:led<=4'b1111;
            2'd3:led<=4'b0000;
        endcase
    end
    else if(~key[3]) begin
        case (state)
            2'd0:led<=4'b1111;
            2'd1:led<=4'b1111;
            2'd2:led<=4'b1111;
            2'd3:led<=4'b1111;
        endcase
    end
    else begin
        led<=4'b0000;
    end
end

endmodule
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : 辣子鸡味的句橘子,331197689@qq.com
// File   : key_debounce.v
// Create : 2023-07-14 10:36:44
// Revise : 2023-07-14 10:36:44
// Editor : sublime text4, tab size (4)
// -----------------------------------------------------------------------------
module key_debounce(
    input wire clk,
    input wire rst_n,
    input wire[3:0] key_in,//四个按键信号输入

    output reg[3:0] key_out//四个按键信号消抖输出
);

parameter TIME_20MS = 1000_000;
reg[19:0] cnt;//20ms计数器
wire add_cnt;//计数开始
wire ent_cnt;//计数终止
wire nedge;//下降沿检测

reg[3:0] key_in_r0;//同步key_in输入信号
reg[3:0] key_in_r1;//延迟一个周期
reg[3:0] key_in_r2;//延迟两个周期

reg flag;//消抖开始标志信号

//计数器模块,当addent满足时开始计数,检测到下降沿重新计数,end_ent满足时停止计数,消抖完成
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt<=20'd0;
    end
    else if(add_cnt)begin
        if(ent_cnt)begin
            cnt<=20'd0;
        end
        else if(nedge)begin
            cnt<=20'd0;
        end
        else begin
            cnt<=cnt+1;
        end
    end
    else begin
        cnt<=cnt;
    end
end

assign add_cnt = flag;//计数开始条件
assign end_cnt = (cnt == TIME_20MS - 1)&&add_cnt;//终止结束条件,当满足计时到20ms,且满足计时条件时成立

//信号延时模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        key_in_r0<=4'b1111;
        key_in_r1<=4'b1111;
        key_in_r2<=4'b1111;
    end
    else begin
        key_in_r0<=key_in;
        key_in_r1<=key_in_r0;
        key_in_r2<=key_in_r1;
    end
end

//检测下降沿,当任意一个按键出现下降沿都会被检测到
assign nedge = (~key_in_r1[0]&key_in_r2[0])||(~key_in_r1[1]&key_in_r2[1])||(~key_in_r1[2]&key_in_r2[2])||(~key_in_r1[3]&key_in_r2[3]);

//消抖开始模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       flag<=1'b0;
    end
    else if(nedge)begin//当出现下降沿开始消抖
        flag<=1'b1;
    end
    else if(end_cnt)begin//当end_cnt满足时停止消抖
        flag<=1'b0;
    end
    else begin
        flag<=flag;
    end
end

//输出信号赋值模块,当消抖完毕标志按键按下,出现一个脉冲信号表示按键按下
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       key_out<=4'b1111;//默认为高电瓶
    end
    else if(end_cnt)begin
        key_out<=key_in;//稳定信号赋值
    end
    else begin
       key_out<=4'b1111;//其他信号默认为高电平
    end
end

endmodule
module key_top(
    input wire clk,
    input wire rst_n,
    input wire[3:0] key,

    output wire[3:0] led
);
wire[3:0] key_r;

key_debounce inst_key_debounce (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key), 
	.key_r(key_r));
key_led inst_key_led (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key_r), 
	.led(led));

endmodule

三、仿真代码

module key_top_tb();
reg clk;
reg rst_n;
reg[3:0] key;
wire[3:0] led;
wire[3:0] key_r;

parameter SYS_CLK = 20;
parameter TIME = 100;
always #(SYS_CLK/2) clk = ~clk;
initial begin
	clk=1'b0;
	rst_n=1'b0;
	#(2*SYS_CLK);
	rst_n=1'b1;
	key = 4'b1111;
	#(2*SYS_CLK);
	repeat (19) begin
   		key[0] = ~key[0];
   		#(2*SYS_CLK);
	end
	key[0] = 1'b0;
	#(400*SYS_CLK);
	$stop;
end
key_debounce #(.TIME_20MS(TIME)) inst_key_bounce (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key), 
	.key_r(key_r));

key_led #(.TIME_0_2S(TIME)) inst_key_led (
	.clk(clk), 
	.rstn(rstn), 
	.key(key), 
	.led(led));


endmodule

四、仿真结果

在这里插入图片描述

五、总结

总的来说编写不算复杂,需要注意的是模块之间的连接和按键消抖模块

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以通过以下步骤实现51单片机按键控制LED: 1. 首先需要连接一个LED和一个按键到51单片机,LED的正极连接到P1口的一个引脚,按键通过一个上拉电阻连接到另一个P1口引脚,按键的另一个端口连接到地。 2. 在51单片机的程序中,需要定义P1口的引脚为输入输出模式。可以使用P1 = 0x00;语句将P1口所有引脚设置为输出模式,或者使用P1 = 0xff;语句将所有引脚设置为输入模式。 3. 在程序中,需要不断地检测按键的状态,可以使用while循环实现。如果按键被按下,对应的P1口的引脚会被拉低,程序需要检测到这个状态并执行相应的操作。 4. 如果按键被按下,LED需要亮起,可以使用P1口的引脚输出高电平来实现。如果按键没有被按下,LED需要灭,可以使用P1口的引脚输出低电平来实现。 以下是一个简单的51单片机按键控制LED的程序示例: ``` #include<reg52.h> sbit led = P1^0; sbit button = P1^1; void main() { while(1) { if(button == 0) //检测按键状态 { led = 1; //按键被按下,LED亮起 } else { led = 0; //按键没有被按下,LED灭 } } } ``` 需要注意的是,以上示例程序仅为演示51单片机按键控制LED的基本原理,实际应用中还需要考虑去抖动、延时等问题。 ### 回答2: 51单片机按键控制led是一种常见的嵌入式系统应用。在这个方案中,使用人们熟悉的按键作为输入设备,通过对按键的状态变化进行检测,进而控制led灯的亮灭。 首先需要了解51单片机的硬件接口。通常,按键与单片机的某个IO口相连,通过io口来检测按键的状态。当按键按下时,io口会检测到一个低电平;当按键松开时,io口会检测到一个高电平。这样,可以通过检测io口的高低电平变化来判断按键的状态。 接下来,需要在代码中编写相应的按键检测逻辑。可以使用循环方式检测io口的电平变化,如果检测到io口的电平从高变低,表示按键被按下;如果检测到io口的电平从低变高,表示按键被松开。根据按键的状态变化,可以执行相应的操作。 最后,利用51单片机的另一个io口,控制led灯的亮灭。当按键按下时,将此io口的电平置为低电平,led灯亮起;当按键松开时,将此io口的电平置为高电平,led灯熄灭。 该方案的实现考验了编程和硬件电路的结合能力。通过编写相应的代码和连接合适的硬件电路,可以实现按键控制led灯的功能。这种方案在嵌入式系统中有广泛应用,例如电子钟、电子秤、电子温度计等,为用户提供了方便和灵活的操作方式。 ### 回答3: 51单片机是一种常见的单片机,具有广泛的应用。按键控制LED是其中一种常见的应用场景。 在这个应用中,我们通常会使用一个或多个按键,通过按下不同的按键控制LED的开关状态。首先需要将按键接入到单片机的IO口上,并设置为输入模式。然后,通过编写程序,在程序中不断检测这个IO口的电平状态,当按键被按下时,IO口的电平状态会发生变化。通过判断电平状态的变化,我们可以确定按键是否被按下。 一旦检测到按键被按下,我们可以在程序中相应的控制LED的开关状态。可以通过一个变量来表示LED的状态,比如0表示LED灭,1表示LED亮。当按键被按下时,通过改变LED状态的变量的值,从而改变LED的开关。 具体实现的步骤包括: 1. 将按键接入到单片机的IO口,并设置为输入模式。 2. 编写程序,在主循环中不断检测IO口的电平状态。 3. 当检测到按键被按下时,改变LED状态的变量的值,从而改变LED的开关。 4. 根据LED状态的变量的值,通过控制IO口的电平状态,来控制LED的开关。 5. 可以使用延时函数来实现LED的闪烁效果,比如每隔一定的时间,改变LED状态的变量的值,从而实现LED的闪烁。 通过以上的步骤,我们可以实现51单片机按键控制LED的功能。这种应用具有简单、灵活、实用的特点,可以在很多电子产品中看到它的身影,比如电子钟、电子玩具等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值