这篇主要介绍如何在手机端修改设备参数,比如设备名称,且实现掉电不丢失。
思路:把需要修改的参数发送给设备,设备根据uuid来分辨是参数,并保存在flash中,重启服务,这样下次上电修改不会丢失。
1.flash的操作
在pstorage.c
中是官方提供操作flash的库函数,下面介绍几个要用的
说明:初始化flash模块,在调用flash模块之前必须先调用他一次
uint32_t pstorage_init(void);
说明:注册flash接口
[in] p_module_param 注册参数
[out] p_block_id 注册成功时标识flash存储块
uint32_t pstorage_register(pstorage_module_param_t p_module_param,
pstorage_handle_t * p_block_id);
说明:根据块编号(block_num)获得你要操作的地址(p_block_id)
[in] p_base_id 注册成功时标识flash存储块(基块ID)
[in] block_num块编号,第一块编号为零
[out] p_block_id ,block_num编号块对应的地址
uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
pstorage_size_t block_num,
pstorage_handle_t * p_block_id);
说明:在指定位置更新写入存储相应大小的数据
[in] p_dest 更新数据的目的地址
[in] p_src 待写入数据buff首地址
[in] size,写入长度
[in] offset,存储地址的相应偏移量
uint32_t pstorage_update(pstorage_handle_t * p_dest,
uint8_t * p_src,
pstorage_size_t size,
pstorage_size_t offset);
说明:在指定位置读取存储区相应大小的数据
[in] p_dest 读取数据的源地址
[in] p_src 读取存放数据buff首地址
[in] size,读取长度
[in] offset,读取数据的源地址的相应偏移量
uint32_t pstorage_load(pstorage_handle_t * p_dest,
uint8_t * p_src,
pstorage_size_t size,
pstorage_size_t offset);
第一步,在系统的派发函数里注册官方提供的flash的callback
static void sys_evt_dispatch(uint32_t sys_evt)
{
//这个函数时在 pstorage 模块中实现的
pstorage_sys_event_handler(sys_evt);
}
第二步,flash初始化
void flash_init(void)
{
uint32_t err_code;
err_code = pstorage_init(); //初始化flash
APP_ERROR_CHECK(err_code);
pstorage_module_param_t module_param;
module_param.block_count = 1; // 申请了一个块
module_param.block_size = 512;//(最小要求是 16)
module_param.cb = flash_callback;// //操作回调
err_code =pstorage_register(&module_param, &block_id);//注册申请
APP_ERROR_CHECK(err_code);
}
flash_callback我理解是相应操作成功、失败、完成、未完成的判断依据(可以根据op_code分辨哪种状态机,根据result分辨成功失败)如下
static void flash_callback(pstorage_handle_t * handle,uint8_t op_code,uint32_t result,uint8_t * p_data,uint32_t data_len)
{
switch(op_code)
{
case PSTORAGE_UPDATE_OP_CODE:
if (result == NRF_SUCCESS)
{
printf("update end");
advertising_init();//重新启动广播
}
break;
}
}
这里只判断PSTORAGE_UPDATE_OP_CODE操作成功(result == NRF_SUCCESS)则打印输出update end
2.怎么判断是操作蓝牙名称呢?
可以根据uuid,GAP GATT这种服务的uuid都是SIG定义好的固定的
在ble_types.h
中80行可以看到设备名称uuid是0x2A00
/* GATT specific UUIDs */
#define BLE_UUID_GATT 0x1801 /**< Generic Attribute Profile. */
#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED 0x2A05 /**< Service Changed Characteristic. */
/* GAP specific UUIDs */
#define BLE_UUID_GAP 0x1800 /**< Generic Access Profile. */
#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME 0x2A00 /**< Device Name Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE 0x2A01 /**< Appearance Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPF 0x2A02 /**< Peripheral Privacy Flag Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */
/** @} */
手机连接设备后,对BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME属性(uuid 0x2A00)写操作,设备判断是不是对这个uuid写,是的话就把写数据保存在flash中,这样下次重启就可以加载flash数据作为设备名称
static void name_change(ble_evt_t * p_ble_evt)
{
ble_gatts_evt_write_t *p_evt_write=&p_ble_evt->evt.gatts_evt.params.write;
//判断是对BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME这个uuid进行写操作
if((p_evt_write->uuid.uuid==BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME)
&& (p_ble_evt->header.evt_id== BLE_GATTS_EVT_WRITE))
{
printf("name change \r\n");
device_name[0] = 0xaa;
//写的长度
device_name[1] = p_evt_write->len;
//写的数据
memcpy(device_name+2, p_evt_write->data, p_evt_write->len);
//保存在flash中
pstorage_update(&my_name_addr, device_name, NAME_SIZE, 0 );
}
}
然后在蓝牙派发函数ble_evt_dispatch
里包含name_change
在gap_params_init
函数里要对从flash加载的数据进行判断有没有手机下发的设备名字,有就用手机下发的,没有就用默认的