电子产业一站式赋能平台

PCB联盟网

搜索
查看: 774|回复: 0
收起左侧

南向设备:实现S1,S2,User三个物理按键的独立事件

[复制链接]

2607

主题

2607

帖子

7472

积分

高级会员

Rank: 5Rank: 5

积分
7472
发表于 2020-12-30 19:56:56 | 显示全部楼层 |阅读模式
南向设备:实现S1,S2,User三个物理按键的独立事件, 实现S1,S2,User三个物理按键的独立事件,咱们在按下S1按钮后会在串口窗口上打印S1 -> 4,说明了S1按钮被按下,S2按钮就是,按下去的那一刻会打印S2 -> 1,松开后会打印S2 -> 4,还有就是长按user按钮会打印一个USR -> 2,这些按钮都是可以自定义设置的,俄罗斯方块就是典型例子,可以通过按键控制方块的位置,控制方块的方向等操作。



代码如下:

dt_btn_demo.c

#include <stdio.h>

#include <unistd.h>

#include “ohos_init.h“

#include “cmsis_os2.h“

#include “dt_btn_util.h“



static void Button_jltf_Callback(const char* sender, BtnEvent event)

{

     printf(“[dt4sw] Button_jltf_Callback() : %s -> %d\n“, sender, event);



     if( event == Pressed )     { /* Pressed == 1     按下事件处理代码 */ }

     if( event == LongPressed ) { /* LongPressed == 2 长按事件处理代码 */ }

     if( event == Released )    { /* Released == 4    释放事件处理代码 */ }

}



static void* DTBtnDemo_jltf_Task(const char* arg)

{

     int ret = 0;



     printf(“[dt4sw] DTBtnDemo_jltf_Task()\n“);



     ret += DTButton_Init(); // 初始化按键事件处理上下文



     /* 设置GPIO_8按键的回调函数,同时需要响应按下,释放以及长按三个事件 */

     /* 按键触发顺序: Pressed -> LongPressed(optional) -> Released */

     ret += DTButton_Enable(“GPIO_8“, Button_jltf_Callback, Pressed | LongPressed | Released);



     /* 分别设置S1, S2, USER按键的回调函数 */

     ret += DTButton_Enable(“S1“, Button_jltf_Callback, Released);

     ret += DTButton_Enable(“S2“, Button_jltf_Callback, Pressed | LongPressed | Released);

     ret += DTButton_Enable(“USR“, Button_jltf_Callback, LongPressed);



     if( ret == 0 )

     {

         while(1)

         {

             usleep(100000);

         }



         DTButton_Disable(“GPIO_8“);  // 取消 GPIO_8 按键的所有按键事件

         DTButton_Disable(“S1“);      // 取消 S1 按键的所有按键事件

         DTButton_Disable(“S2“);      // 取消 S2 按键的所有按键事件

         DTButton_Disable(“USR“);     // 取消 USER 按键的所有按键事件



         DTButton_Deinit(); // 关闭按钮事件处理上下文

     }

     else

     {

         printf(“[dt4sw] Falied to enable button!\n“);

     }



     return (void*)arg;

}



static void DTBtnDemo_Entry(void)

{

     osThreadAttr_t attr = {0};



     printf(“[dt4sw] DTBtnDemo_Entry()\n“);



     attr.name = “DTBtnDemo_jltf_Task“;

     attr.attr_bits = 0U;

     attr.cb_mem = NULL;

     attr.cb_size = 0U;

     attr.stack_mem = NULL;

     attr.stack_size = 1024;

     attr.priority = osPriorityNormal;



     if (osThreadNew((osThreadFunc_t)DTBtnDemo_jltf_Task, NULL, &attr) == NULL)

     {

         printf(“[dt4sw] Falied to create DTBtnDemo Task!\n“);

     }

}



SYS_RUN(DTBtnDemo_Entry);







dt_btn_util.c



#include <unistd.h>

#include <string.h>

#include “cmsis_os2.h“

#include “hi_systick.h“

#include “hi_adc.h“

#include “wifiiot_gpio.h“

#include “wifiiot_gpio_ex.h“

#include “dt_btn_util.h“



#define BUTTON_STACK_SIZE   2048

#define PRESS_INTERVAL      20000

#define LOOP_INTERVAL       40000

#define LONG_PRESS_INTERVAL 64

#define LONG_PRESS_END      0xFFFF

#define INDEX_ERR           -1

#define MAX_KEY_NUM         SSU_None



enum

{

     ADC_USR_MIN = 5,

     ADC_USR_MAX = 228,

     ADC_S1_MIN,

     ADC_S1_MAX  = 512,

     ADC_S2_MIN,

     ADC_S2_MAX  = 854

};



