三.STM32嵌入式学习--GPIO口(3)----通用输入的应用--按键的配置

本文介绍了在嵌入式系统中如何实现按键输入的功能,包括按键初始化配置、按键扫描、消抖处理以及实现长按和组合按键的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面我们讲了IO的通用输出的配置--点灯,今天我们讲讲按键输入。

依旧是学习思路:

如何让芯片内核判断到按键是否按下?

如果按键未按下,内核检测IO口是低电平,如果按下,则检测高电平。

如何检测IO口的电平?

因为是通用输入模式,我们只需要读取数据寄存器对应位的值,就可以知道IO口的电平状态。

按键初始化函数大致框架

{

         //时钟使能    

        //端口模式配置--------通用输入

        //上下拉-----------------浮空

}

注意:

由于按键是机械按键,有抖动,不能直接读IDR的位

所以要消抖 再读IDR寄存器

所以我们在写按键扫描函数时应该有一个延时消抖的过程。

u8 key_scan(void)

{

        If(按键按下 并且 标志位是1)

        {

                延时消抖

                If(按键真的按下)

                {

                        赋值键值

                        标志位锁定 //赋值0

                }

        }

        If(按键抬起了)

        {

                解锁标志位;  //重新赋值1

        }

        返回键值;

}

static void delay_ms(u32 ms)//延时程序
{
	u32 i = 168 / 4 * 1000 * ms;
	while(i)
	{
		i--;
	}	
}

按键初始化函数



/***********************************************
*函数名    :Key_Init
*函数功能  :对按键所用IO口初始化配置
*函数参数  :无
*函数返回值:无
*函数描述  :KEY1-----PA0
            KEY2----PE2
						KEY3----PE3
						KEY4----PE4
************************************************/
void Key_Init(void)
{
	//时钟使能
	RCC->AHB1ENR |=(1<<0);//--------------A
	RCC->AHB1ENR |=(1<<4);//--------------E
	//端口模式寄存器配置
	GPIOA->MODER &= ~(3<<0);
	GPIOE->MODER &= ~((3<<4)|(3<<6)|(3<<8));
	//上下拉配置
	GPIOA->PUPDR &= ~(3<<0);
	GPIOE->PUPDR &= ~((3<<4)|(3<<6)|(3<<8));
	
}

按键扫描函数

/***********************************************
*函数名    :Key_Scan
*函数功能  :按键扫描
*函数参数  :u8
*函数返回值:无
*函数描述  :
************************************************/
u8 Key_Scan(void)
{
	u8 key =0xff;
	static u8 key_flag = 1;
	if((KEY1||!KEY2||!KEY3||!KEY4) && key_flag )
	{
		//延时消抖
		delay_ms(12);
		if(KEY1)
		{
			//锁定标志位
			key_flag=0;
			//赋值键值
			key=1;
		}
		else if(!KEY2)
		{
			//锁定标志位
			key_flag=0;
			//赋值键值
			key=2;
		}
		else if(!KEY3)
		{
			//锁定标志位
			key_flag=0;
			//赋值键值
			key=3;
		}
		else if(!KEY4)
		{
			//锁定标志位
			key_flag=0;
			//赋值键值
			key=4;
		}	
	}
	//按键抬起
	if(!KEY1 && KEY2 && KEY3 && KEY4 )
	{
		key_flag=1;//解锁标志位
	}
	return key;
	
	
	
}

对于机械按键我们还有很多不同的应用,譬如

两个按键一起按


/******************************************
*函数名    :key_scan_key12
*函数功能  :按键1和按键2一起按
*函数参数  :无
*函数返回值:u8
*函数描述  :两个按键一起按实际是两个按键
						 按下,之间的间隔时间不能超过设定的窗口
*********************************************/
u8 key_scan_key12(void)
{
	static u8 key_flag = 1;     
	static u32 cont = 0;
	u8 key = 0xff;
	
	//判断其中一个按键按下
	if((KEY1|| !KEY2) && key_flag)
	{
		
		cont++;
		//两个按键都按下并且时间差<=250000
		if((KEY1 && !KEY2) && cont<=250000)
		{
			delay_ms(10);
			if(KEY1 && !KEY2)
			{
				key = 99;
				key_flag = 0;
			}
			
		}
	}
	//消除恶意一直按KEY1,按按键1/2后超过一定时间再按按键1/2无效
	if(cont > 250000)
	{
		cont = 255000;
	}

	
	//如果两个按键抬起就解锁
	if(!KEY1 && KEY2 )
	{
		key_flag = 1;
		cont = 0;
	}
	
	
	
	return key;
}

长按:


/******************************************
*函数名    :key1_len_scan
*函数功能  :按键1长按 短按扫描
*函数参数  :无
*函数返回值:u8
*函数描述  :短按返回1  长按返回11
*********************************************/
u8 key1_len_scan(void)
{
	u8 key_val = 0xff;
	static u8 key_falg = 1;                //定义长按标志位变量  
	static u32 cont	 = 0;
	
	
	if(KEY1)                               //如果按键1按下
	{
		cont++;                              //开始计数
		if(cont > 250)  cont = 300;          //防止无限加越界
		delay_ms(10);                        //消抖
	} 
	
	//如果按键1抬起 并且时间不超过100  就是短按
	if(!KEY1 && cont>0 && cont<100)         
	{
		key_val = 1;                          //赋值键值1
		cont = 0;                             //清零
	}
	
	//如果时间超过250   并且 标志位1  就是长按
	if(cont >= 250 && key_falg)
	{
		key_val = 11;                         //赋值键值11         
		key_falg = 0;                         //标志位锁定
	}
	
	
	if(!KEY1 && cont >= 250)                //如果长按的按键抬起
	{
		key_falg = 1;                         //标志位解锁
		cont = 0;                             //清零
	} 

	return  key_val;                       //返回键值
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值