OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8276|回复: 33

分享一个自己写的按键扫描软件模块

[复制链接]

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-1-28 23:14:57 | 显示全部楼层 |阅读模式
本帖最后由 ianhom 于 2016-11-2 15:11 编辑

一直在做代码模块化的工作,分享一个自己写的按键扫描模块,欢迎大家试用。   
本模块计划长期更新,本人能力有限,有错误之处欢迎指正交流,我将根据大家的反馈进行修改优化,提供更可靠的软件模块给大家。   

**更新说明**
   
**2016年6月15日**: 本模块目前更新至V1.10,相比于采用switch状态机的V1.00版本,V1.10的状态机采用了状态转移表来实现,在增加状态数量和功能的前提下,不仅提高了执行效率,同时减少了10%的FLASH消耗。额外提供简易初始化方式和应用demo以便大家快速验证。
两个效果展示1、音量控制:短按单次加减,长按持续加减;2、按键实际状态(按下/释放)显示。


## 说明:
本模块可灵活配置如下参数:
* 按键数量;
* 按键常开常闭类型(未按下时稳态值);
* 按键检测使能/非能控制;
* 按键去抖时间;
* 按键长按识别时间;
* 每个按键独立的按键状态获取函数。
   
本模块可以为上层提供:
* 按键事件(瞬态):
  * BTN_PRESSED_EVT            按键刚被短按;
  * BTN_LONG_PRESSED_EVT   按键刚被长按;
  * BTN_S_RELEASED_EVT       按键刚从短按状态下释放;
  * BTN_L_RELEASED_EVT       按键刚从长按状态下释放。
  
* 按键状态(稳态):
  * BTN_IDLE_ST                   按键处于空闲状态(未按下);
  * BTN_PRESS_AFT_ST          按键处于短按状态;
  * BTN_HOLDING_ST            按键处于长按状态。

## 资源消耗参考
M0+内核 + IAR 下 Low优化等级:  

             内容              |        区域          |       大小         | 说明                                                 
-------------------------------- | ---------------------- | ------------------- | ------------------------------------------------
        代码/只读数据      |       Flash          |    468字节      | 程序416字节 + 52字节的状态转移表                                                   
配置参数/状态/接口变量 | RAM静态储存区  | n*20 + 8字节 | n为按键数量  
临时变量/函数调用开销  |    RAM栈区域     |     40字节      | 无   
         
## 使用方法
1. 将Btn_SM_Module.c文件导入IDE工程,增加Btn_SM_Module.h和Btn_SM_Config.h的包含路径。
2. 修改Btn_SM_Config.h中MAX_BTN_CH的值为按键数量, 如需要为每个按键定义独立的“按键状态获取函数”,可在Btn_SM_Config.h定义 __BTN_SM_SPECIFIED_BTN_ST_FN
3. 编写系统时间获取函数,要求反馈系统ms时钟,类型为 uint16 (*)();
4. 编写按键状态获取函数,要求根据输入参数通道号反馈对应按键状态(逻辑1/0),类型为 uint8 (*)(uint8 u8Ch)。
5. 参考Btn_SM_Demo.c的代码,若需快速配置,可调用Btn_SM_Easy_Init()函数初始化模块;或参考Btn_SM_Easy_Init()函数,创建配置参数结构体实体并根据需求进行初始化配置(按键编号、去抖时间,长按时间,按键常态、是否使能按键、按键状态获取函数)和进行初始化工作。
8. 轮询Btn_Channel_Process()进行各个按键通道的状态,通过该函数输出参数确定按键返回事件及状态。
9. 通过Btn_Func_En_Dis()可在初始化之后屏蔽或启用按键功能。

##使用示例
[mw_shl_code=c,true]

#ifndef _BTN_SM_CONFIG_
#define _BTN_SM_CONFIG_

#ifdef __cplusplus
extern "C" {
#endif
  
#define MAX_BTN_CH                   (3)         /* Max number of buttons, please define it here */

/* If you want to use specified button state getting function, define the MACRO */
#define __BTN_SM_SPECIFIED_BTN_ST_FN             /* Use specified button state getting function  */

#ifdef __cplusplus
}
#endif

#endif /* _BTN_SM_CONFIG_ */


/******************************************************************************
* File       : Btn_SM_Module.c
* Function   : Provide demo of button state machine module.
* description: It is a demo for button state machine module.              
* Version    : V1.00
* Author     : Ian
* Date       : 15th Jun 2016
* History    :  No.  When          Who   Version   What        
*               1    15/Jun/2016   Ian   V1.00     Create      
******************************************************************************/

#include "common.h"
#include "KL25_Lpt_Time.h"
#include "Btn_SM_Config.h"
#include "Btn_SM_Module.h"

const uint8* cg_apu8State[] = {"RESS_EVT            |  __  ",\
                               "SHORT_RELEASE_EVT    |  __  ",\
                               "LONG_RELEASE_EVT     |  __  ",\
                               "RESSED_EVT          |  __  ",\
                               "JUST_LONG_PRESSED_EVT|  __  ",\
                               "SHORT_RELEASED_EVT   |  __  ",\
                               "LONG_RELEASED_EVT    |  __  ",\
                               "JUST_PRESS           |    | ",\
                               "SHORT_RELEASED       | |    ",\
                               "LONG_RELEASED        | |    ",\
                               "IDLE                 | |    ",\
                               "SHORT_PRESSED        |    | ",\
                               "LONG_PRESSED         |    | ",\
                               "NONE_EVT                    "};

const uint8* cg_apu8Vol[]   = {"Vol:[               ]",\
                               "Vol:[|              ]",\
                               "Vol:[||             ]",\
                               "Vol:[|||            ]",\
                               "Vol:[||||           ]",\
                               "Vol:[|||||          ]",\
                               "Vol:[||||||         ]",\
                               "Vol:[|||||||        ]",\
                               "Vol:[||||||||       ]",\
                               "Vol:[|||||||||      ]",\
                               "Vol:[||||||||||     ]",\
                               "Vol:[|||||||||||    ]",\
                               "Vol:[||||||||||||   ]",\
                               "Vol:[|||||||||||||  ]",\
                               "Vol:[|||||||||||||| ]",\
                               "Vol:[|||||||||||||||]"};

static T_BTN_RESULT sg_atBtn[MAX_BTN_CH];

/******************************************************************************
* Name       : uint8 Btn_St_Get(uint8 u8Ch)
* Function   : Provide button state according to the channel number
* Input      : uint8 u8Ch  1~255          The number of button channel
* Output:    : None
* Return     : uint8       BTN_STATE_0    0-State
*                          BTN_STATE_1    1-State
*                          BTN_ERROR      Failed
* description: None.
* Version    : V1.00
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint8 Btn_St_Get(uint8 u8Ch)
{
    uint8 u8Temp;
    if(u8Ch == 1)        /* If it is button 1 */
    {   /* Get the button state */
        u8Temp = (!(GPIOA_PDIR & (1 << 5)));
    }
    else if(u8Ch == 2)    /* If it is button 2 */
    {   /* Get the button state */
        u8Temp = (!(GPIOA_PDIR & (1 << 4)));
    }
    else if(u8Ch == 3)    /* If it is button 3 */
    {   /* Get the button state */
        u8Temp = (!(GPIOA_PDIR & (1 << 12)));
    }
    else/* If the button channel number is invalid */
    {   /* Return error */
        u8Temp = BTN_ERROR;
    }
    return  u8Temp;
}

