unsigned char key_sCAN(void)
{
if(key == 0) //检测到被按下
{
delay(5); //延时5ms,消抖
if(key != 0)
retrurn 0; //是抖动,返回退出
while(!key1); // 确认被按下,等下释放
delay(5); //延时5ms,消抖
while(!key1); //确认被释放
return 1; //返回按下信号
}
return 0; //没信号
}
a. 是,则开始等待释放
b. 否,则返回0,退出
/*************************************************
Module Name : key_scan_jitter.v
Engineer : Crazy Bingo
Target Device : EP2C8Q208C8
Tool versions : Quartus II 11.0
Create Date : 2011-6-26
Revision : v1.0
Description :
**************************************************/
module key_scan_jitter
#(
parameter KEY_WIDTH = 2
)
(
input clk,
input rst_n,
input [KEY_WIDTH-1:0] key_data,
output key_flag,
output reg [KEY_WIDTH-1:0] key_value
);
reg [19:0] cnt; //delay_5ms(249999)
reg [2:0] state;
//-----------------------------------
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 20'd0;
else
begin
cnt <= cnt + 1'b1;
= 20'd249999) =
cnt <= 20'd0;
end
end
//-----------------------------------
reg key_flag_r;
reg [KEY_WIDTH-1:0] key_data_r;
clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r <= 1'b0;
key_value <= {KEY_WIDTH{1'b0}};
end
else if(cnt == 20'd249999) //Delay_5ms
begin
case(state)
0:
begin
!= {KEY_WIDTH{1'b1}})
state <= 1;
else
state <= 0;
end
1:
begin
!= {KEY_WIDTH{1'b1}})
state <= 2;
else
state <= 0;
end
2:
begin
key_flag_r <= 1'b1;
key_value <= key_data; //lock the key_value
state <= 3;
end
3:
begin
key_flag_r <= 1'b0; //read the key_value
= {KEY_WIDTH{1'b1}}) =
state <= 4;
else
state <= 3;
end
4:
begin
= {KEY_WIDTH{1'b1}}) =
state <= 0;
else
state <= 4;
end
endcase
end
end
//---------------------------------------
the falling endge of the key_flag
reg key_flag_r0,key_flag_r1;
clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r0 <= 0;
key_flag_r1 <= 0;
end
else
begin
key_flag_r0 <= key_flag_r;
key_flag_r1 <= key_flag_r0;
end
end
assign key_flag = key_flag_r1 & ~key_flag_r0;
endmodule
二是,循环n次计数消抖动。同样,此模块也是Bingo无数次修改测试最后成型的代码,利用了更少的资源,更适用于并行高速FPGA的性能要求。具体代码实现过程请有需要的自行分析,本模块通过相关时钟的适配,n次计数来确认按键信号,Verilog代码如下所示:
/*************************************************
* Module Name : key_scan.v
* Engineer : Crazy Bingo
* Target Device : EP2C8Q208C8
* Tool versions : Quartus II 11.0
* Create Date : 2011-6-25
* Revision : v1.0
* Description :
**************************************************/
module key_scan
parameter KEY_WIDTH = 2
)
(
input clk, //50MHz
input rst_n,
input [KEY_WIDTH-1:0] key_data,
output key_flag,
output reg [KEY_WIDTH-1:0] key_value
);
//---------------------------------
//escape the jitters
reg [19:0] key_cnt; //scan counter
reg [KEY_WIDTH-1:0] key_data_r;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_data_r <= {KEY_WIDTH{1'b1}};
key_cnt <= 0;
end
else
begin
key_data_r <= key_data; //lock the key value
if((key_data == key_data_r) && (key_data != {KEY_WIDTH{1'b1}})) //20ms escape jitter
begin
if(key_cnt < 20'hfffff)
key_cnt <= key_cnt + 1'b1;
end
else key_cnt <= 0;
end
end
wire cnt_flag = (key_cnt == 20'hffffe) ? 1'b1 : 1'b0;//!!
//-----------------------------------
//sure the key is pressed
reg key_flag_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r <= 0;
key_value <= 0;
end
else if(cnt_flag)
begin
key_flag_r <= 1;
key_value <= key_data; //locked the data
end
else //let go your hand
key_flag_r <= 0; //lock the key_value
end
//---------------------------------------
//Capture the rising endge of the key_flag
reg key_flag_r0,key_flag_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r0 <= 0;
key_flag_r1 <= 0;
end
else
begin
key_flag_r0 <= key_flag_r;
key_flag_r1 <= key_flag_r0;
end
end
assign key_flag = ~key_flag_r1 & key_flag_r0;
endmodule
推荐阅读:
MCU最强科普总结(收藏版)
为什么MCU晶体两边要各接一个对地电容
一个产品级MCU菜单框架设计
点击下方『面包板社区』卡片关注我们,
每天学点电子技术干货
▲ 点击关注,后台回复"关键词",领取300 G学习资料包!
内容合作 | 视频、课程合作 | 开发板合作| 转载开白
请联系小助手微信:15889572951(微信同号)
点击阅读原文,下载《单片机编程实例大全》