enum

{

     SSU_USR = 15,

     SSU_S1,

     SSU_S2,

     SSU_None

};



typedef struct

{

     const char* name;

     unsigned int index;

     unsigned int event;

     PBtnCallback callback;

} ButtonInfo;



typedef struct

{

     int pressClicked;

     int longPressClicked;

     int longPressInterval;

     int releaseClicked;

} ButtonClicked;



static volatile int gToClick = 0;

static volatile int gIsInit = 0;

static const char* gBtnName[] = {

     “GPIO_0“,  “GPIO_1“,  “GPIO_2“,  “GPIO_3“,  “GPIO_4“,

     “GPIO_5“,  “GPIO_6“,  “GPIO_7“,  “GPIO_8“,  “GPIO_9“,

     “GPIO_10“, “GPIO_11“, “GPIO_12“, “GPIO_13“, “GPIO_14“,

     “USR“,     “S1“,      “S2“,

     NULL

};



static volatile ButtonInfo gBtnInfo[MAX_KEY_NUM] = {0};

static volatile ButtonClicked gBtnClicked[MAX_KEY_NUM] = {0};



static void OnButtonPressed(char* arg);

static void OnButtonReleased(char* arg);



static int GetIndex(const char* name)

{

     int ret = INDEX_ERR;

     int i = 0;



     while( gBtnName
&& name )
     {
         if( strcmp(gBtnName, name) == 0 )
         {
             ret = i;
             break;
         }

         i++;
     }

     return ret;
}

static int GetSSU(void)
{
     unsigned short data = 0;
     int ret = SSU_None;

     if( hi_adc_read(HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0) == 0 )
     {
         if( (ADC_USR_MIN <= data) && (data <= ADC_USR_MAX) )  ret = SSU_USR;
         if( (ADC_S1_MIN  <= data) && (data <= ADC_S1_MAX ) )  ret = SSU_S1;
         if( (ADC_S2_MIN  <= data) && (data <= ADC_S2_MAX ) )  ret = SSU_S2;
     }

     return ret;
}

static void OnButtonPressed(char* arg)
{
     static volatile hi_u64 sHisTick = 0;
     WifiIotIoName gpio = (WifiIotIoName)arg;
     hi_u64 tick = hi_systick_get_cur_tick();

     gToClick = (tick - sHisTick) > PRESS_INTERVAL;

     if( gToClick )
     {
         sHisTick = tick;

         gBtnClicked[gpio].pressClicked = 1;

         GpioRegisterIsRFunc(gpio,
                             WIFI_IOT_INT_TYPE_EDGE,
                             WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH,
                             OnButtonReleased, arg);
     }         
}

static void OnButtonReleased(char* arg)
{
     WifiIotIoName gpio = (WifiIotIoName)arg;

     if( gToClick )
     {
         gBtnClicked[gpio].releaseClicked = 1;

         GpioRegisterIsrFunc(gpio,
                             WIFI_IOT_INT_TYPE_EDGE,
                             WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                             OnButtonPressed, arg);
     }
}

static void SSUEventtrigger(void)
{
     static hi_u64 sHisTick = 0;
     static int sPreKey = SSU_None;

     int curKey = GetSSU();

     if( (sPreKey == SSU_None) && (curKey != SSU_None) )
     {
         hi_u64 tick = hi_systick_get_cur_tick();
         int toClick = (tick - sHisTick) > PRESS_INTERVAL;

         if( toClick )
         {
             gBtnClicked[curKey].pressClicked = 1;

             sPreKey = curKey;

             sHisTick = tick;
         }
     }
     else if( (sPreKey != SSU_None) && (curKey == SSU_None) )
     {
         gBtnClicked[sPreKey].releaseClicked = 1;

         sPreKey = curKey;
     }
}

static void EventHandler(void)
{
     int i = 0;

     for(i=0; i<MAX_KEY_NUM; i++)
     {
         const char* name = gBtnInfo.name;

         if( gBtnClicked.pressClicked )
         {
             if( gBtnInfo.event & Pressed )
                 gBtnInfo.callback(name, Pressed);

             gBtnClicked.pressClicked = 0;
             gBtnClicked.longPressInterval = 0;
         }

         if( gBtnClicked.longPressInterval < LONG_PRESS_END )
         {
             gBtnClicked.longPressInterval++;
         }

         if( gBtnClicked.longPressInterval == LONG_PRESS_INTERVAL )
         {
             gBtnClicked.longPressClicked = 1;
         }

         if( gBtnClicked.longPressClicked )
         {
             if( gBtnInfo.event & LongPressed )
                 gBtnInfo.callback(name, LongPressed);

             gBtnClicked.longPressClicked = 0;
             gBtnClicked.longPressInterval = LONG_PRESS_END;
         }

         if( gBtnClicked.releaseClicked )
         {
             if( gBtnInfo.event & Released )
                 gBtnInfo.callback(name, Released);

             gBtnClicked.releaseClicked = 0;
             gBtnClicked.longPressInterval= LONG_PRESS_END;
         }
     }
}