/******************************************************************************
* Name       : uint16 System_Time(void)
* Function   : Provide system time in ms
* Input      : None
* Output:    : None
* Return     : uint16      0~65535        The system time in ms
* description: None.
* Version    : V1.00
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint16 System_Time(void)
{
    uint16 u16Temp = (uint16)App_GetSystemTime_ms();
    return u16Temp;
}

/******************************************************************************
* Name       : int main (void)
* Function   : A demo shows how to use button state machine module
* Input      : None
* Output:    : None
* Return     : None
* description: There are three buttons:
*              Button 3 is used to switch operating mode between "button state
*              display" and "Vol control". Long pressed to swtich.
*              Button 1 is used to show button state in "button state display"
*              mode, and increase vol in "Vol control" mode.
*              Button 2 is used to decrease vol in "Vol control" mode only.
* Version    : V1.10
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
int main (void)
{   
    uint8 u8Idx,u8Vol = 0,u8FnCode = 1;;
    uint16 u16Tm = App_GetSystemTime_ms();

    /* Init hardware */
    Gpio_Init();
    Timer_Init();

    /* Esay_Init */
    Btn_SM_Easy_Init(System_Time, Btn_St_Get);

    while(1)
    {   
        /* Button process and get button event & state */
        for(u8Idx = 1; u8Idx <= MAX_BTN_CH; u8Idx++)
        {
            Btn_Channel_Process(u8Idx, &(sg_atBtn[u8Idx-1]));
        }

        /* If the button 3 is long pressed */
        if(BTN_LONG_PRESSED_EVT == sg_atBtn[2].u8Evt)
        {   /* Switch operating mode */
            u8FnCode = !u8FnCode;
        }
        
        /* If it is the "button state" operation mode  */
        if(u8FnCode)     
        {   /* If there is any event with button 1 */
            if(sg_atBtn[0].u8Evt != BTN_NONE_EVT)
            {   /* Display the event of button 1 */
                printf("EVENT:%s\n",cg_apu8State[sg_atBtn[0].u8Evt]);
            }
            /* If the refresh time is up */
            if(App_GetSystemDelay_ms(u16Tm) > 100)
            {   /* Display the state of button 1 */
                printf("STATE:%s\n",cg_apu8State[sg_atBtn[0].u8State]);
                u16Tm = App_GetSystemTime_ms();
            }
        }
      
        /* If it is the "Vol control" operating mode */
        else
        {   /* If button 1 is short pressed (event) */
            if(sg_atBtn[0].u8Evt == BTN_PRESSED_EVT)
            {
                if(15 != u8Vol)
                {   /* Increase the vol within the range */
                    u8Vol++;
                }
                /* Reset the timing */
                u16Tm = App_GetSystemTime_ms();
            }
            /* If button 1 is in long pressed state */
            if(sg_atBtn[0].u8State == BTN_HOLDING_ST)
            {   /* If re-do time is up */
                if(App_GetSystemDelay_ms(u16Tm) > 150)
                {
                    if(15 != u8Vol)
                    {   /* Increase the vol within the range */
                        u8Vol++;
                    }
                    /* Reset the timing */
                    u16Tm = App_GetSystemTime_ms();
                }
            }
            
            /* If button 2 is short pressed (event) */
            if(sg_atBtn[1].u8Evt == BTN_PRESSED_EVT)
            {
                if(0 != u8Vol)
                {   /* Decrease the vol within the range */
                    u8Vol--;
                }
                /* Reset the timing */
                u16Tm = App_GetSystemTime_ms();
            }
            /* If button 2 is in long pressed state */
            if(sg_atBtn[1].u8State == BTN_HOLDING_ST)
            {   /* If re-do time is up */
                if(App_GetSystemDelay_ms(u16Tm)>150)
                {
                    if(0 != u8Vol)
                    {   /* Decrease the vol within the range */
                        u8Vol--;
                    }
                    /* Reset the timing */
                    u16Tm = App_GetSystemTime_ms();
                }
            }
            printf("%s\n", cg_apu8Vol[u8Vol]);
        }     
    }
    return 0;
}

/*End of file*/





[/mw_shl_code]

源代码下载:
最新版本:
Btn_State_Machine_Module V1.10.zip (13.67 KB, 下载次数: 1372)
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-28 23:15:21 | 显示全部楼层
本帖最后由 ianhom 于 2016-6-17 23:10 编辑

Btn_SM_Module.c 源代码
[mw_shl_code=c,true]
/******************************************************************************
* File       : Btn_SM_Module.c
* Function   : Check button state and return short/long press or release events and states.
* description: Button state machine module. It realise button short/long press or release
*              checking and return responding events and states.
*              - Following parameters are configurable:
*                  * Number of buttons.
*                  * Normal state of each buttons.
*                  * Enable/Disable control of each buttons.
*                  * Debounce checking time of each buttons.
*                  * Long-pressed time of each buttons.
*                  * Button state getting function of each buttons.
*
*              - Following events (transient) can be provided
*                  * BTN_PRESSED_EVT        Button is just short pressed                       
*                  * BTN_LONG_PRESSED_EVT   Button is just long pressed                              
*                  * BTN_S_RELEASED_EVT     Button is just released from short pressed                 
*                  * BTN_L_RELEASED_EVT     Button is just released from long pressed   
*
*              - Following states (stable-state) can be provided
*                  * BTN_IDLE_ST            Button stays in idle state (Not pressed)
*                  * BTN_PRESS_AFT_ST       Button stays in short pressed state
*                  * BTN_HOLDING_ST         Button stays in long pressed state              
*              __________
*              HOW TO USE(Quick start):
*              Step 1: Modify MAX_BTN_CH in Btn_SM_Config.h with desired button numbers
*              Step 2: Create a "uint16 (*)()" function to get system time according to
*                      your hardware.
*              Step 3: Create a "uint8 (*)(uint8 u8Ch)" function to get button status(0/1)
*                      according to your hardware.
*              Step 4: Call "Btn_SM_Easy_Init()" to get previous interface functions.
*                      If defined __BTN_SM_SPECIFIED_BTN_ST_FN, each button will use
*                      specified button state getting function.
*              Step 7: Poll "Btn_Channel_Process()" per channel to get events and states.
*
*              NOTE: For advanced configuration, please use Btn_General_Init() and
*                    Btn_channel_Init().
*              NOTE: Button function can be enabled/disabled by calling "Btn_Func_En_Dis().
*              NOTE: This software is modularization designed, so "Btn_SM_Module.c" and
*                    "Btn_SM_Module.h" should work without any modification.
*         
* Version    : V1.10
* Author     : Ian
* Date       : 15th Jun 2016
* History    :  No.  When          Who   Version   What        
*               1    27/Jan/2016   Ian   V1.00     Create      
*               2    15/Jun/2016   Ian   V1.10     Re-design the state machine with state
*                                                  table, return "Event" and "State"                                                         
******************************************************************************/

#include "common.h"
#include "Btn_SM_Config.h"
#include "Btn_SM_Module.h"

