DA14531是dialog今年推出的一款BLE芯片,价格低、功耗低,应用场景广泛。
开发过程中,有遇到这样的一个需求,DA14531与外设通信,随后将一些获得的信息在广播包里发送出去,想要实现这个需求,就需要在初始化蓝牙广播的时候,增加读取器件信息,更改广播包数据,再去广播。
再谈具体修改方法之前,先说一下广播包的数据构成,这里指的是如图所示的数据,不是基础定义的device name,mac地址,RSSI那些。
在Advertisement这个数据包里,可以存放的数据选择很多,可以参考官方BLE协议栈文档,也可以看dialog sdk中gap.h,里面有全部的定义,如图举例说明
包括我们需要用到的manufacture数据也是会显示在Advertisement里面的。
DA14531本身定义的广播包数据,可以在user_config.h里面进行修改,最初的想法是宏定义的动态修改,但是没法成功,后来参考codeless代码,在外部进行重新定义实现了该功能,具体修改如下:
以peripheral例程为基础进行修改,user_peripheral.c中,app_add_ad_struct函数里面有manufacture及广播数据的转存,我们这里可以沿用manufacture的数据转存,将广播数据的转存注释掉。
static void app_add_ad_struct(struct gapm_start_advertise_cmd *cmd, void *ad_struct_data, uint8_t ad_struct_len, uint8_t adv_connectable)
{
uint8_t adv_data_max_size = (adv_connectable) ? (ADV_DATA_LEN - 3) : (ADV_DATA_LEN); //connectable 28bytes
if ((adv_data_max_size - cmd->info.host.adv_data_len) >= ad_struct_len)
{
// Append manufacturer data to advertising data
memcpy(&cmd->info.host.adv_data[cmd->info.host.adv_data_len], ad_struct_data, ad_struct_len);
// Update Advertising Data Length
cmd->info.host.adv_data_len += ad_struct_len;
// Store index of manufacturer data which are included in the advertising data
mnf_data_index = cmd->info.host.adv_data_len - sizeof(struct mnf_specific_data_ad_structure);
}
else if ((SCAN_RSP_DATA_LEN - cmd->info.host.scan_rsp_data_len) >= ad_struct_len)
{
// Append manufacturer data to scan response data
memcpy(&cmd->info.host.scan_rsp_data[cmd->info.host.scan_rsp_data_len], ad_struct_data, ad_struct_len);
// Update Scan Response Data Length
cmd->info.host.scan_rsp_data_len += ad_struct_len;
// Store index of manufacturer data which are included in the scan response data
mnf_data_index = cmd->info.host.scan_rsp_data_len - sizeof(struct mnf_specific_data_ad_structure);
// Mark that manufacturer data is in scan response and not advertising data
mnf_data_index |= 0x80;
}
else
{
// Manufacturer Specific Data do not fit in either Advertising Data or Scan Response Data
ASSERT_WARNING(0);
}
// // Store advertising data length
// stored_adv_data_len = cmd->info.host.adv_data_len;
// // Store advertising data
// memcpy(stored_adv_data, cmd->info.host.adv_data, stored_adv_data_len);
// // Store scan response data length
// stored_scan_rsp_data_len = cmd->info.host.scan_rsp_data_len;
// // Store scan_response data
// memcpy(stored_scan_rsp_data, cmd->info.host.scan_rsp_data, stored_scan_rsp_data_len);
// cmd->info.host.adv_data_len = stored_adv_data_len;
// // Store advertising data
// memcpy(cmd->info.host.adv_data, stored_adv_data, stored_adv_data_len);
// // Store scan response data length
// cmd->info.host.scan_rsp_data_len = stored_scan_rsp_data_len;
// // Store scan_response data
// memcpy(cmd->info.host.scan_rsp_data, stored_scan_rsp_data, stored_scan_rsp_data_len);
}
在user_app_init函数里自定义广播数据,以GAP_AD_TYPE_COMPLETE_NAME为例,前面的19即为后面数据的长度,包括了GAP_AD_TYPE_COMPLETE_NAME的长度。定义完成后,将
adv_data数据转存到stored_adv_data。
void user_app_init(void)
{
uint8_t adv_data[]= {
19, GAP_AD_TYPE_COMPLETE_NAME,
'A', 'B', 'C', 'D', 'E', ' ', 'F', 'G', 'H', 'I', 'J', 'K', 'L', ' ', 'M', 'N', 'Z', 'Y',
};
app_param_update_request_timer_used = EASY_TIMER_INVALID_TIMER;
// Initialize Manufacturer Specific Data
mnf_data_init();
memcpy(stored_adv_data, &adv_data, sizeof(adv_data)); //广播包数据转存stored_adv_data
stored_adv_data_len = sizeof(adv_data);
memcpy(stored_scan_rsp_data, USER_ADVERTISE_SCAN_RESPONSE_DATA, USER_ADVERTISE_SCAN_RESPONSE_DATA_LEN);
stored_scan_rsp_data_len = USER_ADVERTISE_SCAN_RESPONSE_DATA_LEN;
default_app_on_init();
}
随后在user_app_adv_start函数中,将转存的广播包数据存到sdk定义的cmd->info.host.adv_data中
void user_app_adv_start(void)
{
// Schedule the next advertising data update
app_adv_data_update_timer_used = app_easy_timer(APP_ADV_DATA_UPDATE_TO, adv_data_update_timer_cb);
struct gapm_start_advertise_cmd* cmd;
cmd = app_easy_gap_undirected_advertise_get_active(); //非定向可连接广播
cmd->info.host.adv_data_len = stored_adv_data_len;
// Store advertising data
memcpy(cmd->info.host.adv_data, stored_adv_data, stored_adv_data_len);
// Store scan response data length
cmd->info.host.scan_rsp_data_len = stored_scan_rsp_data_len;
// Store scan_response data
memcpy(cmd->info.host.scan_rsp_data, stored_scan_rsp_data, stored_scan_rsp_data_len);
// Add manufacturer data to initial advertising or scan response data, if there is enough space
app_add_ad_struct(cmd, &mnf_data, sizeof(struct mnf_specific_data_ad_structure), 1);
app_easy_gap_undirected_advertise_start();
}
完成后,即可发现广播的advertisement数据包就是自己设定好的数据,想要自定义修改,只需要改动定义的数组即可,manufacture的数据同理,在sdk本身定义的mnf_data_init函数中进行修改即可,需要注意的是要更改manufacture中data的数据长度的话,需要在user_peripheral.h中修改APP_AD_MSD_DATA_LEN。
梳理一下整体的广播过程,还是可以比较容易的做到这个修改。希望有更多的人能分享DA14531系列芯片的开发内容吧。