NRF51822项目实战

2015-6-10

声明:

因为我这几个月项目相当紧急,在搞嵌入式的方案,不再负责单片机的方案了。

单片机NRF51822的方案在当时的考察中,发现不合适,已经不再继续往下做了。早已替换了方案。


这篇博文我也没有时间再去写了,爱莫能助。


建议正在搞NRF51822的童鞋们,找一份已经演示通的代码,例如心率计的这套代码。

把这套代码搞通搞透,不懂的函数、变量和宏定义,可以去查NRF官方提供的手册。也可以自己做假设,然后做实验做验证。




NRF51822项目实战

2014-12-23



首先,需要查到蓝牙发送数据的API接口,可能是类似于网络sock的recv()和send()

拿到用户手册,看到可以参考的第一份代码是心率计,ble_app_hrs这个例程。

之前不知道这个例程的功能,一通乱找都没找到,照着用户手册试了下这个例程,很快就知道突破口了,去找那个按键触发的后续代码,

首先是按键初始化buttons_init(),找到了它有个类似的注册函数button_event_handler,接着进去,找到m_cur_heart_rate这个量,那就接着去找这个变量相关的操作,最后找到

sd_ble_gatts_hvx


这个函数,sd开头也就是蓝牙协议栈提供的底层API了,再没法往下找了,已经是固件级了。


接下来围绕这个API解析外层代码。


后续所有要讲的都是围绕这个API来解析外层代码,搞清楚了相关的流程和函数,就知道怎么改成自己需要的代码了。








2014-12-24


心率计的功能演示:

按开发板上KEY1,手机端会看到心率参数增加

按开发板上KEY2,手机端会看到心率参数减少


代码先从上层往底层解析。

先看main函数

int main(void)
{
    uint32_t err_code;

    timers_init();
    gpiote_init();
    buttons_init();
    ble_stack_init();
    bond_manager_init();

    // Initialize Bluetooth Stack parameters
    gap_params_init();
    advertising_init();
    services_init();
    conn_params_init();
    sec_params_init();

    // Start advertising
    advertising_start();

    // Enter main loop
    for (;;)
    {
        // Switch to a low power state until an event is available for the application
        err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
}

上面5个函数都是初始化,首先是定时器的初始化,先就不进去看了。然后是gpiote的初始化,不知道是不是KEY那两IO的初始化,先进去看看

static void gpiote_init(void)
{
    // Configure the GPIOTE Task to toggle the LED state.
    nrf_gpiote_task_config(GPIOTE_CHAN_FOR_LED_TASK,
                           ADVERTISING_LED_PIN_NO,
                           NRF_GPIOTE_POLARITY_TOGGLE,
                           NRF_GPIOTE_INITIAL_VALUE_LOW);
}

然来是初始化那几个LED的。

退出接着看buttons_init,进入

/**@brief Function for initializing the button module.
 */
static void buttons_init(void)
{
    // Configure HR_INC_BUTTON_PIN_NO and HR_DEC_BUTTON_PIN_NO as wake up buttons and also configure
    // for 'pull up' because the eval board does not have external pull up resistors connected to
    // the buttons.
    static app_button_cfg_t buttons[] =
    {
        {HR_INC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler},
        {HR_DEC_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler}  // Note: This pin is also BONDMNGR_DELETE_BUTTON_PIN_NO
    };
    
    APP_BUTTON_INIT(buttons, sizeof(buttons) / sizeof(buttons[0]), BUTTON_DETECTION_DELAY, false);
}

功能是初始化按键模块

HR_INC_BUTTON_PIN_NO和HR_DEC_BUTTON_PIN_NO分别对应KEY1和KEY2,false在这里的逻辑意义不知道,先不管。

BUTTON_PULL明显是表示该IO用内部上拉方式,button_event_handler这个,应该是回调函数,在发生按键外部中断是,被调用到的,类似于注册方式。

进入这个函数看看

/**@brief Function for handling button events.
 *
 * @param[in]   pin_no   The pin number of the button pressed.
 */
static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    if (button_action == APP_BUTTON_PUSH)
    {
        switch (pin_no)
        {
            case HR_INC_BUTTON_PIN_NO:
                // Increase Heart Rate measurement
                m_cur_heart_rate += HEART_RATE_CHANGE;
                if (m_cur_heart_rate > MAX_HEART_RATE)
                {
                    m_cur_heart_rate = MIN_HEART_RATE; // Loop back
                }
                break;
                
            case HR_DEC_BUTTON_PIN_NO:
                // Decrease Heart Rate measurement
                m_cur_heart_rate -= HEART_RATE_CHANGE;
                if (m_cur_heart_rate < MIN_HEART_RATE)
                {
                    m_cur_heart_rate = MAX_HEART_RATE; // Loop back
                }
                break;
                
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }    
}


非常清晰,就是在发生外部中断时,检测是哪个IO被拉低了,对应的增加或减少m_cur_heart_rate这个参数。

这里特别注意m_cur_heart_rate这个参数,后续蓝牙发送数据,一定会和它有关联,顺着它我才找到sd_ble_gatts_hvx这个发送的函数。

回退到上层,APP_BUTTON_INIT()应该就是类似于注册函数了,不深入去看了。


接着ble_stack_init(),蓝牙协议栈初始化,进入:

static void ble_stack_init(void)
{
    uint32_t err_code;
    
    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);
    
    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);
}

这里面就3个函数,都已经有注释,就不再解释了,其实我也没看明白。没事,先接着往下走,后面看完了再回头来理清楚。

退出看bond_manager_init

/**@brief Function for the Bond Manager initialization.
 */
static void bond_manager_init(void)
{
    uint32_t            err_code;
    ble_bondmngr_init_t bond_init_data;
    bool                bonds_delete;

    // Initialize persistent storage module.
    err_code = pstorage_init();
    APP_ERROR_CHECK(err_code);
    
    // Clear all bonded centrals if the Bonds Delete button is pushed
    err_code = app_button_is_pushed(BONDMNGR_DELETE_BUTTON_PIN_NO, &bonds_delete);
    APP_ERROR_CHECK(err_code);

    // Initialize the Bond Manager
    bond_init_data.evt_handler             = NULL;
    bond_init_data.error_handler           = bond_manager_error_handler;
    bond_init_data.bonds_delete            = bonds_delete;

    err_code = ble_bondmngr_init(&bond_init_data);
    APP_ERROR_CHECK(err_code);
}


虽然有注释,不过还是看不懂,接着往下走。


回到main函数

    // Initialize Bluetooth Stack parameters
    gap_params_init();
    advertising_init();
    services_init();
    conn_params_init();
    sec_params_init();


初始化蓝牙协议栈的参数,很关键。

首先是





你可能感兴趣的:(NRF51822项目实战)