/* State transition table */
const uint8 cg_aau8StateMachine[BTN_STATE_NUM][BTN_TRG_NUM] =
{
    /*  Situation 1  */    /*  Situation 2 */    /*  Situation 3  */     /* Situation 4  */
    /* Btn NOT press */    /* Btn press    */    /* Btn NOT press */     /* Btn press    */
    /* Time NOT out  */    /* Time NOT out */    /* Time out      */     /* Time out     */
    {BTN_PRESS_PRE_ST    , BTN_PRESS_PRE_ST    , BTN_PRESS_PRE_ST     ,  BTN_PRESS_PRE_ST    },    /* BTN_PRESS_EVT        */
    {BTN_SHORT_RELEASE_ST, BTN_SHORT_RELEASE_ST, BTN_SHORT_RELEASE_ST ,  BTN_SHORT_RELEASE_ST},    /* BTN_S_RELEASE_EVT    */
    {BTN_LONG_RELEASE_ST , BTN_LONG_RELEASE_ST , BTN_LONG_RELEASE_ST  ,  BTN_LONG_RELEASE_ST },    /* BTN_L_RELEASE_EVT    */
    {BTN_PRESS_AFT_ST    , BTN_PRESS_AFT_ST    , BTN_PRESS_AFT_ST     ,  BTN_PRESS_AFT_ST    },    /* BTN_PRESSED_EVT      */
    {BTN_HOLDING_ST      , BTN_HOLDING_ST      , BTN_HOLDING_ST       ,  BTN_HOLDING_ST      },    /* BTN_LONG_PRESSED_EVT */
    {BTN_IDLE_ST         , BTN_IDLE_ST         , BTN_IDLE_ST          ,  BTN_IDLE_ST         },    /* BTN_S_RELEASED_EVT   */
    {BTN_IDLE_ST         , BTN_IDLE_ST         , BTN_IDLE_ST          ,  BTN_IDLE_ST         },    /* BTN_L_RELEASED_EVT   */
    {BTN_IDLE_ST         , BTN_PRESS_PRE_ST    , BTN_IDLE_ST          ,  BTN_PRESSED_EVT     },    /* BTN_PRESS_PRE        */
    {BTN_SHORT_RELEASE_ST, BTN_PRESS_AFT_ST    , BTN_S_RELEASED_EVT   ,  BTN_PRESS_AFT_ST    },    /* BTN_SHORT_RELEASE    */
    {BTN_LONG_RELEASE_ST , BTN_HOLDING_ST      , BTN_L_RELEASED_EVT   ,  BTN_HOLDING_ST      },    /* BTN_LONG_RELEASE     */
    {BTN_IDLE_ST         , BTN_PRESS_EVT       , BTN_IDLE_ST          ,  BTN_PRESSED_EVT     },    /* BTN_IDLE             */  
    {BTN_S_RELEASE_EVT   , BTN_PRESS_AFT_ST    , BTN_S_RELEASE_EVT    ,  BTN_LONG_PRESSED_EVT},    /* BTN_PRESS_AFT        */
    {BTN_L_RELEASE_EVT   , BTN_HOLDING_ST      , BTN_L_RELEASED_EVT   ,  BTN_HOLDING_ST      }     /* BTN_HOLDING          */
};

static T_BTN_PARA *sg_aptBtnPara[MAX_BTN_CH] = {0};          /* Parameter interface          */
static T_BTN_ST    sg_atBtnSt[MAX_BTN_CH]    = {0};          /* Running status               */
static PF_GET_TM   sg_pfGetTm                = NULL;         /* Function to get general time */

#ifndef __BTN_SM_SPECIFIED_BTN_ST_FN
static PF_GET_BTN  sg_pfGetBtnSt             = NULL;         /* Function to get button state */
#endif

/******************************************************************************
* Name       : void Btn_Func_En_Dis(uint8 u8Ch, uint8 u8EnDis)
* Function   : Enable or disable button function
* Input      : uint8 u8Ch       1~255               The number of setting button channel
*              uint8 u8EnDis    BTN_FUNC_ENABLE     Enable the button function
*                               BTN_FUNC_DISABLE    Disable the button function
* Output:    : None
* Return     : None
* description: If the button function is enabled, the button events and states could
*              be returned according to the button operation; If the button function
*              is disabled, the returned event and state will be BTN_NONE_EVT and
*              BTN_DIS_STeven button is operated.
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
void Btn_Func_En_Dis(uint8 u8Ch, uint8 u8EnDis)
{   
    sg_aptBtnPara[u8Ch - 1]->u8BtnEn = u8EnDis;      /* Enable or Disable the button functions */
    sg_atBtnSt[u8Ch - 1].u8BtnSt     = BTN_IDLE_ST;  /* Reset the state machine of button      */
}

/******************************************************************************
* Name       : uint8 Btn_General_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
* Function   : General init operation of button state machine.
* Input      : PF_GET_TM pfGetTm       Function to get gengeral time
*              PF_GET_BTN pfGetBtnSt   Function to get button state(0/1)
* Output:    : None
* Return     : BTN_ERROR               Input parameter is invalid
*              SUCCESS                 Init operation is successed
* description: This function should be called once before use button checking.
*              This function get two necessary interface function:
*              "pfGetTm()":Function to get gengeral time;
*              "pfGetBtnSt":Function to get button state(0/1). (if the MACRO
*              __BTN_SM_SPECIFIED_BTN_ST_FN is NOT defined)
*
*              NOTE:If the general init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
uint8 Btn_General_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
{
    /* Check if the input parameter is valid or NOT */
    if(NULL == pfGetTm)
    {   /* Return if the parameter is invalid */
        return BTN_ERROR;
    }
   
    /* If the "Get time" function has NOT registered yet */
    if(NULL == sg_pfGetTm)
    {   /* Register the function */
        sg_pfGetTm = pfGetTm;
    }
    /* If the "Get time" function has already registered, Do NOT re-register */


#ifndef __BTN_SM_SPECIFIED_BTN_ST_FN
    /* Check if the input parameter is valid or NOT */
    if(NULL == pfGetBtnSt)
    {   /* Return if the parameter is invalid */
        return BTN_ERROR;
    }   

    /* If the "Get button state" function has NOT registered yet */
    if(NULL == sg_pfGetBtnSt)
    {   /* Register the function */
        sg_pfGetBtnSt = pfGetBtnSt;
    }
    /* If the "Get button state" function has already registered, Do NOT re-regiter */
#else
    /* If each button use specified button state getting function*/
    /* pfGetBtnSt will be useless                                */
    (void)pfGetBtnSt;             /* Avoid warning from complier */
#endif

    return SUCCESS;
}

/******************************************************************************
* Name       : uint8 Btn_Channel_Init(uint8 u8Ch ,T_BTN_PARA *ptBtnPara)
* Function   : Init operation for each button channel
* Input      : uint8       u8Ch      1~255      The number of setting button channel
*              T_BTN_PARA *ptBtnPara             Parameter of each button channel
* Output:    : None
* Return     : BTN_ERROR        Input parameter is invalid
*              SUCCESS          Init operation is successed
* description: After general init operation, call this function for each channel
*              before button checking.  
*              This function save the parameter structure pointer for further
*              operation, and init running state of such channel.
*
*              NOTE:If the channel init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
uint8 Btn_Channel_Init(uint8 u8Ch ,T_BTN_PARA *ptBtnPara)
{   
    /* Check if the channel number is invalid */
    if((0 == u8Ch) || (u8Ch > MAX_BTN_CH))
    {   /* If the channel number is NOT in the range of 1~MAX_BTN_CH, return error */
        return BTN_ERROR;
    }

    /* Check if the input parameter is invalid */
    if(NULL == ptBtnPara)
    {   /* Return error if parameter is invalid */
        return BTN_ERROR;
    }

#ifdef __BTN_SM_SPECIFIED_BTN_ST_FN
    /* Check if the input parameter is invalid */
    if(NULL == ptBtnPara->pfGetBtnSt)
    {   /* Return error if parameter is invalid */
        return BTN_ERROR;
    }
#endif

    sg_aptBtnPara[u8Ch - 1]      = ptBtnPara;   /* Get the parameters              */
    sg_atBtnSt[u8Ch - 1].u8BtnSt = BTN_IDLE_ST; /* Init the state of state machine */   

    return SUCCESS;
}

