battery service 修改 52832

来源:互联网 发布:东莞大朗淘宝电商培训 编辑:程序博客网 时间:2024/05/24 04:53

实现 battery 特征值的添加函数,这里电池服务实现是定时周期使用notify方式将电量发送给手机,所以通信方式是跟nus服务中的rx特征值一样的,所以直接拷贝ble_nus.c中的rx_char_add 函数做一下简单修改就可以了

static uint32_tbattery_char_add(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)

{

    ble_gatts_char_md_t char_md;

    ble_gatts_attr_md_t cccd_md;

    ble_gatts_attr_t    attr_char_value;

    ble_uuid_t          ble_uuid;

    ble_gatts_attr_md_t attr_md;


    memset(&cccd_md, 0, sizeof(cccd_md));


    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

   BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);


    cccd_md.vloc = BLE_GATTS_VLOC_STACK;


    memset(&char_md, 0, sizeof(char_md));


    char_md.char_props.notify = 1;

    char_md.p_char_user_desc  = NULL;

    char_md.p_char_pf         = NULL;

    char_md.p_user_desc_md    = NULL;

    char_md.p_cccd_md         = &cccd_md;

    char_md.p_sccd_md         = NULL;


ble_uuid.type = p_nus->uuid_type;

//替换uuid

    ble_uuid.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;


    memset(&attr_md, 0, sizeof(attr_md));


   BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);

   BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);


    attr_md.vloc    = BLE_GATTS_VLOC_STACK;

    attr_md.rd_auth = 0;

    attr_md.wr_auth = 0;

    attr_md.vlen    = 1;


    memset(&attr_char_value, 0,sizeof(attr_char_value));


    attr_char_value.p_uuid    = &ble_uuid;

    attr_char_value.p_attr_md = &attr_md;

    attr_char_value.init_len  = sizeof(uint8_t);

    attr_char_value.init_offs = 0;

    attr_char_value.max_len   = BLE_NUS_MAX_RX_CHAR_LEN;


   //替换存储 特性的结构体指针

    returnsd_ble_gatts_characteristic_add(p_nus->service_handle,

                                          &char_md,

                                          &attr_char_value,

                                           &p_nus->rx_handles);

}

然后修改ble_nus.c中的

uint32_tble_nus_init(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)  函数 添加 电池特特性创建的函数调用


uint32_t ble_nus_init(ble_nus_t * p_nus,const ble_nus_init_t * p_nus_init)

{

   …………………………

    …………………………

    …………………………


    // Add the TX Characteristic.

    err_code = tx_char_add(p_nus, p_nus_init);

    if (err_code != NRF_SUCCESS)

    {

        return err_code;

    }

   //添加电池特性创建服务的调用

   err_code =battery_char_add(p_nus, p_nus_init);

    if (err_code!= NRF_SUCCESS)

    {

        returnerr_code;

    }

   

    return NRF_SUCCESS;

}

然后实现 电池电量的发送函数。直接拷贝ble_nus.c中的ble_nus_string_send函数并作如下修改。

uint32_t  battery_send(ble_nus_t* p_nus, uint8_t*battery_level,uint16_t length)

{

    ble_gatts_hvx_params_t hvx_params;


    if (p_nus == NULL)

    {

        return NRF_ERROR_NULL;

    }

    //去掉是否使能notify的标记判断,因为这里用的是电池通道,

    //本来也应该想rx一样做一个是否notify过的标志,例子里为了方便就

    //没做

    if (p_nus->conn_handle == BLE_CONN_HANDLE_INVALID)

    {

        return NRF_ERROR_INVALID_STATE;

    }

    if (length > BLE_NUS_MAX_DATA_LEN)

    {

        return NRF_ERROR_INVALID_PARAM;

    }


    memset(&hvx_params, 0,sizeof(hvx_params));


    hvx_params.handle =p_nus->battery_handles.value_handle;

    hvx_params.p_data =battery_level;

    hvx_params.p_len  = &length;

    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;


    returnsd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);

}

 

之后再创建一个定时器来定时发送电量值

app_timer_create(&battery_timer,APP_TIMER_MODE_REPEATED,battery_timer_handler);


注意 main.c中的宏要响应增加1 #define APP_TIMER_MAX_TIMERS            (3 + BSP_APP_TIMERS_NUMBER)           

 

定时到期处理函数

 

void battery_timer_handler(void *p_context){

    static uint8_tbattery_level[4];

    uint32_t temp;

    nrf_adc_start();

    while(NRF_ADC->BUSY&1);

    float value =(NRF_ADC->RESULT)*1.0;

    value = value*1.2/1024.0;

    value *= 3;


//将电压值扩大100倍,好发送整数出去。

    temp = value * 100;


    battery_level[0]  = (temp>>24)&0xff;

    battery_level[1]  = (temp>>16)&0xff;

    battery_level[2]  = (temp>>8)&0xff;   

    battery_level[3]  = (temp>>0)&0xff;


    battery_send(&m_nus,battery_level, 4);

}

并在连接上后就启动定时器。开始 1s 周期发送电量。

Ble_nus.c中修改

extern app_timer_id_t battery_timer;

void ble_nus_on_ble_evt(ble_nus_t * p_nus, ble_evt_t * p_ble_evt)

{

    if ((p_nus == NULL) || (p_ble_evt== NULL))

    {

        return;

    }


    switch(p_ble_evt->header.evt_id)

    {

        caseBLE_GAP_EVT_CONNECTED:

            on_connect(p_nus,p_ble_evt);

          app_timer_start(battery_timer,  APP_TIMER_TICKS(1000, 0), NULL);

            break;


        caseBLE_GAP_EVT_DISCONNECTED:

            on_disconnect(p_nus,p_ble_evt);

            break;


        case BLE_GATTS_EVT_WRITE:

            on_write(p_nus,p_ble_evt);

            break;


        default:

            // No implementationneeded.

            break;

    }

}

这里写的例子比较粗糙。正确的做法应该是,在手机使能电量发送特征值的notify后,从机才开始定时发送。不过这里这样做并不影响现象,因为虽然连接上后就开始周期发送电量,但是因为notify并未被使能,所以发送会失败,但是程序可以继续正常运作。


烧写程序,手机连接上后,找到电池的那个特征值,使能Notify就能收到周期性的电量报告了。

 

Main函数如下:

int main(void)

{


    uint32_t err_code;

    bool erase_bonds;

    uint8_t  start_string[] = START_STRING;


    // Initialize.

   APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS,APP_TIMER_OP_QUEUE_SIZE, false);

    uart_init();

    app_timer_create(&battery_timer,APP_TIMER_MODE_REPEATED,battery_timer_handler);


   buttons_leds_init(&erase_bonds);

    ble_stack_init();

    gap_params_init();

    services_init();

    advertising_init();

    conn_params_init();


    printf("start\r\n");


   nrf_adc_init();


    err_code =ble_advertising_start(BLE_ADV_MODE_FAST);

    APP_ERROR_CHECK(err_code);


    // Enter main loop.

    for (;;)

    {

        power_manage();

    }

return 0;

}
原创粉丝点击