static void* DTButton_Task(const char* arg)
{
     while( gIsInit )
     {
         SSUEventTrigger();
         EventHandler();
         usleep(LOOP_INTERVAL);
     }

     return (void*)arg;
}

int DTButton_Init(void)
{
     int ret = (int)GpioInit();

     if( ret == (int)HI_ERR_GPIO_REPEAT_INIT )
     {
         ret = 0;
     }

     if( !ret && !gIsInit )
     {
         int i = 0;
         osThreadAttr_t attr = {0};

         for(i=0; i<MAX_KEY_NUM; i++)
         {
             gBtnClicked.longPressInterval = LONG_PRESS_END;
         }

         attr.name = “DTButton_Task“;
         attr.attr_bits = 0U;
         attr.cb_mem = NULL;
         attr.cb_size = 0U;
         attr.stack_mem = NULL;
         attr.stack_size = BUTTON_STACK_SIZE;
         attr.priority = osPriorityNormal;

         ret += (osThreadNew((osThreadFunc_t)DTButton_Task, NULL, &attr) == NULL);

         gIsInit = (ret == 0);
     }

     return ret;
}

void DTButton_Deinit(void)
{
     gIsInit = 0;
}

int DTButton_Enable(const char* name, PBtnCallback callback, unsigned int event)
{
     int ret = -1;

     if( callback )
     {
         int index = name ? GetIndex(name) : INDEX_ERR;

         if( (WIFI_IOT_IO_NAME_GPIO_0 <= index) && (index < WIFI_IOT_IO_NAME_MAX) )
         {   
             ret  = IoSetFunc((WifiIotIoName)index, 0);
             ret += GpioSetDir((WifiIotIoName)index, WIFI_IOT_GPIO_DIR_IN);
             ret += IoSetPull((WifiIotIoName)index, WIFI_IOT_IO_PULL_UP);
             ret += GpioRegisterIsrFunc((WifiIotIoName)index,
                                 WIFI_IOT_INT_TYPE_EDGE,
                                 WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                                 OnButtonPressed, (char*)index);                  
         }
         else if( (SSU_USR <= index) && (index < MAX_KEY_NUM) )
         {
             ret = 0;
         }

         if( ret == 0 )
         {
             gBtnInfo[index].name = name;
             gBtnInfo[index].index = index;
             gBtnInfo[index].event = event;
             gBtnInfo[index].callback = callback;
         }
     }

     return ret;
}

void DTButton_Disable(const char* name)
{
     int gpio = name ? GetIndex(name) : INDEX_ERR;

     if( gpio != INDEX_ERR )
     {
         gBtnInfo[gpio].name = 0;
         gBtnInfo[gpio].index = 0;
         gBtnInfo[gpio].event = 0;
         gBtnInfo[gpio].callback = 0;
     }
}


dt_btn_util.h


#ifndef DT_BTNUTIL_H
#define DT_BTNUTIL_H

/*
   Description:
       Button event ID.
*/
typedef enum
{
     None = 0,
     Pressed = 1,
     LongPressed = 2,
     Released = 4
} BtnEvent;

/*
   Description:
       Button event callback function pointer type.

   Parameter:
       sender -- string name for the GPIO button
       event  -- event ID which trigger the function call

   Return Value:
       0     -- Success
       other -- Failure
*/
typedef void (*PBtnCallback)(const char* sender, BtnEvent event);

/*
   Description:
       To initialize button event process context.

   Parameter:
       None

   Return Value:
       0     -- Success
       other -- Failure
*/
int DTButton_Init(void);

/*
   Description:
       To close button event process context.

   Parameter:
       None

   Return Value:
       None
*/
void DTButton_Deinit(void);

/*
   Description:
       To register callback functions for a GPIO button.

   Parameter:
       name     -- target GPIO port name for a phisical button
       callback -- callback function for button event
       event    -- the target button event to trigger callback

   Return Value:
       0     -- Success
       other -- Failure
*/
int DTButton_Enable(const char* name, PBtnCallback callback, unsigned int event);

/*
   Description:
       To unregister callback functions for a GPIO button.

   Parameter:
       name -- target GPIO port name for a phisical button

   Return Value:
       None
*/
void DTButton_Disable(const char* name);

#endif

本文内容参考了唐佐林老师的部分公开代码。


回复

使用道具 举报

发表回复

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

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表