基于FPGA的按键控制LED的循环左移一位

一:背景介绍

今天早上开工,将按键控制LED的循环左移一位,这一功能实现了一把,这是一个基础功能,我想要的最终实现方式是:状态机FSM;

进阶版本是:状态机通过按键控制其条件的转变,实现多个功能的轮流展示

说到按键电路,大家脑海里首先反应出的就是:按键消抖;



二:知识问答

我想问几个问题:

1)按键消抖有几种方法呢?

两种

2)哪两种呢?

硬件方法 + 软件方法;

3)软件方法如何实现呢?

避过按键的抖动时间

4)按键的抖动期是多长?

5ms~~10ms(网络给出的,其实也差不多了,10ms的抖动期,一般课题,都可以正确实现)


三:思路解析

说到消抖,单片机里已经给出了方法,也就是:如果监测到按键按下(按键出现低电平),跳过10ms的抖动期,然后再检测,是否仍然为低电平,如果是,那就是真的按下了;

那么FPGA呢,是不是也是这种方法?

也可以这样做的,没有问题的,但是使用FPGA延时,需要注意的是:当按键按下后,会不会多次操作某一功能;这是关键,切记;

我推荐的是另一种方法;计数停止法。

核心思想:

如果监测到按键按下(按键出现低电平),那么就开始计数,如果计数到10ms时,仍然为0,则确定为:按键按下,计数停止

如果监测到按键未按下,或者,按键松开,计数值清零,然后一直计数,知道计满10ms为止。


四:框图

在此简略,稍后附上


五:小结

循环左移是一个简单地 实验,添加了按键消抖,在简单里加点料。

我现在还没有尝试使用状态机,写出描述语句,我的打算是:等所有课题或者项目的语句,描述了清楚后再用状态机;

简单铸就雄伟

我先将目前学习过的知识进行一个汇总,然后再逐个提升,简单心思,如此而已;

什么都想做,什么都想一步到位,那是牛人干的事情,作为一个普通人士,我选择逐层提升;

不要瞧不上,LED灯循环左移之类的,举3个例子:串口DB9,使用串行数据传输;SPI,使用串行数据传输;IIC,使用串行数据传输,数据需要移动,左移和右移是不是就用上 了。

大项目也是是由诸多的小项目汇总而成,小项目都还没用搞定,大项目也只能望海兴叹.。

就写这么多的,没法口吐莲花,简单的东西都能讲出花,就此搁笔,与诸君分享。


六:程序

//======================================//
//==Fosc		:	50MHz
//==Timescale   :	1ns/1ns
//==File name   :	huxideng.v
//==Date		:	2016-09-28
//==Author      :	CY
//==Function	:	每按键一次,一个LED灯循环亮灭
//==Description:
//	当没有按键 按下时,flag—_10ms=1'b0;
//	当有   按键 按下时,flag_10ms=1'b1;
//	
//======================================//
module	key_new(
	input		wire			sclk,
	input		wire			rst_n,
	input		wire			key_in,
	
	output		reg			key_value
	);
	
	//==========================//
	parameter	T_10ms=19'd499_999;
	//==========================//
	reg	[18:0]	cnt_10ms;
	reg			flag_10ms;
	
	//==========cnt_10ms==========//
	always@(posedge	sclk	or	negedge	rst_n)
		if(!rst_n)
			cnt_10ms	<=19'd0;
		else	if(key_in==1'b1) 	 //没有这一句,意味着是可以累积计数的,如此会出现,即使遇到1就停止计数,一旦监测到0就会累加计数;
			cnt_10ms	<=19'd0;	//我们实际需要的是:key_in=1时,清零,遇到0时就累积加,所以,必须要添加此句		
		else	if(cnt_10ms==T_10ms)	//为的是cnt_10ms>T_10ms,如此就不会执行	cnt_10ms	<=cnt_10ms+1'b1;
			cnt_10ms	<=19'd500_000;
//		else	if(key_in==1'b0)	//
		else	if(key_in==1'b0&&cnt_10ms<=T_10ms)	//目的 是:计数T_10ms+1'b1之后,就不加1
			cnt_10ms	<=cnt_10ms+1'b1;
			
	//==========flag_10ms========//		
	always@(posedge	sclk	or	negedge	rst_n)
		if(!rst_n)
			flag_10ms	<=1'b0;		//因为key_value要取反,所以光有flag_10ms=0是不行的,还需要key_in==1'b0;按下了才有效果
		else	if(cnt_10ms==T_10ms-1'b1)
			flag_10ms	<=1'b1;
		else
			flag_10ms	<=1'b0;

	//==================//
	always@(posedge	sclk	or	negedge	rst_n)
		if(!rst_n)
			key_value	<=1'b0;		//我看到是LED上电就亮,我还就奇怪了,不可能的啊!后来看看电路图,
//		else	if(flag_10ms==1'b1)	//原来LED是高电平亮,我的初始化key_value<=1'b1;
		else	if(flag_10ms==1'b1&&key_in==1'b0)//所以不管怎么修改电路,都是LED开机就亮,修正为0时,就可以 了
			key_value	<=~key_value;
//			key_value<=1'b0;
//		else
//			key_value	<=1'b1;
			
endmodule
			


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值