单片机学习笔记 —— 按键消抖

  按键是我们学习单片机时一个重要的器件,我们在按下按键时,难免会一位手抖动或者接触不稳定,但如果不消抖,按键按下的瞬间将会产生成百上千次按键有效的结果,最终的现象不可预料,所以有必要进行消抖。

一、消抖原理

原理:使用定时器计时产生中断,只要在一定次数的中断内,按键按下有效的次数达到一定次数,就可以认为按键按下了,此时返回一个按键有效的现象。

例子:比如,我们设置200us产生一个中断,定义两个变量:count_timeskey_pressed_times ,每次中断count_times加一,同时若检测key按键被按下,则key_pressed_times加一。当count_times达到30时,若key_pressed_times>20,则认为按键按下了。
count_times:计算中断次数
key_pressed_times:计算中断时按键按下的次数



二、程序代码

原理图

按键的引脚:KEY1: P3.2、KEY2: P3.3
数码管段选:P0[7…0]
数码管位选:P2[2…0] + P2.3(译码使能)

变量定义

#define uchar unsigned char
#define uint unsigned int

uchar code duanxuan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code weixuan[4]={0x04,0x05,0x06,0x07};

sbit led_sel=P2^3;	//74LH138译码器的使能
sbit key1=P3^2;		//按键key1
sbit key2=P3^3;		//按键key2

uint number;		//显示在数码管上的值
uint flag;			//位选的位置
int count_times,key1_pressed_times,key2_pressed_times;	//消抖中统计次数的量
bit status_P,status_P2;			//按键的钱后两个状态

Init()函数

void Init()
{
	P0M0 = 0XFF;	//设置推挽输出,P3不用设置
	P0M1 = 0X00;
	P2M0 = 0X0F;
	P2M1 = 0X00;
	
	led_sel = 0;	//位选译码器使能有效
	P0 = 0;
	number = 5000;
	count_times = 0;
	key1_pressed_times = 0;
	key2_pressed_times = 0;
	
	status_P = 0;	//默认前后状态都是按下
	status_P2 = 0;
	flag = 0;
	
	TMOD = 0X00;
	EA = 1;
	ET0 = 1;
	TH0 = (65536-200)/256;	//200us一次中断
	TL0 = (65536-200)%256;
	TR0 = 1;
}

中断函数:控制数码管显示、统计中断次数、统计key1和key2被按下的次数

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++;
	
	// 中断次数 检测key1、key2是否被按下
	count_times++;
	if(key1==0)
		key1_pressed_times++;
	
	if(key2==0)
		key2_pressed_times++;
}

main()函数:每15ms采集一次数据,检测按键是否可以被认为被按下

void main()
{
	Init();
	while(1)
	{
		if(flag==4)		//该判断放在中断函数外面更合适
			flag=0;
		
		if(count_times==30)					//每30*0.2ms检测一次按键
		{
			if(key1_pressed_times>=20){		// 该时间段内,key1按下次数达到2/3
				if(status_P==1){
					status_P=0;
					number++;
				}
			}
			else status_P=1;
			
			if(key2_pressed_times>=20){		// 该时间段内,key2按下次数达到2/3
				if(status_P2==1){
					status_P2=0;
					number--;
				}
			}
			else status_P2=1;
			
			count_times=0;					// 所有次数清零
			key1_pressed_times=0;
			key2_pressed_times=0;
		}
	}
}

延时消抖:另一种消抖的办法,如果某一时刻检测到按键key为低电平(按下),再10us,如果按键还是低电平,则可认为按键按下是有效的。

if( sbtKey1 == 0 )
{
	delay( 10 );                     //ÑÓʱÏû¶¶
	if( sbtKey1 == 0 )
	{
		xxx;
	}
}

以上就是关于按键消抖的内容啦~



第五篇单片机学习笔记完结,cheers ! 🍻

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
按键消抖是指在按下或松开按键时,由于机械结构的原因,可能会出现多次触发信号。为了避免这种情况,需要进行按键消抖处理。 一般的按键消抖程序流程如下: 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单片机的延时函数来实现延时功能。这种延时方式相对简单,但是不够准确,可能会受到系统时钟频率、优化等因素的影响。因此,在实际应用中,建议使用定时器中断或者外部中断方式来实现按键消抖处理。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值