/******************************************************************************
* Name       : uint8 Btn_Channel_Process(uint8 u8Ch, T_BTN_RESULT* ptBtnRes)
* Function   : Main process of button checking
* Input      : uint8         u8Ch       1~255                 The number of setting button channel
* Output:    : T_BTN_RESULT* ptBtnRes
*                             ->u8Evt   BTN_PRESSED_EVT       Button is just short pressed
*                                       BTN_LONG_PRESSED_EVT  Button is just long pressed
*                                       BTN_S_RELEASED_EVT    Button is just released from short press
*                                       BTN_L_RELEASED_EVT    Button is just released from long press
*                             ->u8State BTN_IDLE_ST           Button is in idle state
*                                       BTN_PRESS_AFT_ST      Button is in short pressed state
*                                       BTN_HOLDING_ST        Button is in long pressed state
*                                       BTN_DIS_ST            Butoon is disabled
* Return     : BTN_ERROR     Input parameter or button state is invalid
*              SUCCESS       Process operation is successed
* description: This function should be called after general init and channel init.
*              This function should be polled to check button event and state.
*              ------------------------------------------------------------------------------
*             | No.1 Demo of long press and release with debounce check
*             |  ________                                                ______________ ________
*             |          |  Debounce |               |                  |   Debounce   |
*             |    Idle  | Press PRE |  Press AFT    |    Holding       |   Long Rls   |  Idle   
*             |  (output)|           |   (output)    |   (output)       |              | (output)     
*             |          |___________|_______________|__________________|              |
*             |          |           |               |                  |              |
*             |          V           V               V                  V              V
*             |     Press Evt    Pressed Evt   Long pressed Evt   Long release Evt   Long released Evt
*             |                   (output)        (output)                             (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Press Evt" and start timing for debounce check, then
*             |       switch to "Press PRE". If the button is release at this time, it will
*             |       switch back to "Idle". If the button is still pressed and debounce check
*             |       time is out, switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is released now,
*             |       please refer to No.2 demo. when long-pressed time is out in "Press AFT",
*             |       switch to "Long pressed Evt" and output event to caller. Then switch to
*             |       "Holding". If button is released at this moment, switch to "Long release
*             |       Evt" and start timing for debounce check. Then switch to "Long Rls". If
*             |       button is pressed again, swtich back to "Holding". If button is still
*             |       released and debounce time is out, siwtch to "Long released Evt" and
*             |       output event to caller. At the last, switch to "Idle" for next checking.
*              ------------------------------------------------------------------------------
*             | No.2 Demo of short press and release with debounce check
*             |  ________                             _____________ ________
*             |          |  Debounce |               |  Debounce   |
*             |    Idle  | Press PRE |   Press AFT   |  Short Rls  |  Idle         
*             |  (output)|           |   (output)    |             | (output)
*             |          |___________|_______________|             |
*             |          |           |               |             |
*             |          V           V               V             V
*             |     Press Evt    Pressed Evt   Short release Evt   Short release Evt
*             |                   (output)                            (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Press Evt" and start timing for debounce check, then
*             |       switch to "Press PRE". If the button is release at this time, it will
*             |       switch back to "Idle". If the button is still pressed and debounce check
*             |       time is out, switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is still pressed,
*             |       and long-press time is out, please refer to No.1 demo. If the button is
*             |       released in "Press AFT", switch to "Short release Evt" and start timing
*             |       for debounce check. Then switch to "Short Rls". If button is pressed again,
*             |       swtich back to "Press AFT". If button is still released and debounce time
*             |       is out, siwtch to "Short released Evt" and output event to caller. At the
*             |       last, switch to "Idle" for next checking.
*              ------------------------------------------------------------------------------
*             | No.3 Demo of long press and release without debounce check
*             |  ________                                    ________
*             |          |               |                  |
*             |    Idle  |  Press AFT    |    Holding       |  Idle   
*             |  (output)|   (output)    |   (output)       | (output)     
*             |          |_______________|__________________|
*             |          |               |                  |
*             |          V               V                  V
*             |     Pressed Evt   Long pressed Evt   Long released Evt
*             |       (output)        (output)             (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is released now,
*             |       please refer to No.4 demo. when long-pressed time is out in "Press AFT",
*             |       switch to "Long pressed Evt" and output event to caller. Then switch to
*             |       "Holding". If button is released at this moment, switch to "Long released
*             |       Evt" and output event to caller. At the last, switch to "Idle" for next
*             |       checking.
*              ------------------------------------------------------------------------------
*             | No.4 Demo of short press and release without debounce check
*             |  ________                 ________
*             |          |               |
*             |    Idle  |   Press AFT   |  Idle         
*             |  (output)|   (output)    | (output)
*             |          |_______________|
*             |          |               |
*             |          V               V
*             |     Pressed Evt    Short release Evt
*             |      (output)          (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is still pressed,
*             |       and long-press time is out, please refer to No.3 demo. If the button is
*             |       released in "Press AFT", switch to "Short released Evt" and output event
*             |       to caller. At the last, switch to "Idle" for next checking.
*              -----------------------------------------------------------------------------
* Version    : V1.10
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint8 Btn_Channel_Process(uint8 u8Ch, T_BTN_RESULT* ptBtnRes)
{
    uint8 u8TmOut  = 0;
    uint8 u8NextSt = 0x00;  
    uint8 u8BtnSt;

    T_BTN_PARA *ptBtnPara = sg_aptBtnPara[u8Ch - 1];
    T_BTN_ST   *ptBtnSt   = &(sg_atBtnSt[u8Ch - 1]);
        
    /* Check if the channel number is invalid */
    if((0 == u8Ch) || (u8Ch > MAX_BTN_CH))
    {   /* If the channel number is NOT in the range of 1~MAX_BTN_CH, return error */
        return BTN_ERROR;
    }

    ptBtnRes->u8Evt   = BTN_NONE_EVT;         /* Clear the old event */
    ptBtnRes->u8State = ptBtnSt->u8BtnSt;     /* Fill current state  */

    /* Check if the button function is enabled or NOT */
    if(ptBtnPara->u8BtnEn != BTN_FUNC_ENABLE)
    {   /* If the function is NOT enabled, return none event and disabled state */
        ptBtnRes->u8State = BTN_DIS_ST;
        return SUCCESS;
    }
    /* If the function is enabled, go on */
            
    /* Get the state of button first */
#ifdef __BTN_SM_SPECIFIED_BTN_ST_FN   
    u8BtnSt = ptBtnPara->pfGetBtnSt(u8Ch); /* Use the specified one */
#else
    u8BtnSt = sg_pfGetBtnSt(u8Ch);         /* Use common one        */
#endif
        
    /* If the state invalid */
    if(BTN_ERROR == u8BtnSt)
    {   /* Return error */
        return BTN_ERROR;
    }  

    /************************ Do operations of state ***************************/   
    /* If the current state is :           */
    /* Button just pressed event           */
    /* Button just short released event    */
    /* Button just long released event     */
    /* Button pressed totally event        */
    /* Button is long pressed              */
    /* Button short released totally event */
    /* Button long released totally event  */
    if(ptBtnSt->u8BtnSt < BTN_PRESS_PRE_ST)
    {
        ptBtnRes->u8State = cg_aau8StateMachine[ptBtnSt->u8BtnSt][0];    /* Use the next state as result */
        
        /* If the current state is :           */
        /* Button just pressed event           */
        /* Button just short released event    */
        /* Button just long released event     */        
        if(ptBtnSt->u8BtnSt < BTN_PRESSED_EVT)
        {
            ptBtnSt->u16DebounceOldTm = sg_pfGetTm();        /* Start timing debounce time */
        }

        /* If the current state is :           */
        /* Button pressed totally event        */
        /* Button is long pressed              */
        /* Button short released totally event */
        /* Button long released totally event  */
        else
        {
            ptBtnRes->u8Evt = ptBtnSt->u8BtnSt;              /* Update event of result */

            /* If the current state is :       */
            /* Button pressed totally event    */
            if(ptBtnSt->u8BtnSt == BTN_PRESSED_EVT)
            {
                ptBtnSt->u16LongPressOldTm = sg_pfGetTm();   /* Start timing long-press time */
            }
        }
    }

    /* If the current state is :           */
    /* Button is pressed before debounce                   */
    /* Button is released before debounce form short press */
    /* Button is released before debounce form long press  */
    else if(ptBtnSt->u8BtnSt < BTN_IDLE_ST)
    {
        ptBtnRes->u8State += BTN_GO_BACK_OFFSET;    /* Do not provide a debounce state with the result  */
        /* Check if debounce time is out */                  
        u8TmOut = ((sg_pfGetTm() - ptBtnSt->u16DebounceOldTm) >= ptBtnPara->u16DebounceTm);   
    }

    /* If the current state is :              */
    /* Button is short pressed after debounce */
    else if(ptBtnSt->u8BtnSt == BTN_PRESS_AFT_ST)
    {   /* Check if long-press time is out */
        u8TmOut = ((sg_pfGetTm() - ptBtnSt->u16LongPressOldTm) >= ptBtnPara->u16LongPressTm);
    }
        
    /* If the current state is :           */
    /* Button is NOT pressed or released   */
    /* Button is long pressed              */
    /* ----------DO NOTHING!!------------- */


    /*************************** Find the Next state ***************************/
    /* Check if button is press or NOT */
    if(u8BtnSt != ptBtnPara->u8NormalSt)
    {   /* If button is pressed, update index number  */
        u8NextSt++;
    }
   
    /* Check if the debounce or long-press time is out or NOT */
    if(u8TmOut)
    {   /* If time is out, update index number */
        u8NextSt += BTN_TM_TRG_EVT_OFFSET;
    }
   
    /************************* Do the state transition *************************/  
    ptBtnSt->u8BtnSt = cg_aau8StateMachine[ptBtnSt->u8BtnSt][u8NextSt];
   
    return SUCCESS;
}


