单片机之按键消抖

我们前面在电子中的学习中就接触过按键,但是我们只清楚其电路图代表的含义,却不明白真正操作起来会遇到的一系列问题,由于机械触点的弹性,一个按键开关在闭合后不会马上稳定接通,断开时也不会马上断开,如果不处理的话,会导致按键识别为多下,故我们就来研究一下按键消抖(针对的是K1 K2 K3)


实验原理

在这里插入图片描述
这个电路图我们在前面已经接触过,但我们现在主要来消除K1-K3的按键问题

当按键被按下的时候,电路导通接地,I/O口为低电平;
当按键未被按下时,电路断开,I/O口保持高电平。
但一般的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,假如不加以处理,会导致按键被识别为按下多次。为了不产生这种现象而作的措施就是按键消抖。

消抖方法
  • 硬件消抖
    RS触发器
    在这里插入图片描述
    这是一个双稳态电路,学过数字逻辑的小伙伴应该会明白

  • 软件消抖

法一:使用延时
检测出键闭合后执行一个延时程序,5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。
当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序

法二:检测多次
可以设定一个检测周期,如果在一个检测周期内,按键被检测为被按下达到了一定次数,则确认为真正被按下

代码解析

由于按下K1加1,按下K2减1
初始化number为5000,显示在数码管上

  • 全局变量
uint number;//显示在数码管上
uint flag;//位选的位置
int count1,count2,count3,count4;//用于消抖计数
bit status_P,status_P2;//记录按键前一状态
  • 设置中断内容
void InterruptTimer0()interrupt 1
{
	switch(flag)
	{
		case 0:P0=0;P2=weixuan[flag];P0=duanxuan[number/1000];break;
		case 1:P0=0;P2=weixuan[flag];P0=duanxuan[(number/100)%10];break;
		case 2:P0=0;P2=weixuan[flag];P0=duanxuan[(number%100)/10];break;
		case 3:P0=0;P2=weixuan[flag];P0=duanxuan[(number%100)%10];break;
	}
	flag++;
	
	count1++;
	if(key1==0)
	{
		count2++;          //记录K1的按下状态
	}                        
		
	count3++;
	if(key2==0)
	{
		count4++;         //记录K2的按下状态
	}
}
  • 主函数部分
void main()
{
	Init();
	while(1)
	{
		if(flag==4)//修正位选位置
			flag=0;
		
		if(count1==30)//消抖大概6ms,总共统计次数30次
		{
			if(count2>=20)// 如果低电平有效次数为2/3以上
			{
				if(status_P==1)
				{
					status_P=0;
					number++;
				}
			}
			else
				status_P=1;
			count1=0;
			count2=0;
		}
		
		//同理 K2的按键消抖
		if(count3==30)//消抖大概6ms,总共统计次数30次
		{
			if(count4>=20)// 如果低电平有效次数为2/3以上
			{
				if(status_P2==1)
				{
					status_P2=0;
					number--;
				}
			}
			else
				status_P2=1;
			count3=0;
			count4=0;
		}
	}
}

代码比较的简单,其实也算是在一定时间内检测多次,即利用了软件消抖

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
按键消抖是指在按下或松开按键时,由于机械结构的原因,可能会出现多次触发信号。为了避免这种情况,需要进行按键消抖处理。 一般的按键消抖程序流程如下: 1. 初始化按键口为输入状态。 2. 在主循环中循环检测按键口状态。 3. 如果按键口状态为按下状态,延时一段时间(一般为几毫秒)。 4. 再次检测按键口状态,如果状态仍为按下状态,则判定为有效按键信号,执行相应的操作;否则忽略该信号。 以下是一个基于延时方式的按键消抖程序示例,以STM32单片机为例: ```c #include "stm32f10x.h" #define KEY_PORT GPIOA #define KEY_PIN GPIO_Pin_0 void Delay(__IO uint32_t nCount); int main(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置KEY口为输入口 GPIO_InitStructure.GPIO_Pin = KEY_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(KEY_PORT, &GPIO_InitStructure); while(1) { // 检测按键口状态 if(GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == RESET) { // 延时一段时间 Delay(100); // 再次检测按键口状态,如果状态为按下状态,则判定为有效按键信号 if(GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == RESET) { // 执行相应的操作 // ... } } } } // 延时函数 void Delay(__IO uint32_t nCount) { for(; nCount != 0; nCount--); } ``` 在上面的示例中,我们使用了STM32单片机的延时函数来实现延时功能。这种延时方式相对简单,但是不够准确,可能会受到系统时钟频率、优化等因素的影响。因此,在实际应用中,建议使用定时器中断或者外部中断方式来实现按键消抖处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值