IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FSM实例——按键消抖及状态检测 -> 正文阅读

[嵌入式]FSM实例——按键消抖及状态检测


目录

说明

1、功能分析

2、模块代码

3、仿真分析



说明

按键消抖在机械按键中很有必要,保护电路的安全性。一般来说,机械按键抖动持续时间约为20ms,本文从状态机的角度进行按键消抖以及按键状态判别的实现。

场景说明:

按键默认上拉到高电平,按下时为低电平。

代码仅供设计参考,编程方式不唯一。主要是设计思路和功能需求到状态转移图的映射。

不足之处,评论区留言~


1、功能分析

首先状态划分:

1、空闲状态:此时按键没有按下,处于等待按键按下的状态;

2、按下消抖:此时按键按下,进行消抖操作;

3、等待释放:按下消抖已经完成,确认按键已经稳定按下,等待释放;

4、释放消抖:此时按键释放,进行消抖操作;

状态转移条件分析:

当前状态为状态 1

  • 若检测到有下降沿到来,进入状态 2并开始计时 ;
  • 否则一直处于状态 1 等待。

当前状态为状态 2

  • 若检测到有上升沿到来,且计时时间小于20ms,返回状态 1;
  • 若计时时间大于等于20ms,进入状态 3,认为此时按键已经稳定按下;
  • 若以上均不满足,保持在本状态,持续计时。

当前状态为状态 3

  • 若检测到有上升沿到来,进入状态4并开始计时;
  • 否则一直处于本状态,等待释放;

当前状态为状态 4

  • 若检测到有下降沿到来且计时时间小于20ms,返回状态 3;
  • 若计时时间大于等于20ms,进入状态 1,认为此时按键已经稳定释放;
  • 若以上均不满足,保持在本状态,持续计时。

计数器行为分析:

状态1:清零

状态2:持续计时

状态3:清零

状态4:持续计时

状态转换图:

?

?

2、模块代码

VERILOG 编写模块:

// BY  :在路上,正出发
// 说明:实现按键检测的状态机控制(三段式)


