560|0

43

帖子

0

资源

一粒金砂(中级)

【国民技术N32G457评测】五、移植小型嵌入式多按键库 MultiButton [复制链接]

本帖最后由 yang377156216 于 2022-2-22 15:25 编辑

【前言】

在嵌入式软件开发中,通常需要独立按键支持多种功能,如:支持连击、双击、长按、组合连击、任意连击等等。之前使用过硬汉的按键检测程序,如果直接使用的话是没有问题,但是考虑到需要扩展多种按键组合以及多种功能还是有诸多不方便之处,到处搜罗了一遍网上的 FIFO Button ,最后找到个 开源好用的 “MultiButton” 库,打算移植到测评开发板上来。

【MultiButton】

MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。

【MultiButton 使用方法】

1.先申请一个按键结构

struct Button button1;

2.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平

button_init(&button1, read_button_pin, 0);

3.注册按键事件

button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler);
button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_Handler);
...

4.启动按键

button_start(&button1);

5.设置一个5ms间隔的定时器循环调用后台处理函数

while(1) {
    ...
    if(timer_ticks == 5) {
        timer_ticks = 0;
​
        button_ticks();
    }
}

【MultiButton 特性】

MultiButton 使用C语言实现,基于面向对象方式设计思路,每个按键对象单独用一份数据结构管理:

struct Button {
    uint16_t ticks;
    uint8_t  repeat: 4;
    uint8_t  event : 4;
    uint8_t  state : 3;
    uint8_t  debounce_cnt : 3;
    uint8_t  active_level : 1;
    uint8_t  button_level : 1;
    uint8_t  (*hal_button_Level)(void);
    BtnCallback  cb[number_of_event];
    struct Button* next;
};

这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。

【MultiButton 按键事件】

事件 说明
PRESS_DOWN 按键按下,每次按下都触发
PRESS_UP 按键弹起,每次松开都触发
PRESS_REPEAT 重复按下触发,变量repeat计数连击次数
SINGLE_CLICK 单击按键事件
DOUBLE_CLICK 双击按键事件
LONG_PRESS_START 达到长按时间阈值时触发一次
LONG_PRESS_HOLD 长按期间一直触发

 

【MultiButton 移植】

Step 1. 获取到

提示词:如果您需要查看本帖隐藏内容,请登录或者注册
,往之前的模板工程中添加源码 ,且添加头文件路径:

image.png

 Step 2. 添加 bsp 文件 key.c 和 key.h ,主要实现 板载按键的初始化以及multi button 库的初始化,另外注册各个事件以及其实现,demo中实现了 SW1 的单击 、 SW2 的双击 、 SW3和Wakeup组合按键的长按3个事件,通过不同的 LED闪烁来直观感受各种按键功能。

struct Button btn1;
struct Button btn2;
struct Button btn3_wakeup;


/**
 * @brief  read wakeup pin value.
 * @param
 * @param
 */
uint8_t Read_ButtonWakeup_GPIO(void)
{
    return GPIO_ReadInputDataBit(KEY_WAKEUP_PORT, KEY_WAKEUP_INPUT_PIN);
}

/**
 * @brief  read key1 pin value.
 * @param
 * @param
 */
uint8_t Read_ButtonSW1_GPIO(void)
{
    return GPIO_ReadInputDataBit(KEY_SW1_PORT, KEY_SW1_PIN);
}

/**
 * @brief  read key2 pin value.
 * @param
 * @param
 */
uint8_t Read_ButtonSW2_GPIO(void)
{
    return GPIO_ReadInputDataBit(KEY_SW2_PORT, KEY_SW2_PIN);
}

/**
 * @brief  read key3&wakeup pin value.
 * @param
 * @param
 */
uint8_t Read_ButtonSW3_Wakeup_GPIO(void)
{
    if (!GPIO_ReadInputDataBit(KEY_SW3_PORT, KEY_SW3_PIN))
    {
        if (GPIO_ReadInputDataBit(KEY_WAKEUP_PORT, KEY_WAKEUP_INPUT_PIN))
            return 0;//active level is 0
    }
    return 1;//inactive level is 1
}