/******************************************************************************
* Name       : uint8 Btn_SM_Easy_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
* Function   : Easy init operation of button state machine for quick start.
* Input      : PF_GET_TM pfGetTm       Function to get gengeral time
*              PF_GET_BTN pfGetBtnSt   Function to get button state(0/1)
* Output:    : None
* Return     : BTN_ERROR               Input parameter is invalid
*              SUCCESS                 Init operation is successed
* description: This function should be called once before use button checking.
*              This function get two necessary interface function:
*              "pfGetTm()":Function to get gengeral time;
*              "pfGetBtnSt":Function to get button state(0/1). (if the MACRO
*              __BTN_SM_SPECIFIED_BTN_ST_FN is NOT defined)
*
*              NOTE:If the esay init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint8 Btn_SM_Easy_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
{
    static T_BTN_PARA s_atBtnPara[MAX_BTN_CH];
    uint8 u8Idx,u8Temp;

    /* Button general init */
    u8Temp = Btn_General_Init(pfGetTm, pfGetBtnSt);
    if(BTN_ERROR == u8Temp)
    {
        return BTN_ERROR;
    }
   
    for(u8Idx = 0; u8Idx < MAX_BTN_CH; u8Idx++)
    {      
        /* Configure the button parameters */
        s_atBtnPara[u8Idx].u8Ch           = u8Idx + 1;       /* Channel number                  */
        s_atBtnPara[u8Idx].u16DebounceTm  = 50;              /* Debounce time is 50 ms          */
        s_atBtnPara[u8Idx].u16LongPressTm = 1000;            /* Long-press time is 1000ms       */
        s_atBtnPara[u8Idx].u8NormalSt     = 0;               /* The normal state of button is 0 */
        s_atBtnPara[u8Idx].u8BtnEn        = BTN_FUNC_ENABLE; /* Enable button at the beginning  */
#ifdef __BTN_SM_SPECIFIED_BTN_ST_FN
        s_atBtnPara[u8Idx].pfGetBtnSt     = pfGetBtnSt;      /* Function to get button state    */
#endif

        /* Button channels init */
        Btn_Channel_Init(u8Idx + 1 ,&(s_atBtnPara[u8Idx]));
    }
    return SUCCESS;
}


/* end-of-file */




[/mw_shl_code]

机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-28 23:15:40 | 显示全部楼层
本帖最后由 ianhom 于 2016-6-17 23:11 编辑

Btn_SM_Module.h 头文件
[mw_shl_code=c,true]
/******************************************************************************
* File       : Btn_SM_Module.h
* Function   : Check button state and return short/long press or release events and states.
* description: Button state machine module. It realise button short/long press or release
*              checking and return responding events and states.
*              - Following parameters are configurable:
*                  * Number of buttons.
*                  * Normal state of each buttons.
*                  * Enable/Disable control of each buttons.
*                  * Debounce checking time of each buttons.
*                  * Long-pressed time of each buttons.
*                  * Button state getting function of each buttons.
*
*              - Following events (transient) can be provided
*                  * BTN_PRESSED_EVT        Button is just short pressed                       
*                  * BTN_LONG_PRESSED_EVT   Button is just long pressed                              
*                  * BTN_S_RELEASED_EVT     Button is just released from short pressed                 
*                  * BTN_L_RELEASED_EVT     Button is just released from long pressed   
*
*              - Following states (stable-state) can be provided
*                  * BTN_IDLE_ST            Button stays in idle state (Not pressed)
*                  * BTN_PRESS_AFT_ST       Button stays in short pressed state
*                  * BTN_HOLDING_ST         Button stays in long pressed state              
*              __________
*              HOW TO USE(Quick start):
*              Step 1: Modify MAX_BTN_CH in Btn_SM_Config.h with desired button numbers
*              Step 2: Create a "uint16 (*)()" function to get system time according to
*                      your hardware.
*              Step 3: Create a "uint8 (*)(uint8 u8Ch)" function to get button status(0/1)
*                      according to your hardware.
*              Step 4: Call "Btn_SM_Easy_Init()" to get previous interface functions.
*                      If defined __BTN_SM_SPECIFIED_BTN_ST_FN, each button will use
*                      specified button state getting function.
*              Step 7: Poll "Btn_Channel_Process()" per channel to get events and states.
*
*              NOTE: For advanced configuration, please use Btn_General_Init() and
*                    Btn_channel_Init().
*              NOTE: Button function can be enabled/disabled by calling "Btn_Func_En_Dis().
*              NOTE: This software is modularization designed, so "Btn_SM_Module.c" and
*                    "Btn_SM_Module.h" should work without any modification.
*         
* Version    : V1.10
* Author     : Ian
* Date       : 15th Jun 2016
* History    :  No.  When          Who   Version   What        
*               1    27/Jan/2016   Ian   V1.00     Create      
*               2    15/Jun/2016   Ian   V1.10     Re-design the state machine with state
*                                                  table, return "Event" and "State"                                                         
******************************************************************************/




#ifndef _BTN_SM_MODULE_
#define _BTN_SM_MODULE_

