diff --git a/peripheral/button.c b/peripheral/button.c index e23908c..560ef97 100644 --- a/peripheral/button.c +++ b/peripheral/button.c @@ -8,7 +8,7 @@ 作 者 : Radkil 生成日期 : 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_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)); 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_iActiveLogic = _iActiveLogic; pBtn->m_iTimeout = Rd_GetTime(); + pBtn->m_pReadFunc = pReadFunc; + pBtn->m_iPriority = _iPriority; /* 新增:初始化优先级 */ rd_slist_init(&(pBtn->m_tSlist)); return pBtn; @@ -82,6 +140,7 @@ int rd_BtnDelete(rd_btn_t *_pBtn) Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); + _pBtn->m_iActive = 0; _pBtn->m_tSlist.next = NULL; Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); RD_FREE(_pBtn); @@ -99,7 +158,7 @@ int rd_BtnStart(rd_btn_t *_pBtn) Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); if (_pBtn->m_iActive) { - goto END; + Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); return RD_INVALUE; } _pBtn->m_iRepeatCnt = 0; @@ -111,7 +170,6 @@ int rd_BtnStart(rd_btn_t *_pBtn) rd_slist_append(&g_sBtnListHead, &(_pBtn->m_tSlist)); _pBtn->m_iActive = 1; -END: Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); return RD_SUCCESS; } @@ -126,14 +184,13 @@ int rd_BtnStop(rd_btn_t *_pBtn) Rd_MutexLock(&g_fpBtnCtrl, __func__, NULL); if (!_pBtn->m_iActive) { - goto END; + Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); return RD_INVALUE; } rd_slist_remove(&g_sBtnListHead, &(_pBtn->m_tSlist)); _pBtn->m_tSlist.next = NULL; _pBtn->m_iActive = 0; -END: Rd_MutexUnlock(&g_fpBtnCtrl, __func__, NULL); return RD_SUCCESS; } @@ -182,6 +239,40 @@ int rd_BtnSetEventCbk(rd_btn_t *_pBtn, rd_BtnEvent _eEvent, void (*_pEventCbk)(r 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) { if(NULL == _pBtn) @@ -189,17 +280,10 @@ static void rd_BtnCalHoldTime(rd_btn_t *_pBtn) return; } - if (Rd_GetTime() < _pBtn->m_iTimeout) - { - _pBtn->m_iHoldTime = UINT32_MAX - _pBtn->m_iTimeout + Rd_GetTime(); - } - else - { - _pBtn->m_iHoldTime = Rd_GetTime() - _pBtn->m_iTimeout; - } + _pBtn->m_iHoldTime = Rd_GetTime() - _pBtn->m_iTimeout; } -void rd_BtnProcess(cbk_InPut _pFunc) +void rd_BtnProcess() { rd_slist_t *pNode; rd_slist_t *pN; @@ -208,11 +292,17 @@ void rd_BtnProcess(cbk_InPut _pFunc) rd_slist_for_each(pNode, pN, &g_sBtnListHead) { 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) { case STATE_NONE_PRESS: { - if (_pFunc() == _pBtn->m_iActiveLogic) + if (level == _pBtn->m_iActiveLogic) { _pBtn->m_iTimeout = Rd_GetTime() + _pBtn->m_iEliminationTime; _pBtn->m_tState = STATE_CHECK_PRESS; @@ -222,7 +312,7 @@ void rd_BtnProcess(cbk_InPut _pFunc) /* 间隔过大,清零 */ 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; } @@ -231,7 +321,7 @@ void rd_BtnProcess(cbk_InPut _pFunc) } break; case STATE_CHECK_PRESS: { - if (_pFunc() == _pBtn->m_iActiveLogic) + if (level == _pBtn->m_iActiveLogic) { 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_tState = STATE_PRESS_HOLD; + + /* ===== 新增:按下后更新优先级锁 ===== */ + rd_BtnUpdatePriorityLock(); } break; case STATE_PRESS_HOLD: { - if (_pFunc() == _pBtn->m_iActiveLogic) + if (level == _pBtn->m_iActiveLogic) { rd_BtnCalHoldTime(_pBtn); 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_tState = STATE_NONE_PRESS; + + /* ===== 新增:释放后更新优先级锁 ===== */ + rd_BtnUpdatePriorityLock(); } break; default: break; diff --git a/peripheral/include/button.h b/peripheral/include/button.h index 9c69004..f164b4c 100644 --- a/peripheral/include/button.h +++ b/peripheral/include/button.h @@ -83,7 +83,7 @@ typedef enum { }rd_BtnState; typedef struct T_btn_t rd_btn_t; /**< Agile Button 结构体 */ -typedef int (*cbk_InPut)(void); +typedef int (*rd_btn_read_func)(void); struct T_btn_t { @@ -96,8 +96,10 @@ struct T_btn_t uint32_t m_iPrevHoldTime; /**< 缓存 hold_time 变量 */ uint32_t m_iHoldCycleTime; /**< 按键按下后持续调用回调函数的周期(单位ms,默认1s) */ uint32_t m_iTimeout; /**< 超时时间 */ - int m_iActiveLogic; /**< 有效电平(PIN_HIGH/PIN_LOW) */ - void (*m_pEventCbk[EVENT_NUM])(rd_btn_t *pBtn);/**< 按键对象事件回调函数 */ + int m_iActiveLogic; /**< 有效电平(PIN_HIGH/PIN_LOW) */ + int m_iPriority; /**< 按键优先级,0=最高 */ + rd_btn_read_func m_pReadFunc; /**< 按键检测函数返回值与有效电平对应 */ + void (*m_pEventCbk[EVENT_NUM])(rd_btn_t *pBtn); /**< 按键对象事件回调函数 */ rd_slist_t m_tSlist; /**< 单向链表节点 */ }; @@ -117,15 +119,17 @@ struct T_btn_t /*==============================================* * routines' or functions' implementations * *----------------------------------------------*/ -rd_btn_t *rd_BtnCreate(int _iActiveLogic); +rd_btn_t *rd_BtnCreate(int _iActiveLogic, rd_btn_read_func pReadFunc, int _iPriority); int rd_BtnDelete(rd_btn_t *_pBtn); int rd_BtnStart(rd_btn_t *_pBtn); int rd_BtnStop(rd_btn_t *_pBtn); int rd_BtnSetEliminationTime(rd_btn_t *_pBtn, uint8_t _iEliminationTime); int rd_BtnSetHoldCycleTime(rd_btn_t *_pBtn, uint32_t _iHoldCycleTime); int rd_BtnSetEventCbk(rd_btn_t *_pBtn, rd_BtnEvent _eEvent, void (*_pEventCbk)(rd_btn_t *pBtn)); -void rd_BtnProcess(cbk_InPut _pFunc); - +void rd_BtnProcess(); +int rd_BtnSetPriority(rd_btn_t *_pBtn, int _iPriority); +void rd_BtnPriorityLock(int _iLockValue); +void rd_BtnPriorityUnlock(void); #ifdef __cplusplus #if __cplusplus