代码原型基于Siliconlabs EFR32MG Zigbee协议栈的button interface plugin进行优化。
优化后每个按键仅使用一个timer event就可以完成按键功能的实现,每个按键都需要一个timer event,以下源码默认可以支持4个按键的独立操作实现。
按键功能支持低电平、高电平、短按、长按、按住上电、连击、持续按下。
按键功能描述:
1、电平低回调(按键引脚电平变化为低时,已去抖,默认20ms);
WEAK(void w_HalButton_LowCallback(uint8_t buttonIndex))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推。
2、电平高回调(按键引脚电平变化为高时,已去抖,默认20ms);
WEAK(void w_HalButton_HighCallback(uint8_t buttonIndex))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推。
3、短按回调(默认按下到松开的时间小于1000ms为短按);
WEAK(void w_HalButton_PressedShortCallback(uint8_t buttonIndex, uint16_t pressedTime))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推;pressedTime为按下的时间,单位ms。
4、长按回调(默认按下到松开的时间大于等于于1000ms为长按);
WEAK(void w_HalButton_PressedLongCallback(uint8_t buttonIndex, uint16_t pressedTime))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推;pressedTime为按下的时间,单位ms。
5、开机上电按下回调(类似于长按,但仅在开机的条件下执行);
WEAK(void w_HalButton_PressedHoldPowerOnCallback(uint8_t buttonIndex, uint16_t pressedTime))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推;pressedTime为按下的时间,单位ms。
6、连击回调(默认两次短按时间间隔低于500ms为连击计数);
WEAK(void w_HalButton_ContinuousPressedShortCallback(uint8_t buttonIndex, uint8_t pressesNum))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推;pressesNum为连击的次数。
7、持续按下回调(持续按下超过1000ms后,每1000ms产生一个回调);
WEAK(uint8_t w_HalButton_PressingCallback(uint8_t buttonIndex, uint8_t pressingNum))
回调函数为弱函数的形式,使用者可以根据实际情况决定是否更改重写函数,buttonIndex为按键索引,0为第一个按键,以此类推;pressingNum为按下的默认时间1000ms的倍数。常用于长按超过n秒时执行某些动作,而不用等到按键松开后才知道是否需要执行某些动作;若是休眠设备是不需要长时间的保持按键状态扫描,可以设置长按n秒后返回0值,停止该按键的持续扫描定时事件。
例:(以下示例重写了w_HalButton_PressingCallback函数)
/******************************************************************************
* Description : Button pressing callback.
* Parameter : @buttonIndex
* @pressingNum
* Return : nContinue: 0 is stop, 1 is continue.
*****************************************************************************/
uint8_t w_HalButton_PressingCallback(uint8_t buttonIndex, uint8_t pressingNum)
{
uint8_t nContinue = 1;
if (pressingNum >= 10)
{
nContinue = 0;
}
if (buttonIndex == 0)
{
//TODO: ……函数功能1……
}
else if (buttonIndex == 1)
{
//TODO: ……函数功能2……
if (pressingNum >= 3)
{
nContinue = 0;
}
}
else if (buttonIndex == 2)
{
//TODO: ……函数功能3……
nContinue = 0;
}
return nContinue;
}
源码HalButton.c
/***********************************************************************************
* File : HalButton.c
* Description : Hardware Button function.
* Author : Chilli
* Date : 2022.12.15
* Version : 1.0.1
***********************************************************************************/
//==================================================================================
// Include head file
#include "app/framework/include/af.h"
#include "HalGPIO.h"
#include "HalButton.h"
//==================================================================================
// Macro definition
#if (DHB_BUTTON_NUMBER == 0)
void HalButton_Init(void)
{
// None
}
WEAK(void w_HalButton_IsrHandle(uint8_t buttonIndex, uint8_t state))
{
// None
}
WEAK(void w_HalButton_DebounceLowCallback(uint8_t buttonIndex))
{
// None
}
WEAK(void w_HalButton_DebounceHighCallback(uint8_t buttonIndex))
{
// None
}
WEAK(void w_HalButton_LowCallback(uint8_t buttonIndex))
{
// None
}
WEAK(void w_HalButton_HighCallback(uint8_t buttonIndex))
{
// None
}
WEAK(void w_HalButton_PressedShortCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
// None
}
WEAK(void w_HalButton_PressedLongCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
// None
}
WEAK(void w_HalButton_PressedHoldPowerOnCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
// None
}
WEAK(void w_HalButton_ContinuousPressedShortCallback(uint8_t buttonIndex, uint8_t pressesNum))
{
// None
}
WEAK(uint8_t w_HalButton_PressingCallback(uint8_t buttonIndex, uint8_t pressingNum))
{
// None
return 0;
}
#else
//==================================================================================
// Variable declaration
//-----------------------------------------------------------------------------
// Enumeration
typedef enum {
E_BUTTON_NONE = 0,
E_BUTTON_LOW = 0,
E_BUTTON_HIGH,
E_BUTTON_PRE_RELEASE,
E_BUTTON_RELEASED,
E_BUTTON_PRE_PRESS,
E_BUTTON_PRESSED,
E_BUTTON_PRESSING,
E_BUTTON_CONTINUOUS_PRESSES,
E_BUTTON_PRESSED_SHORT,
E_BUTTON_PRESSED_LONG,
E_BUTTON_UNKNOWN,
} teButtonState;
//-----------------------------------------------------------------------------
// Structure
typedef struct {
GPIO_Port_TypeDef port;
unsigned int pin;
uint8_t mode;
bool dout;
bool polarity;
} tsButtonGpio;
typedef struct {
uint8_t u8InitState;
uint8_t u8LastState;
uint8_t u8NextState;
uint8_t u8PressingCount;
uint8_t u8ContinuousPressesCount;
uint16_t u16PressTime;
} tsButtonStatus;
//-----------------------------------------------------------------------------
// Local variable
EmberEventControl HalButton0EventControl;
EmberEventControl HalButton1EventControl;
EmberEventControl HalButton2EventControl;
EmberEventControl HalButton3EventControl;
static const tsButtonGpio sButtonGpio[DHB_BUTTON_NUMBER] = DHAL_BUTTON_INIT;
static tsButtonStatus sButtonStatus[DHB_BUTTON_NUMBER];
//==================================================================================
// Local function declaration
uint8_t halButton_PinIndex(uint8_t pin);
void halButton_IsrCallback(uint8_t pinIntNo);
uint32_t halButton_StatusHandle(uint8_t buttonIndex);
//==================================================================================
// Event function declaration
void HalButton0EventFunction(void);
void HalButton1EventFunction(void);
void HalButton2EventFunction(void);
void HalButton3EventFunction(void);
//==================================================================================
// Local function
/******************************************************************************
* Description : Finds the Index of the pins in the sButtonGpio[] array.
* Parameter : @pin
* Return : @i - Pin index
*****************************************************************************/
uint8_t halButton_PinIndex(uint8_t pin)
{
uint8_t i;
for (i = 0; i < DHAL_BUTTON_NUMBER; i++)
{
if (sButtonGpio[i].pin == pin)
{
break;
}
}
return i;
}
/******************************************************************************
* Description : Button interrupt ISR callback function.
* Parameter : @pinIntNo - Pin Interrupt number index
* Return : void
*****************************************************************************/
void halButton_IsrCallback(uint8_t pinIntNo)
{
uint8_t pinIntIndex = 0;
uint8_t buttonStateCurrent = 0;
pinIntIndex = halButton_PinIndex(pinIntNo);
//HalButtonPrintln("halButton_IsrCallback pinIntIndex=%d", pinIntIndex);
buttonStateCurrent = GPIO_PinInGet(sButtonGpio[pinIntIndex].port, sButtonGpio[pinIntIndex].pin);
#if (DHB_BUTTON_DEBOUNCE_COUNT > 0)
uint8_t buttonStateLast = 0;
uint32_t debounceCount = 0;
for (debounceCount = 0; debounceCount < DHB_BUTTON_DEBOUNCE_COUNT; debounceCount++)
{
if (buttonStateCurrent != buttonStateLast)
{
debounceCount = 0;
}
buttonStateLast = buttonStateCurrent;
buttonStateCurrent = GPIO_PinInGet(sButtonGpio[pinIntIndex].port, sButtonGpio[pinIntIndex].pin);
}
#endif //(DHB_BUTTON_DEBOUNCE_COUNT > 0)
w_HalButton_IsrHandle(pinIntIndex, buttonStateCurrent);
}
/******************************************************************************
* Description : Button status handle function.
* Parameter : @buttonIndex
* Return : @nRetTimeMs - The event next running time
*****************************************************************************/
uint32_t halButton_StatusHandle(uint8_t buttonIndex)
{
uint8_t nButtonState = 0;
uint16_t nPressedTime = 0;
uint16_t nCurrentU16Tick = 0;
uint32_t nCurrentU32Tick = 0;
uint32_t nRetTimeMs = 0;
if(buttonIndex >= DHAL_BUTTON_NUMBER)
{
return nRetTimeMs;
}
nCurrentU16Tick = halCommonGetInt16uMillisecondTick();
nCurrentU32Tick = halCommonGetInt32uMillisecondTick();
nButtonState = GPIO_PinInGet(sButtonGpio[buttonIndex].port, sButtonGpio[buttonIndex].pin);
switch (sButtonStatus[buttonIndex].u8NextState)
{
case E_BUTTON_NONE:
break;
case E_BUTTON_PRE_RELEASE:
if (sButtonGpio[buttonIndex].polarity == DHB_BUTTON_LOW_POLARITY)
{
if (nButtonState == DHB_BUTTON_HIGH_LEVEL)
{
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_PRESSED)
{
w_HalButton_HighCallback(buttonIndex);
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_RELEASED;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_NONE;
// Negative overflow: For example 119 - 65470 = -65351 Convert uint16_t = 185
nPressedTime = nCurrentU16Tick - sButtonStatus[buttonIndex].u16PressTime;
if (nPressedTime <= DHB_BUTTON_PRESSED_SHORT_TIME_MS)
{
w_HalButton_PressedShortCallback(buttonIndex, nPressedTime);
#if (DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS != 0)
sButtonStatus[buttonIndex].u8ContinuousPressesCount++;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_CONTINUOUS_PRESSES;
nRetTimeMs = DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS;
#endif
}
else
{
w_HalButton_PressedLongCallback(buttonIndex, nPressedTime);
sButtonStatus[buttonIndex].u8ContinuousPressesCount = 0;
if((nCurrentU32Tick <= DHB_BUTTON_PRESSED_POWER_ON_TIME_MS)
&& (sButtonStatus[buttonIndex].u8InitState == DHB_BUTTON_LOW_POLARITY))
{
w_HalButton_PressedHoldPowerOnCallback(buttonIndex, nPressedTime);
}
}
sButtonStatus[buttonIndex].u8InitState = E_BUTTON_UNKNOWN;
sButtonStatus[buttonIndex].u8PressingCount = 0;
}
}
}
else // polarity == DHB_BUTTON_HIGH_POLARITY
{
if (nButtonState == DHB_BUTTON_LOW_LEVEL)
{
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_PRESSED)
{
w_HalButton_LowCallback(buttonIndex);
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_RELEASED;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_NONE;
// Negative overflow: For example 119 - 65470 = -65351 Convert uint16_t = 185
nPressedTime = nCurrentU16Tick - sButtonStatus[buttonIndex].u16PressTime;
if (nPressedTime <= DHB_BUTTON_PRESSED_SHORT_TIME_MS)
{
w_HalButton_PressedShortCallback(buttonIndex, nPressedTime);
#if (DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS != 0)
sButtonStatus[buttonIndex].u8ContinuousPressesCount++;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_CONTINUOUS_PRESSES;
nRetTimeMs = DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS;
#endif
}
else
{
w_HalButton_PressedLongCallback(buttonIndex, nPressedTime);
sButtonStatus[buttonIndex].u8ContinuousPressesCount = 0;
if((nCurrentU32Tick <= DHB_BUTTON_PRESSED_POWER_ON_TIME_MS)
&& (sButtonStatus[buttonIndex].u8InitState == DHB_BUTTON_HIGH_POLARITY))
{
w_HalButton_PressedHoldPowerOnCallback(buttonIndex, nPressedTime);
}
}
sButtonStatus[buttonIndex].u8InitState = E_BUTTON_UNKNOWN;
sButtonStatus[buttonIndex].u8PressingCount = 0;
}
}
}
break;
case E_BUTTON_PRE_PRESS:
if (sButtonGpio[buttonIndex].polarity == DHB_BUTTON_LOW_POLARITY)
{
if (nButtonState == DHB_BUTTON_LOW_LEVEL)
{
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_RELEASED)
{
w_HalButton_LowCallback(buttonIndex);
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_PRESSED;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRESSING;
sButtonStatus[buttonIndex].u16PressTime = nCurrentU16Tick;
nRetTimeMs = DHB_BUTTON_PRESSING_TIME_MS;
}
}
}
else // polarity == DHB_BUTTON_HIGH_POLARITY
{
if (nButtonState == DHB_BUTTON_HIGH_LEVEL)
{
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_RELEASED)
{
w_HalButton_HighCallback(buttonIndex);
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_PRESSED;
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRESSING;
sButtonStatus[buttonIndex].u16PressTime = nCurrentU16Tick ;
nRetTimeMs = DHB_BUTTON_PRESSING_TIME_MS;
}
}
}
break;
case E_BUTTON_PRESSING:
sButtonStatus[buttonIndex].u8PressingCount++;
if (sButtonStatus[buttonIndex].u8PressingCount >= 255)
{
w_HalButton_PressingCallback(buttonIndex, sButtonStatus[buttonIndex].u8PressingCount);
sButtonStatus[buttonIndex].u8PressingCount = 0;
nRetTimeMs = 0;
}
else
{
if (w_HalButton_PressingCallback(buttonIndex, sButtonStatus[buttonIndex].u8PressingCount))
{
nRetTimeMs = DHB_BUTTON_PRESSING_TIME_MS;
}
else
{
nRetTimeMs = 0;
}
}
#if (DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS != 0)
if(sButtonStatus[buttonIndex].u8ContinuousPressesCount >= 2) // Press the key more than twice consecutively.
{
w_HalButton_ContinuousPressedShortCallback(buttonIndex, sButtonStatus[buttonIndex].u8ContinuousPressesCount);
}
#endif
sButtonStatus[buttonIndex].u8ContinuousPressesCount = 0;
break;
case E_BUTTON_CONTINUOUS_PRESSES:
#if (DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS != 0)
if(sButtonStatus[buttonIndex].u8ContinuousPressesCount >= 2) // Press the key more than twice consecutively.
{
w_HalButton_ContinuousPressedShortCallback(buttonIndex, sButtonStatus[buttonIndex].u8ContinuousPressesCount);
}
#endif
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_NONE;
sButtonStatus[buttonIndex].u8ContinuousPressesCount = 0;
break;
default:
break;
}
return nRetTimeMs;
}
//==================================================================================
// Event function
/******************************************************************************
* Description : Button0 event function.
* Parameter : void
* Return : void
*****************************************************************************/
void HalButton0EventFunction(void)
{
emberEventControlSetInactive(HalButton0EventControl);
#if (DHAL_BUTTON_NUMBER >= 1)
uint32_t nNextTimeMs = halButton_StatusHandle(0);
if (nNextTimeMs > 0)
{
emberEventControlSetDelayMS(HalButton0EventControl, nNextTimeMs);
}
//HalButtonPrintln("HalButton0EventFunction nNextTimeMs=%d", nNextTimeMs);
#endif // DHAL_BUTTON_NUMBER >= 1
}
/******************************************************************************
* Description : Button1 event function.
* Parameter : void
* Return : void
*****************************************************************************/
void HalButton1EventFunction(void)
{
emberEventControlSetInactive(HalButton1EventControl);
#if (DHAL_BUTTON_NUMBER >= 2)
uint32_t nNextTimeMs = halButton_StatusHandle(1);
if (nNextTimeMs > 0)
{
emberEventControlSetDelayMS(HalButton1EventControl, nNextTimeMs);
}
//HalButtonPrintln("HalButton1EventFunction nNextTimeMs=%d", nNextTimeMs);
#endif // DHAL_BUTTON_NUMBER >= 2
}
/******************************************************************************
* Description : Button2 event function.
* Parameter : void
* Return : void
*****************************************************************************/
void HalButton2EventFunction(void)
{
emberEventControlSetInactive(HalButton2EventControl);
#if (DHAL_BUTTON_NUMBER >= 3)
uint32_t nNextTimeMs = halButton_StatusHandle(2);
if (nNextTimeMs > 0)
{
emberEventControlSetDelayMS(HalButton2EventControl, nNextTimeMs);
}
//HalButtonPrintln("HalButton2EventFunction nNextTimeMs=%d", nNextTimeMs);
#endif // DHAL_BUTTON_NUMBER >= 3
}
/******************************************************************************
* Description : Button3 event function.
* Parameter : void
* Return : void
*****************************************************************************/
void HalButton3EventFunction(void)
{
emberEventControlSetInactive(HalButton3EventControl);
#if (DHAL_BUTTON_NUMBER >= 4)
uint32_t nNextTimeMs = halButton_StatusHandle(3);
if (nNextTimeMs > 0)
{
emberEventControlSetDelayMS(HalButton3EventControl, nNextTimeMs);
}
//HalButtonPrintln("HalButton3EventFunction nNextTimeMs=%d", nNextTimeMs);
#endif // DHAL_BUTTON_NUMBER >= 4
}
//==================================================================================
// Extend function
/******************************************************************************
* Description : Button Initialization.
* Parameter : void
* Return : void
*****************************************************************************/
void HalButton_Init(void)
{
// Initialize GPIO interrupt dispatcher
GPIOINT_Init();
// Enable GPIO in CMU
#if !defined(_SILICON_LABS_32B_SERIES_2)
CMU_ClockEnable(cmuClock_HFPER, true);
#endif //!defined(_SILICON_LABS_32B_SERIES_2)
CMU_ClockEnable(cmuClock_GPIO, true);
for (uint8_t i = 0; i < DHB_BUTTON_NUMBER; i++)
{
// Configure pin as input
GPIO_PinModeSet(sButtonGpio[i].port,
sButtonGpio[i].pin,
sButtonGpio[i].mode,
sButtonGpio[i].dout);
// Register callbacks before setting up and enabling pin interrupt.
GPIOINT_CallbackRegister(sButtonGpio[i].pin, halButton_IsrCallback);
// Set rising and falling edge interrupts
GPIO_ExtIntConfig(sButtonGpio[i].port,
sButtonGpio[i].pin,
sButtonGpio[i].pin,
true,
true,
true);
}
HalButtonPrintln("HalButton_Init ButtonNum=%d", DHB_BUTTON_NUMBER);
for (uint8_t i = 0; i < DHB_BUTTON_NUMBER; i++)
{
sButtonStatus[i].u8LastState = E_BUTTON_RELEASED;
sButtonStatus[i].u8NextState = E_BUTTON_NONE;
sButtonStatus[i].u8PressingCount = 0;
sButtonStatus[i].u8ContinuousPressesCount = 0;
sButtonStatus[i].u16PressTime = 0;
sButtonStatus[i].u8InitState = GPIO_PinInGet(sButtonGpio[i].port, sButtonGpio[i].pin);
w_HalButton_IsrHandle(i, sButtonStatus[i].u8InitState);
}
}
/******************************************************************************
* Description : Button ISR handle.
* Parameter : @buttonIndex
* @state - DHB_BUTTON_LOW_LEVEL or DHB_BUTTON_HIGH_LEVEL
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_IsrHandle(uint8_t buttonIndex, uint8_t state))
{
#if (DHAL_BUTTON_NUMBER > 0)
if(buttonIndex >= DHAL_BUTTON_NUMBER)
{
return;
}
if (state == DHB_BUTTON_LOW_LEVEL)
{
w_HalButton_DebounceLowCallback(buttonIndex);
if (sButtonGpio[buttonIndex].polarity == DHB_BUTTON_LOW_POLARITY)
{
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRE_PRESS;
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_NONE)
{
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_RELEASED;
}
}
else // polarity == DHB_BUTTON_HIGH_POLARITY
{
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRE_RELEASE;
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_NONE)
{
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_PRESSED;
}
}
}
else // state == DHB_BUTTON_HIGH_LEVEL
{
w_HalButton_DebounceHighCallback(buttonIndex);
if (sButtonGpio[buttonIndex].polarity == DHB_BUTTON_LOW_POLARITY)
{
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRE_RELEASE;
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_NONE)
{
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_PRESSED;
}
}
else // polarity == DHB_BUTTON_HIGH_POLARITY
{
sButtonStatus[buttonIndex].u8NextState = E_BUTTON_PRE_PRESS;
if (sButtonStatus[buttonIndex].u8LastState == E_BUTTON_NONE)
{
sButtonStatus[buttonIndex].u8LastState = E_BUTTON_RELEASED;
}
}
}
#if (DHAL_BUTTON_NUMBER >= 1)
if (buttonIndex == 0)
{
emberEventControlSetDelayMS(HalButton0EventControl, DHB_BUTTON0_DEBOUNCE_TIME_MS);
}
#endif // DHAL_BUTTON_NUMBER >= 1
#if (DHAL_BUTTON_NUMBER >= 2)
if (buttonIndex == 1)
{
emberEventControlSetDelayMS(HalButton1EventControl, DHB_BUTTON1_DEBOUNCE_TIME_MS);
}
#endif // DHAL_BUTTON_NUMBER >= 2
#if (DHAL_BUTTON_NUMBER >= 3)
if (buttonIndex == 2)
{
emberEventControlSetDelayMS(HalButton2EventControl, DHB_BUTTON2_DEBOUNCE_TIME_MS);
}
#endif // DHAL_BUTTON_NUMBER >= 3
#if (DHAL_BUTTON_NUMBER >= 4)
if (buttonIndex == 3)
{
emberEventControlSetDelayMS(HalButton3EventControl, DHB_BUTTON3_DEBOUNCE_TIME_MS);
}
#endif // DHAL_BUTTON_NUMBER >= 4
#endif // DHAL_BUTTON_NUMBER > 0
}
/******************************************************************************
* Description : Button debounce low callback.
* Parameter : @buttonIndex
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_DebounceLowCallback(uint8_t buttonIndex))
{
//HalButtonPrintln("HB--w_HalButton_DebounceLowCallback buttonIndex=%d", buttonIndex);
}
/******************************************************************************
* Description : Button debounce high callback.
* Parameter : @buttonIndex
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_DebounceHighCallback(uint8_t buttonIndex))
{
//HalButtonPrintln("HB--w_HalButton_DebounceHighCallback buttonIndex=%d", buttonIndex);
}
/******************************************************************************
* Description : Button low callback.
* Parameter : @buttonIndex
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_LowCallback(uint8_t buttonIndex))
{
HalButtonPrintln("HB--w_HalButton_LowCallback buttonIndex=%d", buttonIndex);
}
/******************************************************************************
* Description : Button high callback.
* Parameter : @buttonIndex
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_HighCallback(uint8_t buttonIndex))
{
HalButtonPrintln("HB--w_HalButton_HighCallback buttonIndex=%d", buttonIndex);
}
/******************************************************************************
* Description : Button pressed short callback.
* Parameter : @buttonIndex
* @pressedTime - The time the button is pressed, unit milliseconds
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_PressedShortCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
HalButtonPrintln("HB--w_HalButton_PressedShortCallback buttonIndex=%d,pressedTime=%d", buttonIndex, pressedTime);
}
/******************************************************************************
* Description : Button pressed long callback.
* Parameter : @buttonIndex
* @pressedTime - The time the button is pressed, unit milliseconds
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_PressedLongCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
HalButtonPrintln("HB--w_HalButton_PressedLongCallback buttonIndex=%d,pressedTime=%d", buttonIndex, pressedTime);
}
/******************************************************************************
* Description : Button pressed hold power on callback.
* Parameter : @buttonIndex
* @pressedTime - The time the button is pressed, unit milliseconds
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_PressedHoldPowerOnCallback(uint8_t buttonIndex, uint16_t pressedTime))
{
HalButtonPrintln("HB--w_HalButton_PressedHoldPowerOnCallback buttonIndex=%d,pressedTime=%d", buttonIndex, pressedTime);
}
/******************************************************************************
* Description : Button continuous pressed short callback.
* Parameter : @buttonIndex
* @pressesNum - Number of consecutive short button presses
* Return : void
*****************************************************************************/
WEAK(void w_HalButton_ContinuousPressedShortCallback(uint8_t buttonIndex, uint8_t pressesNum))
{
HalButtonPrintln("HB--w_HalButton_ContinuousPressedShortCallback buttonIndex=%d,pressesNum=%d", buttonIndex, pressesNum);
}
/******************************************************************************
* Description : Button pressing callback.
* Parameter : @buttonIndex
* @pressingNum
* Return : nContinue: 0 is stop, 1 is continue.
*****************************************************************************/
WEAK(uint8_t w_HalButton_PressingCallback(uint8_t buttonIndex, uint8_t pressingNum))
{
uint8_t nContinue = 1;
HalButtonPrintln("HB--w_HalButton_PressingCallback buttonIndex=%d,pressingNum=%d", buttonIndex, pressingNum);
return nContinue;
}
#endif // DHB_BUTTON_NUMBER
源码HalButton.h
/***********************************************************************************
* File : HalButton.h
* Description : Hardware Button function.
* Author : Chilli
* Date : 2022.2.7
* Version : 1.0.1
***********************************************************************************/
#ifndef HAL_BUTTON_H_
#define HAL_BUTTON_H_
//==================================================================================
// Include head file
//==================================================================================
// Macro definition
// DHB(Define Hal Button)
#ifndef DHB_BUTTON_CONFIG_METHODS
#define DHB_BUTTON_CONFIG_METHODS 1 // Button Configuration Methods: 0 is SDK Plugin, 1 is User Config
#endif
#if defined(DHB_BUTTON_CONFIG_METHODS)
#ifndef DHB_BUTTON0_DEBOUNCE_TIME_MS
#define DHB_BUTTON0_DEBOUNCE_TIME_MS 20 // Button0 of Button debounce time, Units ms
#endif
#ifndef DHB_BUTTON1_DEBOUNCE_TIME_MS
#define DHB_BUTTON1_DEBOUNCE_TIME_MS 20 // Button1 of Button debounce time, Units ms
#endif
#ifndef DHB_BUTTON2_DEBOUNCE_TIME_MS
#define DHB_BUTTON2_DEBOUNCE_TIME_MS 20 // Button2 of Button debounce time, Units ms
#endif
#ifndef DHB_BUTTON3_DEBOUNCE_TIME_MS
#define DHB_BUTTON3_DEBOUNCE_TIME_MS 20 // Button3 of Button debounce time, Units ms
#endif
#ifndef DHB_BUTTON_PRESSING_MAX_NUM
#define DHB_BUTTON_PRESSING_MAX_NUM 20 // Button pressing max number
#endif
#ifndef DHB_BUTTON_PRESSING_TIME_MS
#define DHB_BUTTON_PRESSING_TIME_MS 1000 // Button pressing timing interval, Units ms
#endif
#ifndef DHB_BUTTON_PRESSED_SHORT_TIME_MS
#define DHB_BUTTON_PRESSED_SHORT_TIME_MS 1000 // Button short pressed time out, Units ms
#endif
#ifndef DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS
#define DHB_BUTTON_CONTINUOUS_PRESSED_SHORT_TIME_MS 500 // Button continouns short pressed time out, Units ms
#endif
#ifndef DHB_BUTTON_PRESSED_POWER_ON_TIME_MS
#define DHB_BUTTON_PRESSED_POWER_ON_TIME_MS 3000 // Button pressed power-on time, Units ms
#endif
#if (DHB_BUTTON_CONFIG_METHODS == 0)
#elif (DHB_BUTTON_CONFIG_METHODS == 1)
#define DHB_BUTTON_HIGH_LEVEL 1 // High level
#define DHB_BUTTON_LOW_LEVEL 0 // Low level
#define DHB_BUTTON_HIGH_POLARITY 1 // High polarity
#define DHB_BUTTON_LOW_POLARITY 0 // Low polarity
#ifndef DHB_BUTTON_NUMBER
#define DHB_BUTTON_NUMBER 0 // Number of Button
#endif
#ifndef DHB_BUTTON_DEBOUNCE_COUNT
#define DHB_BUTTON_DEBOUNCE_COUNT 5 // Button bebounce count times
#endif
#endif
#endif // DHB_BUTTON_CONFIG_METHODS
//==================================================================================
// Variable declaration
//-----------------------------------------------------------------------------
// Enumeration
//-----------------------------------------------------------------------------
// Structure
//-----------------------------------------------------------------------------
// Extend variable
//==================================================================================
// Extend function declaration
void HalButton_Init(void);
void w_HalButton_IsrHandle(uint8_t buttonIndex, uint8_t state);
void w_HalButton_DebounceLowCallback(uint8_t buttonIndex);
void w_HalButton_DebounceHighCallback(uint8_t buttonIndex);
void w_HalButton_LowCallback(uint8_t buttonIndex);
void w_HalButton_HighCallback(uint8_t buttonIndex);
void w_HalButton_PressedShortCallback(uint8_t buttonIndex, uint16_t pressedTime);
void w_HalButton_PressedLongCallback(uint8_t buttonIndex, uint16_t pressedTime);
void w_HalButton_PressedHoldPowerOnCallback(uint8_t buttonIndex, uint16_t pressedTime);
void w_HalButton_ContinuousPressedShortCallback(uint8_t buttonIndex, uint8_t pressesNum);
uint8_t w_HalButton_PressingCallback(uint8_t buttonIndex, uint8_t pressingNum);
#endif // HAL_BUTTON_H_
芯片引脚宏定义
// BUTTON >>>
#define DHAL_BUTTON_NUMBER 3 // Number of Button
#define DHB_BUTTON_NUMBER DHAL_BUTTON_NUMBER
#if (DHAL_BUTTON_NUMBER >= 1)
#if defined(CORTEXM3_EM3585)
#elif defined(CORTEXM3_EFR32)
#define DHAL_BUTTON0_PIN_INDEX 0
#define DHAL_BUTTON0_PORT (gpioPortF)
#define DHAL_BUTTON0_PIN (5U)
#define DHAL_BUTTON0_PINS PORTF_PIN(5)
#define DHAL_BUTTON0_GPIO_MODE gpioModeInput // gpioModeInput,gpioModeInputPull,gpioModeInputPullFilter
#define DHAL_BUTTON0_GPIO_DOUT 1 // 0 is Low, 1 is High
#define DHAL_BUTTON0_POLARITY 0 // 0 is Low active, 1 is High active
#endif
#endif // DHAL_BUTTON_NUMBER >= 1
#if (DHAL_BUTTON_NUMBER >= 2)
#if defined(CORTEXM3_EM3585)
#elif defined(CORTEXM3_EFR32)
#define DHAL_BUTTON1_PIN_INDEX 1
#define DHAL_BUTTON1_PORT (gpioPortD)
#define DHAL_BUTTON1_PIN (14U)
#define DHAL_BUTTON1_PINS PORTD_PIN(14)
#define DHAL_BUTTON1_GPIO_MODE gpioModeInput // gpioModeInput,gpioModeInputPull,gpioModeInputPullFilter
#define DHAL_BUTTON1_GPIO_DOUT 1 // 0 is Low, 1 is High
#define DHAL_BUTTON1_POLARITY 0 // 0 is Low active, 1 is High active
#endif
#endif // DHAL_BUTTON_NUMBER >= 2
#if (DHAL_BUTTON_NUMBER >= 3)
#if defined(CORTEXM3_EM3585)
#elif defined(CORTEXM3_EFR32)
#define DHAL_BUTTON2_PIN_INDEX 0
#define DHAL_BUTTON2_PORT (gpioPortF)
#define DHAL_BUTTON2_PIN (4U)
#define DHAL_BUTTON2_PINS PORTF_PIN(4)
#define DHAL_BUTTON2_GPIO_MODE gpioModeInput // gpioModeInput,gpioModeInputPull,gpioModeInputPullFilter
#define DHAL_BUTTON2_GPIO_DOUT 1 // 0 is Low, 1 is High
#define DHAL_BUTTON2_POLARITY 0 // 0 is Low active, 1 is High active
#endif
#endif // DHAL_BUTTON_NUMBER >= 3
#if (DHAL_BUTTON_NUMBER >= 4)
#if defined(CORTEXM3_EM3585)
#elif defined(CORTEXM3_EFR32)
#define DHAL_BUTTON3_PIN_INDEX 0
#define DHAL_BUTTON3_PORT (gpioPortA)
#define DHAL_BUTTON3_PIN (4U)
#define DHAL_BUTTON3_PINS PORTA_PIN(4)
#define DHAL_BUTTON3_GPIO_MODE gpioModeInput // gpioModeInput,gpioModeInputPull,gpioModeInputPullFilter
#define DHAL_BUTTON3_GPIO_DOUT 1 // 0 is Low, 1 is High
#define DHAL_BUTTON3_POLARITY 0 // 0 is Low active, 1 is High active
#endif
#endif // DHAL_BUTTON_NUMBER >= 4
#if (DHAL_BUTTON_NUMBER == 1)
#define DHAL_BUTTON_INIT {{DHAL_BUTTON0_PORT, DHAL_BUTTON0_PIN, DHAL_BUTTON0_GPIO_MODE, DHAL_BUTTON0_GPIO_DOUT, DHAL_BUTTON0_POLARITY}}
#elif (DHAL_BUTTON_NUMBER == 2)
#define DHAL_BUTTON_INIT {{DHAL_BUTTON0_PORT, DHAL_BUTTON0_PIN, DHAL_BUTTON0_GPIO_MODE, DHAL_BUTTON0_GPIO_DOUT, DHAL_BUTTON0_POLARITY},\
{DHAL_BUTTON1_PORT, DHAL_BUTTON1_PIN, DHAL_BUTTON1_GPIO_MODE, DHAL_BUTTON1_GPIO_DOUT, DHAL_BUTTON1_POLARITY}}
#elif (DHAL_BUTTON_NUMBER == 3)
#define DHAL_BUTTON_INIT {{DHAL_BUTTON0_PORT, DHAL_BUTTON0_PIN, DHAL_BUTTON0_GPIO_MODE, DHAL_BUTTON0_GPIO_DOUT, DHAL_BUTTON0_POLARITY},\
{DHAL_BUTTON1_PORT, DHAL_BUTTON1_PIN, DHAL_BUTTON1_GPIO_MODE, DHAL_BUTTON1_GPIO_DOUT, DHAL_BUTTON1_POLARITY},\
{DHAL_BUTTON2_PORT, DHAL_BUTTON2_PIN, DHAL_BUTTON2_GPIO_MODE, DHAL_BUTTON2_GPIO_DOUT, DHAL_BUTTON2_POLARITY}}
#elif (DHAL_BUTTON_NUMBER == 4)
#define DHAL_BUTTON_INIT {{DHAL_BUTTON0_PORT, DHAL_BUTTON0_PIN, DHAL_BUTTON0_GPIO_MODE, DHAL_BUTTON0_GPIO_DOUT, DHAL_BUTTON0_POLARITY},\
{DHAL_BUTTON1_PORT, DHAL_BUTTON1_PIN, DHAL_BUTTON1_GPIO_MODE, DHAL_BUTTON1_GPIO_DOUT, DHAL_BUTTON1_POLARITY},\
{DHAL_BUTTON2_PORT, DHAL_BUTTON2_PIN, DHAL_BUTTON2_GPIO_MODE, DHAL_BUTTON2_GPIO_DOUT, DHAL_BUTTON2_POLARITY},\
{DHAL_BUTTON3_PORT, DHAL_BUTTON3_PIN, DHAL_BUTTON3_GPIO_MODE, DHAL_BUTTON3_GPIO_DOUT, DHAL_BUTTON3_POLARITY}}
#endif
// BUTTON <<<
Debug打印宏设置
// DUMA(Define User Main Application)
#define DUMA_PRINT_ENABLE
#ifdef DUMA_PRINT_ENABLE
#define DebugPrintln(ENABLE, ...) \
if(ENABLE) \
{ \
emberAfPrintln(EMBER_AF_PRINT_APP, __VA_ARGS__); \
}
#define DebugBufferPrintln(ENABLE, buffer, len, withSpace) \
if(ENABLE) \
{ \
emberAfPrint(EMBER_AF_PRINT_APP, "["); \
emberAfPrintBuffer(EMBER_AF_PRINT_APP, (buffer), (len), (withSpace)); \
emberAfPrint(EMBER_AF_PRINT_APP, "]\r\n"); \
}
#define DebugBufferPrint(ENABLE, buffer, len, withSpace) \
if(ENABLE) \
{ \
emberAfPrintBuffer(EMBER_AF_PRINT_APP, (buffer), (len), (withSpace)); \
}
#else
#define DebugPrintln(ENABLE, ...)
#define DebugBufferPrintln(ENABLE, buffer, len, withSpace)
#define DebugBufferPrint(ENABLE, buffer, len, withSpace)
#endif // DUMA_PRINT_ENABLE
//-------------------------------------------------------------------
// Debug print enable. 0 is disable, 1 is enable.
#define DUMA_PRINT_HAL_ADC_ENABLE 0
#define DUMA_PRINT_HAL_GPIO_ENABLE 0
#define DUMA_PRINT_HAL_BUTTON_ENABLE 1
#define DUMA_PRINT_HAL_LED_ENABLE 0
#define DUMA_PRINT_BUFFER_ENABLE 1
#define HalAdcPrintln(...) DebugPrintln(DUMA_PRINT_HAL_ADC_ENABLE, __VA_ARGS__)
#define HalGpioPrintln(...) DebugPrintln(DUMA_PRINT_HAL_GPIO_ENABLE, __VA_ARGS__)
#define HalButtonPrintln(...) DebugPrintln(DUMA_PRINT_HAL_BUTTON_ENABLE, __VA_ARGS__)
#define HalLedPrintln(...) DebugPrintln(DUMA_PRINT_HAL_LED_ENABLE, __VA_ARGS__)
#define UserBufferPrint(buffer, len, withSpace) DebugBufferPrint(DUMA_PRINT_BUFFER_ENABLE, (buffer), (len), (withSpace))
注:
宏定义中支持的设置:
1、按键独立的去抖时间,默认20ms;
2、持续按下的最大次数,默认20次(应避免休眠设备长时间扫描按键状态);
3、持续按下的回调时间间隔,默认1000ms;
4、短按的超时时间,默认1000ms;
5、连击的时间间隔,默认500ms;
6、按键的数量设置,默认0,但Timer Event仍然需要配置;
7、按键引脚端口及极性;
其他抖动的高低电平回调函数仅用于调试验证。