#ifdef __cplusplus
extern "C" {
#endif
  
#ifndef MAX_BTN_CH
#define MAX_BTN_CH                   (1)         /* Max number of buttons, please define it in upper layer */
#endif

#define BTN_STATE_NUM                (13)        /* The number of states in state machine               */
#define BTN_TRG_NUM                  (4)         /* The number of trigger event in state machine        */

/* States of button state machine */
#define BTN_PRESS_EVT                (0)         /* Button just pressed event                           */
#define BTN_S_RELEASE_EVT            (1)         /* Button just short released event                    */
#define BTN_L_RELEASE_EVT            (2)         /* Button just long released event                     */
#define BTN_PRESSED_EVT              (3)         /* Button pressed totally event                        */
#define BTN_LONG_PRESSED_EVT         (4)         /* Button is long pressed                              */
#define BTN_S_RELEASED_EVT           (5)         /* Button short released totally event                 */
#define BTN_L_RELEASED_EVT           (6)         /* Button long released totally event                  */

#define BTN_PRESS_PRE_ST             (7)         /* Button is pressed before debounce                   */
#define BTN_SHORT_RELEASE_ST         (8)         /* Button is released before debounce form short press */
#define BTN_LONG_RELEASE_ST          (9)         /* Button is released before debounce form long press  */
#define BTN_IDLE_ST                  (10)        /* Button is NOT pressed or released                   */
#define BTN_PRESS_AFT_ST             (11)        /* Button is short pressed after debounce              */
#define BTN_HOLDING_ST               (12)        /* Button is long pressed                              */
#define BTN_NONE_EVT                 (13)        /* No event with the button                            */
#define BTN_DIS_ST                   (14)        /* Button is disabled                                  */

#define BTN_GO_BACK_OFFSET           (3)         /* Offset betwen debounce state and previous ones      */
#define BTN_TM_TRG_EVT_OFFSET        (2)         /* Offset for time out trigger in state table          */

#define SUCCESS                      (0)         /* Correct condition                 */
#define BTN_ERROR                    (0xFF)      /* Error condition                   */

#ifdef NULL
#undef NULL
#define NULL                         (0)         /* Null type potinter                                  */
#endif


/* Parameters */
#define BTN_FUNC_ENABLE              (1)         /* Button input function is enabled  */
#define BTN_FUNC_DISABLE             (0)         /* Button input function is disabled */

#define BTN_NORMAL_0                 (0)         /* The normal state of button is "0" */
#define BTN_NORMAL_1                 (1)         /* The normal state of button is "1" */

#define BTN_STATE_0                  (0)         /* The state of button is "0"        */
#define BTN_STATE_1                  (1)         /* The state of button is "1"        */

/* Function type definition */
/******************************************************************************
* Name       : uint8  (*)(uint8 u8Ch)
* Function   : Get the button state 0/1
* Input      : uint8 u8Ch       1~255     The number of setting button channel
* Output:    : None
* Return     : BTN_STATE_0      Button state is logic "0"
*              BTN_STATE_1      Button state is logic "1"
*              BTN_ERROR        Failed to get button state.
* description: This function should return the button state according to the channel number
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
typedef uint8  (*PF_GET_BTN)(uint8 u8Ch);      

/******************************************************************************
* Name       : uint16 (*)()
* Function   : Get the time of General time
* Input      : None
* Output:    : None
* Return     : 0~65535  Free running general clock time for system(for example, 1ms timer)
* description: This function should return the general clock time.
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
typedef uint16 (*PF_GET_TM)();      


/* Structure type definition */
/*******************************************************************************
* Structure  : T_BTN_PARA
* Description: Structure of button state machine parameters.
* Memebers   : Type    Member          Range             Descrption     
               PF_GET_BTN  pfGetBtnSt                    Function to get button state   
               uint16  u16LongPressTm  0~65535           Time units for long press distinguish
               uint16  u16DebounceTm   0~65535           Time uints for debounce check        
               uint8   u8BtnEn         BTN_FUNC_ENABLE   Enable button function
                                       BTN_FUNC_DISABLE  Disable button function   
               uint8   u8NormalSt      BTN_NORMAL_0      The normal state of button is "0"
                                       BTN_NORMAL_1      The normal state of button is "1"
               uint8   u8Ch            1~255             Channel number of button      
*******************************************************************************/
typedef struct _T_BTN_PARA_
{
#ifdef __BTN_SM_SPECIFIED_BTN_ST_FN
    PF_GET_BTN  pfGetBtnSt;         /* Function to get button state    */
#endif
    uint16      u16LongPressTm;     /* Time for long press distinguish */
    uint16      u16DebounceTm;      /* Time for debounce check         */
    uint8       u8BtnEn;            /* Enable or disable function      */
    uint8       u8NormalSt;         /* Normal(stable) state of button  */
    uint8       u8Ch;               /* Channel number of button        */
}T_BTN_PARA;

/*******************************************************************************
* Structure  : T_BTN_RESULT
* Description: Structure of button result: Event & State.
* Memebers   : Type    Member   Range                 Descrption     
*              uint8   u8Evt    BTN_PRESSED_EVT       Button is just short pressed
*                               BTN_LONG_PRESSED_EVT  Button is just long pressed
*                               BTN_S_RELEASED_EVT    Button is just released from short press
*                               BTN_L_RELEASED_EVT    Button is just released from long press
*              uint8   u8State  BTN_IDLE_ST           Button is in idle state
*                               BTN_PRESS_AFT_ST      Button is in short pressed state
*                               BTN_HOLDING_ST        Button is in long pressed state
*                               BTN_DIS_ST            Butoon is disabled
*******************************************************************************/
typedef struct _T_BTN_RESULT
{
    uint8       u8Evt;         /* Event of button */
    uint8       u8State;       /* State of button */
}T_BTN_RESULT;


/*******************************************************************************
* Structure  : T_BTN_ST
* Description: Structure of button running status.
* Memebers   : Type    Member             Range              Descrption     
               uint16  u16DebounceOldTm   0~65535            The start time of debounce check   
               uint16  u16LongPressOldTm  0~65535            The start time of long press check
               uint8   u8BtnSt            BTN_IDLE           Button is NOT pressed or released           
                                          BTN_PRESS_PRE      Button is pressed before debounce                  
                                          BTN_PRESS_AFT      Button is short pressed after debounce              
                                          BTN_HOLDING        Button is long pressed                              
                                          BTN_SHORT_RELEASE  Button is released before debounce form short press
                                          BTN_LONG_RELEASE   Button is released before debounce form long press  
*******************************************************************************/
typedef struct _T_BTN_ST_
{
    uint16  u16DebounceOldTm;       /* The start time of debounce check   */
    uint16  u16LongPressOldTm;      /* The start time of long press check */
    uint8   u8BtnSt;                /* The state of state machine         */
}T_BTN_ST;


/* Function declaration */
/******************************************************************************
* Name       : void Btn_Func_En_Dis(uint8 u8Ch, uint8 u8EnDis)
* Function   : Enable or disable button function
* Input      : uint8 u8Ch       1~255               The number of setting button channel
*              uint8 u8EnDis    BTN_FUNC_ENABLE     Enable the button function
*                               BTN_FUNC_DISABLE    Disable the button function
* Output:    : None
* Return     : None
* description: If the button function is enabled, the button events and states could
*              be returned according to the button operation; If the button function
*              is disabled, the returned event and state will be BTN_NONE_EVT and
*              BTN_DIS_STeven button is operated.
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
void Btn_Func_En_Dis(uint8 u8Ch, uint8 u8EnDis);

/******************************************************************************
* Name       : uint8 Btn_General_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
* Function   : General init operation of button state machine.
* Input      : PF_GET_TM pfGetTm       Function to get gengeral time
*              PF_GET_BTN pfGetBtnSt   Function to get button state(0/1)
* Output:    : None
* Return     : BTN_ERROR               Input parameter is invalid
*              SUCCESS                 Init operation is successed
* description: This function should be called once before use button checking.
*              This function get two necessary interface function:
*              "pfGetTm()":Function to get gengeral time;
*              "pfGetBtnSt":Function to get button state(0/1). (if the MACRO
*              __BTN_SM_SPECIFIED_BTN_ST_FN is NOT defined)
*
*              NOTE:If the general init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
uint8 Btn_General_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt);

/******************************************************************************
* Name       : uint8 Btn_Channel_Init(uint8 u8Ch ,T_BTN_PARA *ptBtnPara)
* Function   : Init operation for each button channel
* Input      : uint8       u8Ch      1~255      The number of setting button channel
*              T_BTN_PARA *ptBtnPara             Parameter of each button channel
* Output:    : None
* Return     : BTN_ERROR        Input parameter is invalid
*              SUCCESS          Init operation is successed
* description: After general init operation, call this function for each channel
*              before button checking.  
*              This function save the parameter structure pointer for further
*              operation, and init running state of such channel.
*
*              NOTE:If the channel init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 27th Jan 2016
******************************************************************************/
uint8 Btn_Channel_Init(uint8 u8Ch ,T_BTN_PARA *ptBtnPara);

/******************************************************************************
* Name       : uint8 Btn_Channel_Process(uint8 u8Ch, T_BTN_RESULT* ptBtnRes)
* Function   : Main process of button checking
* Input      : uint8         u8Ch       1~255                 The number of setting button channel
* Output:    : T_BTN_RESULT* ptBtnRes
*                             ->u8Evt   BTN_PRESSED_EVT       Button is just short pressed
*                                       BTN_LONG_PRESSED_EVT  Button is just long pressed
*                                       BTN_S_RELEASED_EVT    Button is just released from short press
*                                       BTN_L_RELEASED_EVT    Button is just released from long press
*                             ->u8State BTN_IDLE_ST           Button is in idle state
*                                       BTN_PRESS_AFT_ST      Button is in short pressed state
*                                       BTN_HOLDING_ST        Button is in long pressed state
*                                       BTN_DIS_ST            Butoon is disabled
* Return     : BTN_ERROR     Input parameter or button state is invalid
*              SUCCESS       Process operation is successed
* description: This function should be called after general init and channel init.
*              This function should be polled to check button event and state.
*              ------------------------------------------------------------------------------
*             | No.1 Demo of long press and release with debounce check
*             |  ________                                                ______________ ________
*             |          |  Debounce |               |                  |   Debounce   |
*             |    Idle  | Press PRE |  Press AFT    |    Holding       |   Long Rls   |  Idle   
*             |  (output)|           |   (output)    |   (output)       |              | (output)     
*             |          |___________|_______________|__________________|              |
*             |          |           |               |                  |              |
*             |          V           V               V                  V              V
*             |     Press Evt    Pressed Evt   Long pressed Evt   Long release Evt   Long released Evt
*             |                   (output)        (output)                             (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Press Evt" and start timing for debounce check, then
*             |       switch to "Press PRE". If the button is release at this time, it will
*             |       switch back to "Idle". If the button is still pressed and debounce check
*             |       time is out, switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is released now,
*             |       please refer to No.2 demo. when long-pressed time is out in "Press AFT",
*             |       switch to "Long pressed Evt" and output event to caller. Then switch to
*             |       "Holding". If button is released at this moment, switch to "Long release
*             |       Evt" and start timing for debounce check. Then switch to "Long Rls". If
*             |       button is pressed again, swtich back to "Holding". If button is still
*             |       released and debounce time is out, siwtch to "Long released Evt" and
*             |       output event to caller. At the last, switch to "Idle" for next checking.
*              ------------------------------------------------------------------------------
*             | No.2 Demo of short press and release with debounce check
*             |  ________                             _____________ ________
*             |          |  Debounce |               |  Debounce   |
*             |    Idle  | Press PRE |   Press AFT   |  Short Rls  |  Idle         
*             |  (output)|           |   (output)    |             | (output)
*             |          |___________|_______________|             |
*             |          |           |               |             |
*             |          V           V               V             V
*             |     Press Evt    Pressed Evt   Short release Evt   Short release Evt
*             |                   (output)                            (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Press Evt" and start timing for debounce check, then
*             |       switch to "Press PRE". If the button is release at this time, it will
*             |       switch back to "Idle". If the button is still pressed and debounce check
*             |       time is out, switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is still pressed,
*             |       and long-press time is out, please refer to No.1 demo. If the button is
*             |       released in "Press AFT", switch to "Short release Evt" and start timing
*             |       for debounce check. Then switch to "Short Rls". If button is pressed again,
*             |       swtich back to "Press AFT". If button is still released and debounce time
*             |       is out, siwtch to "Short released Evt" and output event to caller. At the
*             |       last, switch to "Idle" for next checking.
*              ------------------------------------------------------------------------------
*             | No.3 Demo of long press and release without debounce check
*             |  ________                                    ________
*             |          |               |                  |
*             |    Idle  |  Press AFT    |    Holding       |  Idle   
*             |  (output)|   (output)    |   (output)       | (output)     
*             |          |_______________|__________________|
*             |          |               |                  |
*             |          V               V                  V
*             |     Pressed Evt   Long pressed Evt   Long released Evt
*             |       (output)        (output)             (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is released now,
*             |       please refer to No.4 demo. when long-pressed time is out in "Press AFT",
*             |       switch to "Long pressed Evt" and output event to caller. Then switch to
*             |       "Holding". If button is released at this moment, switch to "Long released
*             |       Evt" and output event to caller. At the last, switch to "Idle" for next
*             |       checking.
*              ------------------------------------------------------------------------------
*             | No.4 Demo of short press and release without debounce check
*             |  ________                 ________
*             |          |               |
*             |    Idle  |   Press AFT   |  Idle         
*             |  (output)|   (output)    | (output)
*             |          |_______________|
*             |          |               |
*             |          V               V
*             |     Pressed Evt    Short release Evt
*             |      (output)          (output)
*             |
*             | Note: At the first stage, button is in "Idle" state, if the button is pressed,
*             |       it will switch to "Pressed Evt", start long-pressed timing and output
*             |       event to caller, then switch to "Press AFT". If button is still pressed,
*             |       and long-press time is out, please refer to No.3 demo. If the button is
*             |       released in "Press AFT", switch to "Short released Evt" and output event
*             |       to caller. At the last, switch to "Idle" for next checking.
*              -----------------------------------------------------------------------------
* Version    : V1.10
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint8 Btn_Channel_Process(uint8 u8Ch, T_BTN_RESULT* ptBtnRes);

/******************************************************************************
* Name       : uint8 Btn_SM_Easy_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt)
* Function   : Easy init operation of button state machine for quick start.
* Input      : PF_GET_TM pfGetTm       Function to get gengeral time
*              PF_GET_BTN pfGetBtnSt   Function to get button state(0/1)
* Output:    : None
* Return     : BTN_ERROR               Input parameter is invalid
*              SUCCESS                 Init operation is successed
* description: This function should be called once before use button checking.
*              This function get two necessary interface function:
*              "pfGetTm()":Function to get gengeral time;
*              "pfGetBtnSt":Function to get button state(0/1). (if the MACRO
*              __BTN_SM_SPECIFIED_BTN_ST_FN is NOT defined)
*
*              NOTE:If the esay init is failed, DO NOT continue!!
* Version    : V1.00
* Author     : Ian
* Date       : 15th Jun 2016
******************************************************************************/
uint8 Btn_SM_Easy_Init(PF_GET_TM pfGetTm, PF_GET_BTN pfGetBtnSt);



#ifdef __cplusplus
}
#endif

