Browse Source

【主线待合】按钮模块重构

paint_robot_new-v1.5
Lizongdi 1 week ago
parent
commit
c84904bd66
  1. 134
      peripheral/button.c
  2. 16
      peripheral/include/button.h

134
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;

16
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

Loading…
Cancel
Save