/**
 * @brief  SW1 btn single click event handler.
 * @param  btn
 * @param
 */
void BTN1_SINGLE_Click_Handler(void *btn)
{
    //do something...
    LedBlink(PORT_GROUP1, LED1_PIN);
}

/**
 * @brief  SW2 btn double click event handler.
 * @param  btn
 * @param
 */
void BTN2_DOUBLE_Click_Handler(void *btn)
{
    //do something...
    LedBlink(PORT_GROUP2, LED2_PIN);
}

/**
 * @brief  SW3 btn & Wakeup btn long press event handler.
 * @param  btn
 * @param
 */
void BTN3_WAKEUP_LONG_PRESS_START_Handler(void *btn)
{
    //do something...
    LedBlink(PORT_GROUP2, LED3_PIN);
}

/**
 * @brief  Configures key port.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
void KeyInputInit(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    /*Configure the GPIO pin as input floating*/
    GPIO_InitStructure.Pin        = KEY_SW1_PIN | KEY_SW2_PIN | KEY_SW3_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(KEY_SW1_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = KEY_WAKEUP_INPUT_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(KEY_WAKEUP_PORT, &GPIO_InitStructure);

    /* MultiButton init */
    button_init(&btn1, Read_ButtonSW1_GPIO, 0);
    button_init(&btn2, Read_ButtonSW2_GPIO, 0);
    button_init(&btn3_wakeup, Read_ButtonSW3_Wakeup_GPIO, 0);//btn3 & wakeup 组合键

    button_attach(&btn1, SINGLE_CLICK,     BTN1_SINGLE_Click_Handler);
    button_attach(&btn2, DOUBLE_CLICK,     BTN2_DOUBLE_Click_Handler);
    button_attach(&btn3_wakeup, LONG_PRESS_START, BTN3_WAKEUP_LONG_PRESS_START_Handler);

    button_start(&btn1);
    button_start(&btn2);
    button_start(&btn3_wakeup);
}

 Step 3. 在main初始化时,调用按键初始化函数,并且注册按键轮询任务

/* Initialize sw1~sw3 and wakeup button */
    KeyInputInit();

mtmMain.Register(button_ticks,5);//每5ms轮询button tick一次

 Step 4. 编译下载到开发板上,验证功能正常,可以实现 单击、双击以及组合按键的长按功能,该小型软件库也非常方便地可以移植到其它平台。

 

【评测后序】

除了成功地完成了前面几篇测评任务,还验证了 USB和bxCAN 功能,这2大外设国民技术采用的策略非常明显,与 STM32 做得一样,且usbfs device 库也是使用的ST 的,所以比较稳定,上手也较为简单。本次开发板测评内容已全部结束,期待后续国民技术能带来更多优质国产MCU。

 

4. N32G45x_MultiButton_MillisTaskManager.zip (1.23 MB, 下载次数: 6)


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

相关帖子
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
    推荐帖子
    【年味大比拼】+会飞的英歌舞

    本帖最后由 xiaozhuang 于 2019-2-11 12:52 编辑 锵锵锵 我是广东省粤东潮汕人 现在借eeworld宝地跟各位同仁介绍一下家乡的英 ...

    今日有奖直播上午10点:ADI软件定义无线电ADALM-Pluto入门实战

    今日有奖直播上午10点:ADI软件定义无线电ADALM-Pluto入门实战 >>点击进入直播 直播时间:2019年9月21日上午10:00-11: ...

    速率5G以上的网口

    支持速率为5G以上的网口,有哪些型号?

    中芯国际北京530亿项目细节来了

    据中芯国际发出的最新公告,公司与北京开发区管委会订立合作框架文件,双方有意就发展及营运集成电路项目于中国共同成立合资企业 ...

    图像缩放算法的研究与FPGA设计

    504592

    测评汇总:上海航芯 ACM32F070开发板+触控功能评估板

    活动详情:【上海航芯 ACM32F070开发板+触控功能评估板】更新至 2022-11-09测评报告汇总:@mars4zhu 【上海航芯 ACM32F070开发板 ...

    关闭
    站长推荐上一条 1/6 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表