#endif /* _BTN_SM_MODULE_ */





[/mw_shl_code]


机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

5

主题

163

帖子

0

精华

高级会员

Rank: 4

积分
615
金钱
615
注册时间
2011-11-7
在线时间
180 小时
发表于 2016-1-29 00:25:30 | 显示全部楼层
楼主代码写得很漂亮。但站在使用者的角度来说我觉得有点复杂。
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-1-29 08:22:29 | 显示全部楼层
楼主大牛
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

4

主题

35

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2013-4-23
在线时间
98 小时
发表于 2016-1-29 09:06:48 | 显示全部楼层
好贴,多谢分享。
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 12:34:03 | 显示全部楼层
夜猫煮茶 发表于 2016-1-29 00:25
楼主代码写得很漂亮。但站在使用者的角度来说我觉得有点复杂。

感谢回复!
确实初始化和参数配置麻烦一点,我看看如何简化一下,既能保证配置灵活性,又能初始操作简单。
感谢回复~~
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 12:35:13 | 显示全部楼层

不敢当不敢当,小弟还在初级阶段慢慢摸索,希望能得到论坛大神的指点
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 12:35:48 | 显示全部楼层
dalianlwd 发表于 2016-1-29 09:06
好贴,多谢分享。

感谢回复!希望能得到前辈指点~
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
发表于 2016-1-29 12:45:16 | 显示全部楼层
感觉复杂了。。。
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 13:32:52 | 显示全部楼层
solo 发表于 2016-1-29 12:45
感觉复杂了。。。

感谢回复~
是初始化的部分复杂了吗,正打算简化一下;
还是按键的处理过程复杂了,功能还是想保留一定灵活性,不过代码的size打算在进一步优化一下。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1835
金钱
1835
注册时间
2014-6-27
在线时间
981 小时
发表于 2016-1-29 14:19:38 | 显示全部楼层
ianhom 发表于 2016-1-29 13:32
感谢回复~
是初始化的部分复杂了吗,正打算简化一下;
还是按键的处理过程复杂了,功能还是想保留一定 ...

