|
|
@ -8,7 +8,7 @@ |
|
|
作 者 : Radkil |
|
|
作 者 : Radkil |
|
|
生成日期 : 2026年3月25日星期三 |
|
|
生成日期 : 2026年3月25日星期三 |
|
|
最近修改 : |
|
|
最近修改 : |
|
|
功能描述 : 按键时间驱动处理 |
|
|
功能描述 : 按键时间驱动处理(含优先级机制) |
|
|
|
|
|
|
|
|
修改历史 : |
|
|
修改历史 : |
|
|
1.日 期 : 2026年3月25日星期三 |
|
|
1.日 期 : 2026年3月25日星期三 |
|
|
@ -45,6 +45,12 @@ |
|
|
|
|
|
|
|
|
static rd_slist_t g_sBtnListHead = RD_SLIST_OBJECT_INIT(g_sBtnListHead); |
|
|
static rd_slist_t g_sBtnListHead = RD_SLIST_OBJECT_INIT(g_sBtnListHead); |
|
|
static rd_mutex_t g_fpBtnCtrl = RD_MUTEX_INITIALIZER; |
|
|
static rd_mutex_t g_fpBtnCtrl = RD_MUTEX_INITIALIZER; |
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
|
* 模块级变量 - 优先级控制 * |
|
|
|
|
|
*----------------------------------------------*/ |
|
|
|
|
|
static int g_iPriorityLock = 0; /**< 优先级锁:>0 时屏蔽低于该值的按键 */ |
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
/*----------------------------------------------*
|
|
|
* 常量定义 * |
|
|
* 常量定义 * |
|
|
*----------------------------------------------*/ |
|
|
*----------------------------------------------*/ |
|
|
@ -52,7 +58,57 @@ static rd_mutex_t g_fpBtnCtrl = RD_MUTEX_INITIALIZER; |
|
|
/*----------------------------------------------*
|
|
|
/*----------------------------------------------*
|
|
|
* 宏定义 * |
|
|
* 宏定义 * |
|
|
*----------------------------------------------*/ |
|
|
*----------------------------------------------*/ |
|
|
rd_btn_t *rd_BtnCreate(int _iActiveLogic) |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 判断按键是否被优先级锁屏蔽 |
|
|
|
|
|
* @return 1=被屏蔽,0=允许处理 |
|
|
|
|
|
*/ |
|
|
|
|
|
static int rd_BtnIsPriorityLocked(rd_btn_t *_pBtn) |
|
|
|
|
|
{ |
|
|
|
|
|
if (g_iPriorityLock <= 0) |
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
/* 优先级数值越小越高,被锁的按键优先级低于锁值则屏蔽 */ |
|
|
|
|
|
if (_pBtn->m_iPriority >= g_iPriorityLock) |
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 更新当前最高活跃优先级(用于自动加锁/解锁) |
|
|
|
|
|
*/ |
|
|
|
|
|
static void rd_BtnUpdatePriorityLock(void) |
|
|
|
|
|
{ |
|
|
|
|
|
rd_slist_t *pNode; |
|
|
|
|
|
rd_slist_t *pN; |
|
|
|
|
|
int highest = -1; /* -1 表示没有按键处于按下状态 */ |
|
|
|
|
|
|
|
|
|
|
|
rd_slist_for_each(pNode, pN, &g_sBtnListHead) |
|
|
|
|
|
{ |
|
|
|
|
|
rd_btn_t *_pBtn = rd_slist_entry(pNode, rd_btn_t, m_tSlist); |
|
|
|
|
|
if (_pBtn->m_iActive && |
|
|
|
|
|
(_pBtn->m_tState == STATE_PRESS_DOWN || |
|
|
|
|
|
_pBtn->m_tState == STATE_PRESS_HOLD)) |
|
|
|
|
|
{ |
|
|
|
|
|
if (highest < 0 || _pBtn->m_iPriority < highest) |
|
|
|
|
|
highest = _pBtn->m_iPriority; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (highest < 0) |
|
|
|
|
|
{ |
|
|
|
|
|
/* 没有按键按下,自动解锁 */ |
|
|
|
|
|
g_iPriorityLock = 0; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
/* 有按键按下,锁定比它优先级低的按键 */ |
|
|
|
|
|
g_iPriorityLock = highest + 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
rd_btn_t *rd_BtnCreate(int _iActiveLogic, rd_btn_read_func pReadFunc, int _iPriority) |
|
|
{ |
|
|
{ |
|
|
rd_btn_t *pBtn = (rd_btn_t *)RD_MALLOC(sizeof(rd_btn_t)); |
|
|
rd_btn_t *pBtn = (rd_btn_t *)RD_MALLOC(sizeof(rd_btn_t)); |
|
|
if (pBtn == NULL) return NULL; |
|
|
if (pBtn == NULL) return NULL; |
|
|
@ -68,6 +124,8 @@ rd_btn_t *rd_BtnCreate(int _iActiveLogic) |
|
|
pBtn->m_iHoldCycleTime = RD_BUTTON_HOLD_CYCLE_TIME_DEFAULT; |
|
|
pBtn->m_iHoldCycleTime = RD_BUTTON_HOLD_CYCLE_TIME_DEFAULT; |
|
|
pBtn->m_iActiveLogic = _iActiveLogic; |
|
|
pBtn->m_iActiveLogic = _iActiveLogic; |
|
|
pBtn->m_iTimeout = Rd_GetTime(); |
|
|
pBtn->m_iTimeout = Rd_GetTime(); |
|
|
|
|
|
pBtn->m_pReadFunc = pReadFunc; |
|
|
|
|
|
pBtn->m_iPriority = _iPriority; /* 新增:初始化优先级 */ |
|
|
rd_slist_init(&(pBtn->m_tSlist)); |
|
|
rd_slist_init(&(pBtn->m_tSlist)); |
|
|
|
|
|
|
|
|
return pBtn; |
|
|
return pBtn; |
|
|
@ -82,6 +140,7 @@ int rd_BtnDelete(rd_btn_t *_pBtn) |
|
|
|
|
|
|
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
|
|
|
_pBtn->m_iActive = 0; |
|
|
_pBtn->m_tSlist.next = NULL; |
|
|
_pBtn->m_tSlist.next = NULL; |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
RD_FREE(_pBtn); |
|
|
RD_FREE(_pBtn); |
|
|
@ -99,7 +158,7 @@ int rd_BtnStart(rd_btn_t *_pBtn) |
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
if (_pBtn->m_iActive) |
|
|
if (_pBtn->m_iActive) |
|
|
{ |
|
|
{ |
|
|
goto END; |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
return RD_INVALUE; |
|
|
return RD_INVALUE; |
|
|
} |
|
|
} |
|
|
_pBtn->m_iRepeatCnt = 0; |
|
|
_pBtn->m_iRepeatCnt = 0; |
|
|
@ -111,7 +170,6 @@ int rd_BtnStart(rd_btn_t *_pBtn) |
|
|
rd_slist_append(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
rd_slist_append(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
_pBtn->m_iActive = 1; |
|
|
_pBtn->m_iActive = 1; |
|
|
|
|
|
|
|
|
END: |
|
|
|
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
return RD_SUCCESS; |
|
|
return RD_SUCCESS; |
|
|
} |
|
|
} |
|
|
@ -126,14 +184,13 @@ int rd_BtnStop(rd_btn_t *_pBtn) |
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
if (!_pBtn->m_iActive) |
|
|
if (!_pBtn->m_iActive) |
|
|
{ |
|
|
{ |
|
|
goto END; |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
return RD_INVALUE; |
|
|
return RD_INVALUE; |
|
|
} |
|
|
} |
|
|
rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); |
|
|
_pBtn->m_tSlist.next = NULL; |
|
|
_pBtn->m_tSlist.next = NULL; |
|
|
_pBtn->m_iActive = 0; |
|
|
_pBtn->m_iActive = 0; |
|
|
|
|
|
|
|
|
END: |
|
|
|
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
return RD_SUCCESS; |
|
|
return RD_SUCCESS; |
|
|
} |
|
|
} |
|
|
@ -182,6 +239,40 @@ int rd_BtnSetEventCbk(rd_btn_t *_pBtn, rd_BtnEvent _eEvent, void (*_pEventCbk)(r |
|
|
return RD_SUCCESS; |
|
|
return RD_SUCCESS; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 手动设置按键优先级 |
|
|
|
|
|
*/ |
|
|
|
|
|
int rd_BtnSetPriority(rd_btn_t *_pBtn, int _iPriority) |
|
|
|
|
|
{ |
|
|
|
|
|
if (NULL == _pBtn) |
|
|
|
|
|
return RD_INVALUE; |
|
|
|
|
|
|
|
|
|
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
|
|
|
_pBtn->m_iPriority = _iPriority; |
|
|
|
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
|
|
|
|
|
|
|
|
|
return RD_SUCCESS; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 手动加优先级锁(屏蔽优先级 >= _iLockValue 的按键) |
|
|
|
|
|
* @param _iLockValue 锁值,优先级 >= 此值的按键被屏蔽,0=解锁 |
|
|
|
|
|
*/ |
|
|
|
|
|
void rd_BtnPriorityLock(int _iLockValue) |
|
|
|
|
|
{ |
|
|
|
|
|
Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); |
|
|
|
|
|
g_iPriorityLock = _iLockValue; |
|
|
|
|
|
Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 手动解锁优先级锁 |
|
|
|
|
|
*/ |
|
|
|
|
|
void rd_BtnPriorityUnlock(void) |
|
|
|
|
|
{ |
|
|
|
|
|
rd_BtnPriorityLock(0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void rd_BtnCalHoldTime(rd_btn_t *_pBtn) |
|
|
static void rd_BtnCalHoldTime(rd_btn_t *_pBtn) |
|
|
{ |
|
|
{ |
|
|
if(NULL == _pBtn) |
|
|
if(NULL == _pBtn) |
|
|
@ -189,17 +280,10 @@ static void rd_BtnCalHoldTime(rd_btn_t *_pBtn) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (Rd_GetTime() < _pBtn->m_iTimeout) |
|
|
_pBtn->m_iHoldTime = Rd_GetTime() - _pBtn->m_iTimeout; |
|
|
{ |
|
|
|
|
|
_pBtn->m_iHoldTime = UINT32_MAX - _pBtn->m_iTimeout + Rd_GetTime(); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
_pBtn->m_iHoldTime = Rd_GetTime() - _pBtn->m_iTimeout; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
void rd_BtnProcess() |
|
|
{ |
|
|
{ |
|
|
rd_slist_t *pNode; |
|
|
rd_slist_t *pNode; |
|
|
rd_slist_t *pN; |
|
|
rd_slist_t *pN; |
|
|
@ -208,11 +292,17 @@ void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
rd_slist_for_each(pNode, pN, &g_sBtnListHead) |
|
|
rd_slist_for_each(pNode, pN, &g_sBtnListHead) |
|
|
{ |
|
|
{ |
|
|
rd_btn_t *_pBtn = rd_slist_entry(pNode, rd_btn_t, m_tSlist); |
|
|
rd_btn_t *_pBtn = rd_slist_entry(pNode, rd_btn_t, m_tSlist); |
|
|
|
|
|
|
|
|
|
|
|
/* ===== 新增:优先级屏蔽判断 ===== */ |
|
|
|
|
|
if (rd_BtnIsPriorityLocked(_pBtn)) |
|
|
|
|
|
continue; /* 被屏蔽的按键直接跳过,不更新状态 */ |
|
|
|
|
|
|
|
|
|
|
|
int level = _pBtn->m_pReadFunc(); |
|
|
switch (_pBtn->m_tState) |
|
|
switch (_pBtn->m_tState) |
|
|
{ |
|
|
{ |
|
|
case STATE_NONE_PRESS: |
|
|
case STATE_NONE_PRESS: |
|
|
{ |
|
|
{ |
|
|
if (_pFunc() == _pBtn->m_iActiveLogic) |
|
|
if (level == _pBtn->m_iActiveLogic) |
|
|
{ |
|
|
{ |
|
|
_pBtn->m_iTimeout = Rd_GetTime() + _pBtn->m_iEliminationTime; |
|
|
_pBtn->m_iTimeout = Rd_GetTime() + _pBtn->m_iEliminationTime; |
|
|
_pBtn->m_tState = STATE_CHECK_PRESS; |
|
|
_pBtn->m_tState = STATE_CHECK_PRESS; |
|
|
@ -222,7 +312,7 @@ void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
/* 间隔过大,清零 */ |
|
|
/* 间隔过大,清零 */ |
|
|
if (_pBtn->m_iRepeatCnt) |
|
|
if (_pBtn->m_iRepeatCnt) |
|
|
{ |
|
|
{ |
|
|
if ((Rd_GetTime() - _pBtn->m_iTimeout) < (UINT32_MAX / 2)) |
|
|
if ((Rd_GetTime() - _pBtn->m_iTimeout) > (UINT32_MAX / 2)) |
|
|
{ |
|
|
{ |
|
|
_pBtn->m_iRepeatCnt = 0; |
|
|
_pBtn->m_iRepeatCnt = 0; |
|
|
} |
|
|
} |
|
|
@ -231,7 +321,7 @@ void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
} break; |
|
|
} break; |
|
|
case STATE_CHECK_PRESS: |
|
|
case STATE_CHECK_PRESS: |
|
|
{ |
|
|
{ |
|
|
if (_pFunc() == _pBtn->m_iActiveLogic) |
|
|
if (level == _pBtn->m_iActiveLogic) |
|
|
{ |
|
|
{ |
|
|
if ((Rd_GetTime() - _pBtn->m_iTimeout) < (UINT32_MAX / 2)) |
|
|
if ((Rd_GetTime() - _pBtn->m_iTimeout) < (UINT32_MAX / 2)) |
|
|
{ |
|
|
{ |
|
|
@ -253,10 +343,13 @@ void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
|
|
|
|
|
|
_pBtn->m_iTimeout = Rd_GetTime(); |
|
|
_pBtn->m_iTimeout = Rd_GetTime(); |
|
|
_pBtn->m_tState = STATE_PRESS_HOLD; |
|
|
_pBtn->m_tState = STATE_PRESS_HOLD; |
|
|
|
|
|
|
|
|
|
|
|
/* ===== 新增:按下后更新优先级锁 ===== */ |
|
|
|
|
|
rd_BtnUpdatePriorityLock(); |
|
|
} break; |
|
|
} break; |
|
|
case STATE_PRESS_HOLD: |
|
|
case STATE_PRESS_HOLD: |
|
|
{ |
|
|
{ |
|
|
if (_pFunc() == _pBtn->m_iActiveLogic) |
|
|
if (level == _pBtn->m_iActiveLogic) |
|
|
{ |
|
|
{ |
|
|
rd_BtnCalHoldTime(_pBtn); |
|
|
rd_BtnCalHoldTime(_pBtn); |
|
|
if (_pBtn->m_iHoldTime - _pBtn->m_iPrevHoldTime >= _pBtn->m_iHoldCycleTime) |
|
|
if (_pBtn->m_iHoldTime - _pBtn->m_iPrevHoldTime >= _pBtn->m_iHoldCycleTime) |
|
|
@ -280,6 +373,9 @@ void rd_BtnProcess(cbk_InPut _pFunc) |
|
|
|
|
|
|
|
|
_pBtn->m_iTimeout = Rd_GetTime() + RD_BUTTON_TWO_INTERVAL_TIME_DEFAULT; |
|
|
_pBtn->m_iTimeout = Rd_GetTime() + RD_BUTTON_TWO_INTERVAL_TIME_DEFAULT; |
|
|
_pBtn->m_tState = STATE_NONE_PRESS; |
|
|
_pBtn->m_tState = STATE_NONE_PRESS; |
|
|
|
|
|
|
|
|
|
|
|
/* ===== 新增:释放后更新优先级锁 ===== */ |
|
|
|
|
|
rd_BtnUpdatePriorityLock(); |
|
|
} break; |
|
|
} break; |
|
|
default: |
|
|
default: |
|
|
break; |
|
|
break; |
|
|
|