STM32F103 STM32 CubeMX配置GPIO实现按键 FIFO 方案

一: 前言

当项目或工程有多个按键时,可以考虑使用FIFO 方案实现按键检测和处理。

二:简介

FIFO也就是First in, First out。就是先进先出,后进后出,不进不出。FIFO相当于是一个缓冲环节,可以防止数据丢失。 一般用到不同时域之间的数据传输。比如说单片机按键的速度和CPU去处理按键对应的任务的速度显然是不同的,如果任务非常庞大,可能还没有处理完一个任务,我们已经按了好几次。如果没有FIFO机制,那么后面几次的按键可能都会被忽略,但又不能让CPU去等待按键。所以说可以使用FIFO机制去存储按键事件,等待CPU挨个处理。在单片机的串口也会使用这种方法,挨个发送数据,因为CPU处理的速度显然比串口发送数据的速度高。

三: 配置

通过STM32CubeMX 配置相应GPIO 为输入。

四: 代码

本例中设置了4个按键, 记得要配置gpio,在MX_GPIO_Init()中初始化,然后在主函数每隔10ms扫描一次。10ms可以通过systick 处理。

key_bsp.c


#include "bsp_key.h"
#include "stm32f1xx_hal.h"
#include "main.h"

#define HARD_KEY_NUM	    4	   					
#define KEY_COUNT   	 	(HARD_KEY_NUM + 0)	

static KEY_T KEYS[KEY_COUNT] = {0};
static KEY_FIFO_T KEY_FIFO;		


//Put key to FIFO
void Key_Put(uint8_t _KeyCode)
{
	KEY_FIFO.Buf[KEY_FIFO.Wp] = _KeyCode;

	if (++KEY_FIFO.Wp  >= KEY_FIFO_SIZE)
	{
		KEY_FIFO.Wp = 0;
	}
}


//Get key from FIFO
uint8_t Key_Get(){
	uint8_t ret;

	if (KEY_FIFO.Rp == KEY_FIFO.Wp)
	{
		return KEY_NONE;
	}
	else
	{
		ret = KEY_FIFO.Buf[KEY_FIFO.Rp];

		if (++KEY_FIFO.Rp >= KEY_FIFO_SIZE)
		{
			KEY_FIFO.Rp = 0;
		}
		return ret;
	}
}


static void Key_Detect(uint8_t i)
{
	KEY_T *pBtn;
	uint8_t pr;
	pBtn = &KEYS[i];
	


	if(pBtn->IsPress == NULL) return;
	pr = pBtn->IsPress();
	if (pr)  //whether press down
	{
		if (pBtn->Count < KEY_FILTER_PERIOD) //press down filter
		{
			pBtn->Count = KEY_FILTER_PERIOD;
		}
		else if(pBtn->Count < 2 * KEY_FILTER_PERIOD)//press down filter
		{
			pBtn->Count++;
		
		}
		else
		{
			if (pBtn->State == 0)
			{
                // uint16_t temp;
				pBtn->State = 1;

				/* send press down */
				Key_Put((uint8_t)(3 * i + 1));
              
			}

			if (pBtn->LongPressPeriod > 0) // Long press set
			{
				if (pBtn->LongPressCount < pBtn->LongPressPeriod)
				{
					/* if LongPressCount = LongTime */
					if (++pBtn->LongPressCount == pBtn->LongPressPeriod)
					{
						/* send LongPress */
						Key_Put((uint8_t)(3 * i + 3));
					}
				}
				else  //repeat send after long press
				{
					// if set repeatSpeed 
					if (pBtn->RepeatPeriod > 0)
					{
						if (++pBtn->RepeatCount >= pBtn->RepeatPeriod)
						{
							pBtn->RepeatCount = 0;
							/* repeat send */
							Key_Put((uint8_t)(3 * i + 1));
						}
					}
				}
			}
		}
	}
	else  //key up
	{

		if(pBtn->Count > KEY_FILTER_PERIOD) //Count > KEY_FILTER_PERIOD
		{
			pBtn->Count = KEY_FILTER_PERIOD;
		}
		else if(pBtn->Count != 0)  //Count <= KEY_FILTER_PERIOD
		{
			pBtn->Count--;
		}
		else  // Count = 0
		{
			if (pBtn->State == 1)
			{
				pBtn->State = 0;

				/* send key up*/
				Key_Put((uint8_t)(3 * i + 2));
			}
		}

		pBtn->LongPressCount = 0;
		pBtn->RepeatCount = 0;
	}


}