很好啊,自己写的,能在应用中稳定灵活使用就行了。
回复 支持 反对

使用道具 举报

5

主题

163

帖子

0

精华

高级会员

Rank: 4

积分
615
金钱
615
注册时间
2011-11-7
在线时间
180 小时
发表于 2016-1-29 22:02:26 | 显示全部楼层
ianhom 发表于 2016-1-29 12:34
感谢回复!
确实初始化和参数配置麻烦一点,我看看如何简化一下,既能保证配置灵活性,又能初始操作简单 ...

主要是我太菜了(这是实话),所以追求用起来非常简单的方法
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 22:11:43 | 显示全部楼层
夜猫煮茶 发表于 2016-1-29 22:02
主要是我太菜了(这是实话),所以追求用起来非常简单的方法

太谦虚了,很感谢你的建议!
模块功能丰富,一样可以把接口做的友好易用的,已经有好多人提意见让我优化接口了。这方面我还要努力。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

3

主题

548

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1383
金钱
1383
注册时间
2015-2-3
在线时间
197 小时
发表于 2016-1-29 22:17:50 | 显示全部楼层
本帖最后由 yyx112358 于 2016-1-29 22:19 编辑

很棒的东西啊,这东西很花时间的。
给个建议啊,建议封装成类似于对象的结构,结构清晰而且容易升级,比如原子的usmart:
//usmart控制管理器
struct _m_usmart_dev
{
        struct _m_usmart_nametab *funs;        //函数名指针

        void (*init)(u8);                                //初始化
        u8 (*cmd_rec)(u8*str);                       //识别函数名及参数
        void (*exe)(void);                                 //执行
        void (*scan)(void);             //扫描
        u8 fnum;                                                   //函数数量
        u8 pnum;                        //参数数量
        u8 id;                                                        //函数id
        u8 sptype;                                                //参数显示类型(非字符串参数):0,10进制;1,16进制;
        u16 parmtype;                                        //参数的类型
        u8  plentbl[MAX_PARM];                  //每个参数的长度暂存表
        u8  parm[PARM_LEN];                          //函数的参数
        u8 runtimeflag;                                        //0,不统计函数执行时间;1,统计函数执行时间,注意:此功能必须在USMART_ENTIMX_SCAN使能的时候,才有用
        u32 runtime;                                        //运行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
};
也可以参考ST官方HAL库的方法,可以解决楼主的初始化配置问题
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 22:27:47 | 显示全部楼层
yyx112358 发表于 2016-1-29 22:17
很棒的东西啊,这东西很花时间的。
给个建议啊,建议封装成类似于对象的结构,结构清晰而且容易升级,比如 ...

感谢回复~
很棒的建议~工作中用的版本是类似于对象的结构,不过我做的不够彻底。
后来考虑模块运行的可靠性,就把参数部分和模块运行部分的分离开了,模块的运行状态都为static修饰,仅内部可见,确保模块运行的状态不会被其他模块修改。而把配置参数留到外部,由上层提供并注册到模块内部,至于对对象的操作这点我一直做得不好,设计的接口还是通过头文件的函数提供出去。。。。加上我对面向对象的夹生理解,就形成了现在的版本。。。。
感谢建议,我再往面向对象的方向考虑考虑,感谢!!
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-1-29 22:34:07 | 显示全部楼层
TinyBoy 发表于 2016-1-29 14:19
很好啊,自己写的,能在应用中稳定灵活使用就行了。

感谢回复!
自己工作中使用感觉不错,就把他从平台中抽离了出来,希望能做的更通用,分享给大家。不过从大家的回复来看,我的接口做的还是不够友好易用,功能实现方面也不够简洁(size有点大),本想带点面向对象编程方式,但牺牲了不少RAM做接口,估计51用起来还是有点吃力。还有很多要优化的地方。
回头要潜心学习下你分享的按键扫描的程序,很值得学习!!感谢分享!
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

22

主题

117

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
798
金钱
798
注册时间
2015-10-24
在线时间
160 小时
发表于 2016-6-8 12:02:51 | 显示全部楼层
谢谢楼主分享
楼主写的代码格式是我们学习的目标啊
回复 支持 反对

使用道具 举报

11

主题

200

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1154
金钱
1154
注册时间
2014-11-9
在线时间
228 小时
发表于 2016-6-8 12:05:04 | 显示全部楼层
刚刚学到,按键要高效,不能延时啊
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-8 14:56:25 | 显示全部楼层
Time_Zero 发表于 2016-6-8 12:02
谢谢楼主分享
楼主写的代码格式是我们学习的目标啊

感谢支持!
说好持续更新的,没有做到,惭愧
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-8 14:57:50 | 显示全部楼层
黄伟达 发表于 2016-6-8 12:05
刚刚学到,按键要高效,不能延时啊

恩,按键判断不能阻塞,耗时挺长的
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

11

主题

200

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1154
金钱
1154
注册时间
2014-11-9
在线时间
228 小时
发表于 2016-6-8 15:15:26 | 显示全部楼层
ianhom 发表于 2016-6-8 14:57
恩,按键判断不能阻塞,耗时挺长的

做项目的时候绝对不能出现卡死在某个程序的
回复 支持 反对

使用道具 举报

55

主题

243

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1608
金钱
1608
注册时间
2012-12-30
在线时间
241 小时
发表于 2016-6-8 15:51:03 | 显示全部楼层
cool。。。。一直在追赶LZ
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-17 23:14:46 | 显示全部楼层
更新模块代码V1.10,使用状态转移表重新编写状态机;代码size减小,效率增加;同时反馈按键事件和状态;额外提供简易初始化方式和应用demo以便大家快速验证。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-20 17:34:02 | 显示全部楼层
更新了个视频,这样直观一点
1、音量控制:短按单次加减,长按持续加减;
2、按键实际状态(按下/释放)显示。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

15

主题

184

帖子

0

精华

高级会员

Rank: 4

积分
647
金钱
647
注册时间
2014-4-29
在线时间
299 小时
发表于 2016-6-20 19:23:26 | 显示全部楼层
多谢楼主分享,楼主辛苦了,不管用不用的到,这个东西看一看就能让人受益
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-6-7
在线时间
4 小时
发表于 2016-6-21 08:29:11 | 显示全部楼层
很不错,顶一个!!
回复 支持 反对

使用道具 举报

3

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2016-5-29
在线时间
13 小时
发表于 2016-6-21 09:11:29 | 显示全部楼层
很赞,而且代码格式感觉好清爽,膜拜中
回复 支持 反对

使用道具 举报

0

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
171
金钱
171
注册时间
2016-3-16
在线时间
48 小时
发表于 2016-6-21 11:35:14 | 显示全部楼层
妥妥的大神 膜拜一下
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-21 13:31:26 | 显示全部楼层
xianshasaman 发表于 2016-6-20 19:23
多谢楼主分享,楼主辛苦了,不管用不用的到,这个东西看一看就能让人受益

感谢支持!好在有坛友们的建议,智慧是大家的
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-21 13:31:55 | 显示全部楼层
xjstudystm 发表于 2016-6-21 08:29
很不错,顶一个!!

感谢支持!!
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-21 13:33:11 | 显示全部楼层
Ice丶Dragon 发表于 2016-6-21 09:11
很赞,而且代码格式感觉好清爽,膜拜中

感谢感谢!!我的注释还是不够简练,太长,慢慢修改~
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
 楼主| 发表于 2016-6-21 13:34:47 | 显示全部楼层
一颗烂荔枝 发表于 2016-6-21 11:35
妥妥的大神 膜拜一下

不敢当大神,我仅是社会主义接班人
感谢支持!
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

0

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2018-3-22
在线时间
18 小时
发表于 2018-8-2 09:09:34 | 显示全部楼层
谢谢楼主分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-18 03:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表