NRF52832 BSP使用分析

1.首先需要启动低速时钟

    NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_LFCLKSTART    = 1;

    while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
    {
        // Do nothing.
    }

2.初时化函数bsp_init中

m_registered_callback = callback; 这行是注册回调函数,通过参数传入

  err_code = bsp_event_to_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT);  这行是分

配默认的事件

err_code = app_button_init((app_button_cfg_t *)app_buttons,   //事件数组
                                       BUTTONS_NUMBER,         //按键个数
                                       APP_TIMER_TICKS(50));    //50ms的TICK时间数

事件数组定义

static const app_button_cfg_t app_buttons[BUTTONS_NUMBER] =
{
    #ifdef BSP_BUTTON_0
    {BSP_BUTTON_0, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_0

    #ifdef BSP_BUTTON_1
    {BSP_BUTTON_1, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_1

    #ifdef BSP_BUTTON_2
    {BSP_BUTTON_2, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_2

    #ifdef BSP_BUTTON_3
    {BSP_BUTTON_3, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_3

    #ifdef BSP_BUTTON_4
    {BSP_BUTTON_4, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_4

    #ifdef BSP_BUTTON_5
    {BSP_BUTTON_5, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_5

    #ifdef BSP_BUTTON_6
    {BSP_BUTTON_6, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_6

    #ifdef BSP_BUTTON_7
    {BSP_BUTTON_7, false, BUTTON_PULL, bsp_button_event_handler},
    #endif // BUTTON_7

};

使能APP Button

err_code = app_button_enable();

创建定APP定时器

err_code = app_timer_create(&m_bsp_button_tmr,
                                        APP_TIMER_MODE_SINGLE_SHOT,
                                        button_timer_handler);

3.指定按键与事件关联起来

uint32_t bsp_event_to_button_action_assign(uint32_t button, bsp_button_action_t action, bsp_event_t event)
{
    uint32_t err_code = NRF_SUCCESS;

#if BUTTONS_NUMBER > 0
    if (button < BUTTONS_NUMBER)
    {
        if (event == BSP_EVENT_DEFAULT)
        {
            // Setting default action: BSP_EVENT_KEY_x for PUSH actions, BSP_EVENT_NOTHING for RELEASE and LONG_PUSH actions.
            event = (action == BSP_BUTTON_ACTION_PUSH) ? (bsp_event_t)(BSP_EVENT_KEY_0 + button) : BSP_EVENT_NOTHING;
        }
        switch (action)
        {
            case BSP_BUTTON_ACTION_PUSH:     //按键压下事件指定
                m_events_list[button].push_event = event;
                break;
            case BSP_BUTTON_ACTION_LONG_PUSH:   //按键长按事件指定
                m_events_list[button].long_push_event = event;
                break;
            case BSP_BUTTON_ACTION_RELEASE:     按键释放事件指定
                m_events_list[button].release_event = event;
                break;
            default:
                err_code = NRF_ERROR_INVALID_PARAM;
                break;
        }
    }
    else
    {
        err_code = NRF_ERROR_INVALID_PARAM;
    }
#else
    err_code = NRF_ERROR_INVALID_PARAM;
#endif // BUTTONS_NUMBER > 0

    return err_code;
}

4.app_button_init函数

 err_code = nrf_drv_gpiote_init(); //初时化GPIOTE

err_code = nrf_drv_gpiote_in_init(p_btn->pin_no, &config, gpiote_event_handler); //GPIOTE IN事件设置

app_timer_create(&m_detection_delay_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            detection_delay_timeout_handler); //创建按键检测定时器

5.static void gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)由GPIOTE事件回调,回调中会启动

定时器一次err_code = app_timer_start(m_detection_delay_timer_id, m_detection_delay, NULL);

6.定时时间到会回调static void detection_delay_timeout_handler(void * p_context)函数一次,回调中由以下发出通知,即调用到

app_buttons数组中定义的函数bsp_button_event_handler

   p_btn->button_handler(p_btn->pin_no, transition);

7.static void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action)回调函数

static void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    bsp_event_t        event  = BSP_EVENT_NOTHING;
    uint32_t           button = 0;
    uint32_t           err_code;
    static uint8_t     current_long_push_pin_no;              /**< Pin number of a currently pushed button, that could become a long push if held long enough. */
    static bsp_event_t release_event_at_push[BUTTONS_NUMBER]; /**< Array of what the release event of each button was last time it was pushed, so that no release event is sent if the event was bound after the push of the button. */

    button = bsp_board_pin_to_button_idx(pin_no);  //得到按键在数组中的序号

    if (button < BUTTONS_NUMBER)
    {
        switch (button_action)
        {
            case APP_BUTTON_PUSH:    //按键按下事件
                event = m_events_list[button].push_event;
                if (m_events_list[button].long_push_event != BSP_EVENT_NOTHING) //如果定义了长按键
                {
                    err_code = app_timer_start(m_bsp_button_tmr, APP_TIMER_TICKS(BSP_LONG_PUSH_TIMEOUT_MS), (void*)&current_long_push_pin_no);  //启动长按键定时器
                    if (err_code == NRF_SUCCESS)
                    {
                        current_long_push_pin_no = pin_no;
                    }
                }
                release_event_at_push[button] = m_events_list[button].release_event;
                break;
            case APP_BUTTON_RELEASE:  //按键释放
                (void)app_timer_stop(m_bsp_button_tmr);
                if (release_event_at_push[button] == m_events_list[button].release_event)
                {
                    event = m_events_list[button].release_event;
                }
                break;
            case BSP_BUTTON_ACTION_LONG_PUSH:   //长按键事件,由长按键定时器调用进入
                event = m_events_list[button].long_push_event;
        }
    }

    if ((event != BSP_EVENT_NOTHING) && (m_registered_callback != NULL))
    {
        m_registered_callback(event);   //回调到注册的按键事件函数
    }
}

8.长按定时器回调函数,此函数在bsp_init中设置过

static void button_timer_handler(void * p_context)
{
    bsp_button_event_handler(*(uint8_t *)p_context, BSP_BUTTON_ACTION_LONG_PUSH);  //调用按键事件函数
}

9.回调到使用者注册的按键事件函数,注册由bsp_init实现

   m_registered_callback(event); 

10. 使用者自定义bsp_evt_handler按键事件注册

err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_evt_handler);

11.void bsp_evt_handler(bsp_event_t evt)函数

void bsp_evt_handler(bsp_event_t evt)
{
    uint32_t err_code;
    switch (evt)
    {
        case BSP_EVENT_KEY_0:        //此事件值可由bsp_event_to_button_action_assign函数指定
            break;

        case BSP_EVENT_KEY_1:   //此事件值可由bsp_event_to_button_action_assign函数指定
            break;

        default:
            return; // no implementation needed
    }
    
}

总结按键事件传递流程:

按键产生GPIOTE事件->回调gpiote_event_handler函数,启动一次性定时器(50ms,可设置)->定时器事件回调函数,调用

p_btn->button_handler(p_btn->pin_no, transition)去通知数组中定义的回调函数->bsp_button_event_handler处理按键按下,释放等事件,由m_registered_callback(event)调用将事件回调->最终调用到bsp_evt_handler函数

长按事件先由按键按下事件,启动一个长按键定时器(约1秒,可设置)->定时器时间到,回调button_timer_handler函数,此函数再直接调用bsp_button_event_handler函数->长按事件由m_registered_callback(event)调用将事件回调->最终调用到bsp_evt_handler函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
nRF52832是一款高度集成的多协议系统级芯片(SoC),广泛应用于物联网(IoT)、无线传感器网络及低功耗蓝牙(Bluetooth Low Energy,BLE)等领域。以下是nRF52832使用教程的一般步骤: 1. 硬件搭建:对于使用nRF52832进行开发的项目,首先需要搭建硬件环境。这可能包括购买nRF52832开发板、连接外部传感器、电源以及调试工具等。 2. 开发环境搭建:下载并安装nRF5 SDK(Software Development Kit),这是nRF52832开发所需的软件工具包。这个SDK提供了开发所需的库文件、示例代码和编译工具。 3. 编写代码:使用C或C++等编程语言,编写逻辑代码以控制和配置nRF52832的功能。可以使用SDK提供的示例代码作为起点,根据项目需求进行修改和调试。 4. 编译和烧写:使用SDK提供的编译工具将代码编译为可执行文件,然后使用下载器将可执行文件烧写到nRF52832芯片上。这个过程通常需要连接开发板到计算机,并按照指示进行操作。 5. 调试和测试:在代码烧写完成后,可以使用调试器工具对nRF52832进行调试和测试。这些工具可以帮助开发者查找和修复代码中的错误,并确保程序的正常执行。 6. 运行应用程序:将开发板上的nRF52832连接到相应设备或系统中,通过编写的应用程序进行功能验证和测试。在此过程中,你可以使用SDK提供的开发工具和库文件来加强和扩展应用程序的功能。 总之,nRF52832使用教程包括硬件搭建,开发环境搭建,编写代码,编译和烧写,调试和测试以及运行应用程序。通过这些步骤,开发者可以利用nRF52832的强大功能来实现各种物联网和低功耗蓝牙应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雨依依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值