`timescale 1ns/1ps

module KEY_FILTER_FSM(
// -----------------------------输入端口声明
	input    					I_CLK, //外部激励时钟 50MHz
	input    					I_RSTN,//外部复位信号 开关控制 
	input 						I_KEY, //外部按键
// -----------------------------输出端口声明
	output 						O_KEY1 //脉冲信号 拉高表示检测到按键稳定按下一次

	);
// -----------------------------内部参数声明
// 状态机参数
localparam 						P_STATE_IDLE 		= 4'b0001;//空闲
localparam 						P_STATE_DOWN 		= 4'b0010;//下降(按下)
localparam 						P_STATE_WAIT   		= 4'b0100;//等待释放
localparam 						P_STATE_UP   		= 4'b1000;//上升(释放)

// 计数参数
localparam						P_COUNT_MAX         = 20'hF_4240;//20ms 计数峰值

// -----------------------------内部信号声明
// 状态机相关
reg								[3:0]				R_CS;//当前状态
reg								[3:0]				R_NS;//下一状态

// 计数相关
reg 							[19:0]				R_COUNT_20MS;// 20ms计数器

// 输入打拍
reg													R_KEY; //输入 I_KEY 打1拍
reg													RR_KEY;//输入 I_KEY 打2拍

// 边沿
wire												W_KEY_POS;//上升边沿
wire												W_KEY_NEG;//下降边沿

// 按键状态
reg													R_KEY_DOWN;//单脉冲信号 拉高表示按键稳定按下
reg													R_KEY_UP;  //单脉冲信号 拉高表示按键稳定释放

// -----------------------------功能实现
// 输入打拍
always @ (posedge I_CLK)
begin
	if(I_RSTN == 1'b0)
	begin
		R_KEY <= 1'b0;
		RR_KEY <= 1'b0;
	end 
	else
	begin
		R_KEY <= I_KEY;
		RR_KEY <= R_KEY;
	end
end
// 边沿检测
assign W_KEY_POS = R_KEY & (~RR_KEY);//上升沿
assign W_KEY_NEG = (~R_KEY) & RR_KEY;//下降沿


// 三段式状态机
// 第一段 时序逻辑:状态转移
always @ (posedge I_CLK )
begin
	if(I_RSTN == 1'b0)
	begin
		R_CS <= P_STATE_IDLE;
	end
	else
	begin
		R_CS <= R_NS;
	end
end

// 第二段 组合逻辑:状态迁移条件
always @ (*)
begin
	case(R_CS)
		P_STATE_IDLE:
		begin
			if(W_KEY_NEG == 1)
			begin
				R_NS = P_STATE_DOWN;
			end
			else
			begin
				R_NS = P_STATE_IDLE;
			end
		end
		P_STATE_DOWN:
		begin
			if(W_KEY_POS == 1 && R_COUNT_20MS < P_COUNT_MAX)
			begin
				R_NS = P_STATE_IDLE;
			end
			else if(R_COUNT_20MS >= P_COUNT_MAX)
			begin
				R_NS = P_STATE_WAIT;
			end
			else
			begin
				R_NS = P_STATE_DOWN;
			end
		end
		P_STATE_WAIT:
		begin
			if(W_KEY_POS == 1)
			begin
				R_NS = P_STATE_UP;
			end
			else
			begin
				R_NS = P_STATE_WAIT;
			end
		end
		P_STATE_UP:
		begin
			if(W_KEY_NEG == 1 && R_COUNT_20MS < P_COUNT_MAX)
			begin
				R_NS = P_STATE_WAIT;
			end
			else if(R_COUNT_20MS >= P_COUNT_MAX)
			begin
				R_NS = P_STATE_IDLE;
			end
			else
			begin
				R_NS = P_STATE_UP;
			end
		end
		default:
		begin
			R_NS = P_STATE_IDLE;
		end
	endcase
end

// 第三段 时序逻辑:状态事件
always @ (posedge I_CLK )
begin
	case(R_CS)
		P_STATE_IDLE:
		begin
			R_COUNT_20MS <= 0;
			R_KEY_UP <= 0;
			R_KEY_DOWN <= 0;
		end
		P_STATE_DOWN:
		begin
			R_COUNT_20MS <= R_COUNT_20MS+1;
			if(R_COUNT_20MS >= P_COUNT_MAX)
			begin
				R_KEY_DOWN <= 1;
			end
	    end
		P_STATE_WAIT:
		begin
			R_COUNT_20MS <= 0;
			R_KEY_DOWN <= 0;
		end
		P_STATE_UP:
		begin
			R_COUNT_20MS <= R_COUNT_20MS+1;
			if(R_COUNT_20MS >= P_COUNT_MAX)
			begin
				R_KEY_UP <= 1;
			end
	    end
		default:
		begin
			R_COUNT_20MS <= 0;
			R_KEY_UP <= 0;
			R_KEY_DOWN <= 0;
		end
	endcase 
end

assign O_KEY1 = R_KEY_UP;

endmodule

3、仿真分析

建立激励文件,模拟按键抖动过程:

// 测试按键消抖以及按键稳定按下模块的功能
// BY:在路上,正出发

`timescale 1ns/1ps

module SIM_KEY_DETECT();

reg I_CLK;
reg I_RSTN;
reg I_KEY;
wire O_KEY1;

// 时钟
`define clock_period 20
initial I_CLK = 0;
always #(`clock_period/2) I_CLK = ~I_CLK;


initial
begin
	I_RSTN = 0;
	I_KEY = 1;
	# 40
	I_RSTN = 1;
	# 40
	I_KEY = 0;
	# 1000000
	I_KEY = 1;
	# 3000000
	I_KEY = 0;
	# 5000000
	I_KEY = 1;
	# 8000000
	I_KEY = 0;
	# 5000000
	I_KEY = 1;
	# 100
	I_KEY = 0;
	# 30000000
	I_KEY = 1;

	# 1000000
	I_KEY = 0;
	# 3000000
	I_KEY = 1;
	# 5000000
	I_KEY = 0;
	# 8000000
	I_KEY = 1;
	# 5000000
	I_KEY = 0;
	# 100
	I_KEY = 1;
	# 30000000
	I_KEY = 0;
	$stop;

end

// 例化模块

KEY_FILTER_FSM inst_KEY_FILTER_FSM (
 .I_CLK(I_CLK),
 .I_RSTN(I_RSTN), 
 .I_KEY(I_KEY), 
 .O_KEY1(O_KEY1));

endmodule 

时序结果图:

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 12:18:17  更:2022-04-29 12:19:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:36:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码