static void Key_InitAllVar(){
	uint8_t i;

	
	KEY_FIFO.Rp = 0;
	KEY_FIFO.Wp = 0;

	for (i = 0; i < KEY_COUNT; i++)
	{
		KEYS[i].IsPress = NULL;  
		KEYS[i].LongPressPeriod = KEY_LONG_PERIOD;			
		KEYS[i].Count = KEY_FILTER_PERIOD / 2;		
		KEYS[i].State = 0;							
		KEYS[i].RepeatPeriod = 0;						
		KEYS[i].RepeatCount = 0;						
    KEYS[i].LastPressTime = 0;
	}

	
}

void Key_SetParam(uint8_t _ucKeyID, uint16_t _LongPressPeriod, uint8_t  _RepeatPeriod, uint8_t (*_IsPress)(void) )
{
	KEYS[_ucKeyID].LongPressPeriod = _LongPressPeriod;		
	KEYS[_ucKeyID].RepeatPeriod = _RepeatPeriod;			
	KEYS[_ucKeyID].RepeatCount = 0;					
	KEYS[_ucKeyID].IsPress = _IsPress;
}



static uint8_t Key1_PressedCallback(){
    return !HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin);
}

static uint8_t Key2_PressedCallback(){
    return !HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin);
}
static uint8_t Key3_PressedCallback(){
    return !HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin);
}
static uint8_t Key4_PressedCallback(){
    return !HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin);
}

void Key_Init(void)
{
	Key_InitAllVar();		
	
	Key_SetParam(KID_K1_SET,100,0,Key1_PressedCallback);	
  Key_SetParam(KID_K2_MODE,100,0,Key2_PressedCallback);	
  Key_SetParam(KID_K3_START,100,0,Key3_PressedCallback);
  Key_SetParam(KID_K4_STOP,100,0,Key4_PressedCallback);		
}

void Key_Scan10ms(){
	uint8_t i;

	for (i = 0; i < KEY_COUNT; i++)
	{
		Key_Detect(i);
	}
}

key_bsp.h

#ifndef _BSP_KEY_H
#define _BSP_KEY_H

#include "main.h"


#define KEY_DOWN_K1_SET		    KEY_1_DOWN
#define KEY_UP_K1_SET		    KEY_1_UP
#define KEY_LONG_K1_SET		    KEY_1_LONG

#define KEY_DOWN_K2_MODE		KEY_2_DOWN
#define KEY_UP_K2_MODE		KEY_2_UP
#define KEY_LONG_K2_MODE		KEY_2_LONG

#define KEY_DOWN_K3_START		KEY_3_DOWN
#define KEY_UP_K3_START		KEY_3_UP
#define KEY_LONG_K3_START		KEY_3_LONG

#define KEY_DOWN_K4_STOP		KEY_4_DOWN
#define KEY_UP_K4_STOP		KEY_4_UP
#define KEY_LONG_K4_STOP		KEY_4_LONG


typedef enum
{
	KEY_NONE = 0,			

	KEY_1_DOWN,				
	KEY_1_UP,				
	KEY_1_LONG,				
    
	KEY_2_DOWN,				
	KEY_2_UP,				
	KEY_2_LONG,			

	KEY_3_DOWN,			
	KEY_3_UP,				
	KEY_3_LONG,				

	KEY_4_DOWN,				
	KEY_4_UP,				
	KEY_4_LONG,				

}KEY_ENUM;



typedef enum
{
	KID_K1_SET = 0,
	KID_K2_MODE,
	KID_K3_START,
    KID_K4_STOP,

}KEY_ID_E;

//Set scan parameter
#define KEY_SCAN_PERIOR 10
#define KEY_FILTER_PERIOD 50/KEY_SCAN_PERIOR
#define KEY_LONG_PERIOD   1000/KEY_SCAN_PERIOR

参考文章:

单片机中按键检测函数详细分析经典

STM32H7的GPIO应用之按键FIFO

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值