嵌入式--按键事件模块

嵌入式–按键事件模块

从github那边淘来的,不知道是哪位大神写的,在此感谢他的付出。也不知道叫什么模块,暂且叫它按键事件模块吧。

头文件 multi_button.h

#ifndef _MULTI_BUTTON_H_
#define _MULTI_BUTTON_H_

#include "stdint.h"
#include "string.h"

//According to your need to modify the constants.
#define TICKS_INTERVAL    5	//ms
#define DEBOUNCE_TICKS    3	//MAX 8
#define SHORT_TICKS       (300 / TICKS_INTERVAL)
#define LONG_TICKS        (1600 / TICKS_INTERVAL)


typedef void (*BtnCallback)(void*);

typedef enum {
	PRESS_DOWN = 0,
	PRESS_UP,
	PRESS_REPEAT,
	SINGLE_CLICK,
	DOUBLE_CLICK,
	LONG_PRESS_START,
	LONG_PRESS_HOLD,
	number_of_event,
	NONE_PRESS
}PressEvent;

typedef struct Button {
	uint16_t ticks;
	uint8_t  repeat : 4;
	uint8_t  event : 4;
	uint8_t  state : 3;
	uint8_t  debounce_cnt : 3;
	uint8_t  active_level : 1;
	uint8_t  button_level : 1;
	uint8_t  (*hal_button_Level)(void);
	BtnCallback  cb[number_of_event];
	struct Button* next;
}Button;

#ifdef __cplusplus
extern "C" {
#endif

void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level);
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb);
PressEvent get_button_event(struct Button* handle);
int  button_start(struct Button* handle);
void button_stop(struct Button* handle);
void button_ticks(void);

#ifdef __cplusplus
}
#endif

#endif

源文件 multi_button.c

#include "multi_button.h"

#define EVENT_CB(ev)   if(handle->cb[ev])handle->cb[ev]((Button*)handle)

//button handle list head.
static struct Button* head_handle = NULL;

/**
  * @brief  Initializes the button struct handle.
  * @param  handle: the button handle strcut.
  * @param  pin_level: read the HAL GPIO of the connet button level.
  * @param  active_level: pressed GPIO level.
  * @retval None
 */
   void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level)
   {
   memset(handle, 0, sizeof(struct Button));
   handle->event = (uint8_t)NONE_PRESS;
   handle->hal_button_Level = pin_level;
   handle->button_level = handle->hal_button_Level();
   handle->active_level = active_level;
   }

/**
  * @brief  Attach the button event callback function.
  * @param  handle: the button handle strcut.
  * @param  event: trigger event type.
  * @param  cb: callback function.
  * @retval None
      */
      void button_attach(struct Button* handle, PressEvent event, BtnCallback cb)
      {
      handle->cb[event] = cb;
      }

/**
  * @brief  Inquire the button event happen.
  * @param  handle: the button handle strcut.
  * @retval button event.
      */
      PressEvent get_button_event(struct Button* handle)
      {
      return (PressEvent)(handle->event);
      }

/**
  * @brief  Button driver core function, driver state machine.
  * @param  handle: the button handle strcut.
  * @retval None
*/
  void button_handler(struct Button* handle)
  {
  uint8_t read_gpio_level = handle->hal_button_Level();

  //ticks counter working..
  if((handle->state) > 0) handle->ticks++;

  /*------------button debounce handle---------------*/
  if(read_gpio_level != handle->button_level) { //not equal to prev one
  	//continue read 3 times same new level change
  	if(++(handle->debounce_cnt) >= DEBOUNCE_TICKS) {
  		handle->button_level = read_gpio_level;
  		handle->debounce_cnt = 0;
  	}
  } else { //leved not change ,counter reset.
  	handle->debounce_cnt = 0;
  }

  /*-----------------State machine-------------------*/
  switch (handle->state) {
  case 0:
  	if(handle->button_level == handle->active_level) {	//start press down
  		handle->event = (uint8_t)PRESS_DOWN;
  		EVENT_CB(PRESS_DOWN);
  		handle->ticks = 0;
  		handle->repeat = 1;
  		handle->state = 1;
  	} else {
  		handle->event = (uint8_t)NONE_PRESS;
  	}
  	break;

  case 1:
  	if(handle->button_level != handle->active_level) { //released press up
  		handle->event = (uint8_t)PRESS_UP;
  		EVENT_CB(PRESS_UP);
  		handle->ticks = 0;
  		handle->state = 2;

  	} else if(handle->ticks > LONG_TICKS) {
  		handle->event = (uint8_t)LONG_PRESS_START;
  		EVENT_CB(LONG_PRESS_START);
  		handle->state = 5;
  	}
  	break;

  case 2:
  	if(handle->button_level == handle->active_level) { //press down again
  		handle->event = (uint8_t)PRESS_DOWN;
  		EVENT_CB(PRESS_DOWN);
  		handle->repeat++;
  		EVENT_CB(PRESS_REPEAT); // repeat hit
  		handle->ticks = 0;
  		handle->state = 3;
  	} else if(handle->ticks > SHORT_TICKS) { //released timeout
  		if(handle->repeat == 1) {
  			handle->event = (uint8_t)SINGLE_CLICK;
  			EVENT_CB(SINGLE_CLICK);
  		} else if(handle->repeat == 2) {
  			handle->event = (uint8_t)DOUBLE_CLICK;
  			EVENT_CB(DOUBLE_CLICK); // repeat hit
  		}
  		handle->state = 0;
  	}
  	break;

  case 3:
  	if(handle->button_level != handle->active_level) { //released press up
  		handle->event = (uint8_t)PRESS_UP;
  		EVENT_CB(PRESS_UP);
  		if(handle->ticks < SHORT_TICKS) {
  			handle->ticks = 0;
  			handle->state = 2; //repeat press
  		} else {
  			handle->state = 0;
  		}
  	}
  	break;

  case 5:
  	if(handle->button_level == handle->active_level) {
  		//continue hold trigger
  		handle->event = (uint8_t)LONG_PRESS_HOLD;
  		EVENT_CB(LONG_PRESS_HOLD);

  	} else { //releasd
  		handle->event = (uint8_t)PRESS_UP;
  		EVENT_CB(PRESS_UP);
  		handle->state = 0; //reset
  	}
  	break;
  }
  }

/**
  * @brief  Start the button work, add the handle into work list.
  * @param  handle: target handle strcut.
  * @retval 0: succeed. -1: already exist.
*/
 int button_start(struct Button* handle)
 {
	 struct Button* target = head_handle;
	 while(target) {
	 	if(target == handle) return -1;	//already exist.
	 	target = target->next;
	 }
	 handle->next = head_handle;
	 head_handle = handle;
	 return 0;
 }

/**
  * @brief  Stop the button work, remove the handle off work list.
  * @param  handle: target handle strcut.
  * @retval None
      */
void button_stop(struct Button* handle)
{
		struct Button** curr;
		for(curr = &head_handle; *curr; ) {
			struct Button* entry = *curr;
			if (entry == handle) {
				*curr = entry->next;
			} else
				curr = &entry->next;
		}
}

/**
  * @brief  background ticks, timer repeat invoking interval 5ms.
  * @param  None.
  * @retval None
      */
 void button_ticks()
 {
	struct Button* target;
	for(target=head_handle; target; target=target->next) {
		button_handler(target);
	}
 }

上面有个小bug:
handle->event = (uint8_t)PRESS_REPEAT;
EVENT_CB(PRESS_REPEAT); // repeat hit
// 这句前面要增加handle->event = (uint8_t)PRESS_REPEAT; 不然不起作用。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值