prj to mdks
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "bsp_key.h"
|
||||
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
#define EVENT_CALLBACK(event) do{ \
|
||||
if (key_index->Callback[ event ]) \
|
||||
{ \
|
||||
key_index->Callback[ event ]( key_index->id, event ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static struct BSP_KEY *_key_head;
|
||||
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief 按键对象初始化
|
||||
* @note
|
||||
* @param[in] key: 按键句柄
|
||||
* @param[in] id: 按键 ID,用于识别不同的按键
|
||||
* @param[in] KEY_GetState: 按键状态获取回调函数
|
||||
* @param[in] press_level: 按键按下时的电平状态
|
||||
* @param[in] press_time: 设置按键长按的间隔时间
|
||||
* @retval 执行结果
|
||||
*/
|
||||
#if (KEY_USER_DEFINE_PRESS_TIME)
|
||||
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level, uint16_t press_time)
|
||||
#else
|
||||
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level)
|
||||
#endif
|
||||
{
|
||||
memset(key, 0, sizeof(struct BSP_KEY));
|
||||
|
||||
key->id = id;
|
||||
key->press_level = press_level;
|
||||
key->continuous_value = 0xFF;
|
||||
key->GetState = KEY_GetState;
|
||||
#if (KEY_USER_DEFINE_PRESS_TIME)
|
||||
key->press_time = press_time;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按键启用
|
||||
* @note 每个按键初始化并注册好相应的按键事件回调函数后,必须调用本函数才能使用
|
||||
* @param[in] key: 按键句柄
|
||||
* @retval 执行结果
|
||||
*/
|
||||
int8_t BSP_Key_Start(struct BSP_KEY *key)
|
||||
{
|
||||
struct BSP_KEY *key_index = _key_head;
|
||||
|
||||
while (key_index)
|
||||
{
|
||||
if (key_index == key)
|
||||
return 1;
|
||||
|
||||
key_index = key_index->next;
|
||||
}
|
||||
|
||||
key->next = _key_head;
|
||||
_key_head = key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按键停用
|
||||
* @note 当按键不再需要使用时,便可调用本函数
|
||||
* @param[in] key:按键句柄
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_Key_Stop(struct BSP_KEY *key)
|
||||
{
|
||||
struct BSP_KEY *key_now = _key_head;
|
||||
struct BSP_KEY *key_last;
|
||||
|
||||
for (; key_now; key_now = key_now->next)
|
||||
{
|
||||
if (key_now == key)
|
||||
{
|
||||
if (key == _key_head)
|
||||
{
|
||||
_key_head = key->next;
|
||||
return;
|
||||
}
|
||||
|
||||
if (key->next)
|
||||
key_last->next = key->next;
|
||||
|
||||
else
|
||||
key_last->next = NULL;
|
||||
}
|
||||
key_last = key_now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 注册按键事件触发时的回调函数
|
||||
* @note 若需要使用按键,则至少应该注册一个按键事件的回调函数
|
||||
* @param[in] key: 按键句柄
|
||||
* @param[in] event: 按键事件
|
||||
* @param[in] callback: 按键事件回调函数
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_Key_Register(struct BSP_KEY *key, KEY_EVENT event, Key_EventCallback callback)
|
||||
{
|
||||
key->Callback[ event ] = callback;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按键业务处理函数
|
||||
* @note 若需要使用按键的任何功能,都需要调用本函数,并周期性的循环执行
|
||||
* @param[in] ms: 告知本函数每隔多少毫秒被执行1次
|
||||
* @retval None
|
||||
*/
|
||||
void BSP_Key_Handler(uint8_t ms)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t times = 0xFF;
|
||||
struct BSP_KEY *key_index = _key_head;
|
||||
|
||||
for (; i < (8 - KEY_CONSECUTIVE_READ_TIME); i++)
|
||||
times >>= 1;
|
||||
|
||||
for (; key_index; key_index = key_index->next)
|
||||
{
|
||||
/* 获取按键电平值 */
|
||||
key_index->continuous_value = (key_index->continuous_value << 1) | key_index->GetState();
|
||||
|
||||
/* 获取按键按下或弹起状态 */
|
||||
if ((key_index->continuous_value & times) == 0x00)
|
||||
{
|
||||
if (key_index->press_level == KEY_PRESS_LOW)
|
||||
key_index->key_state = KEY_DOWN;
|
||||
else
|
||||
key_index->key_state = KEY_UP;
|
||||
}
|
||||
else if((key_index->continuous_value & times) == times)
|
||||
{
|
||||
if (key_index->press_level == KEY_PRESS_HIGH)
|
||||
key_index->key_state = KEY_DOWN;
|
||||
else
|
||||
key_index->key_state = KEY_UP;
|
||||
}
|
||||
|
||||
/* 按键状态机 */
|
||||
switch (key_index->state)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (key_index->key_state == KEY_DOWN) /* 首次按下 */
|
||||
{
|
||||
key_index->event = KEY_PRESS;
|
||||
EVENT_CALLBACK( KEY_PRESS );
|
||||
key_index->state = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (key_index->key_state == KEY_UP) /* 按下后放开 */
|
||||
{
|
||||
key_index->tick = 0;
|
||||
#if (KEY_CLICK_EVENT_WHEN_DBLCLICK)
|
||||
key_index->event = KEY_CLICK;
|
||||
EVENT_CALLBACK( KEY_CLICK );
|
||||
#endif
|
||||
key_index->state = 2;
|
||||
}
|
||||
else if (key_index->key_state == KEY_DOWN) /* 还处于第一次按下的状态 */
|
||||
{
|
||||
key_index->tick += ms;
|
||||
|
||||
#if (KEY_USER_DEFINE_PRESS_TIME)
|
||||
if (key_index->tick >= key_index->press_time) /* 第一次按下时间已超过长按触发时间 */
|
||||
#else
|
||||
if (key_index->tick >= KEY_LONG_PRESS_TIME) /* 超时未按下 */
|
||||
#endif
|
||||
{
|
||||
key_index->tick = 0;
|
||||
key_index->event = KEY_LONG_PRESS;
|
||||
EVENT_CALLBACK( KEY_LONG_PRESS );
|
||||
key_index->state = 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: /* 检测是否双击 */
|
||||
{
|
||||
if (key_index->key_state == KEY_DOWN) /* 单击后再次按下 */
|
||||
{
|
||||
if (KEY_DBLCLICK_PRESS_VALID) /* 第二次按下立即触发标志 */
|
||||
{
|
||||
key_index->event = KEY_DBLCLICK;
|
||||
EVENT_CALLBACK( KEY_DBLCLICK );
|
||||
}
|
||||
key_index->tick = 0;
|
||||
key_index->state = 3;
|
||||
}
|
||||
else if (key_index->key_state == KEY_UP) /* 未按下 */
|
||||
{
|
||||
key_index->tick += ms;
|
||||
|
||||
if (key_index->tick >= KEY_DBLCLICK_TIME) /* 单击后超时未再按下,事件结束 */
|
||||
{
|
||||
#if (KEY_CLICK_EVENT_WHEN_DBLCLICK == 0)
|
||||
key_index->event = KEY_CLICK;
|
||||
EVENT_CALLBACK( KEY_CLICK );
|
||||
#endif
|
||||
key_index->tick = 0;
|
||||
key_index->state = 0;
|
||||
key_index->event = KEY_NONE_EVENT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: /* 双击事件,第二次已按下 */
|
||||
{
|
||||
if (key_index->key_state == KEY_UP) /* 第二次已放开按键 */
|
||||
{
|
||||
if (KEY_DBLCLICK_PRESS_VALID == 0) /* 第二次按下放开后才触发标志 */
|
||||
{
|
||||
key_index->event = KEY_DBLCLICK;
|
||||
EVENT_CALLBACK( KEY_DBLCLICK );
|
||||
}
|
||||
key_index->tick = 0;
|
||||
key_index->state = 0;
|
||||
key_index->event = KEY_NONE_EVENT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: /* 长时间按着(进入此处时长按回调事件已经被执行完毕) */
|
||||
{
|
||||
if (key_index->key_state == KEY_DOWN) /* 此时依旧被按着 */
|
||||
{
|
||||
key_index->tick += ms;
|
||||
|
||||
#if (KEY_LONG_PRESS_CONTINU_TRIG_TIME)
|
||||
/* 需要长按保持触发 */
|
||||
if (key_index->tick >= KEY_LONG_PRESS_CONTINU_TRIG_TIME)
|
||||
{
|
||||
key_index->tick = 0;
|
||||
key_index->event = KEY_LONG_PRESS_HOLD;
|
||||
EVENT_CALLBACK( KEY_LONG_PRESS_HOLD );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (key_index->key_state == KEY_UP) /* 用户已放开按键,流程结束 */
|
||||
{
|
||||
key_index->tick = 0;
|
||||
key_index->state = 0;
|
||||
key_index->event = KEY_NONE_EVENT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default :break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user