本讲接收如何实现动态广播。
教程基于 9.0 sdk中的 Uart例子。
实现动态广播的方法是 广播->停止广播->修改参数->重启广播
所以我们通过一个定时器来周期性的 关闭广播然后再修改广播数据之后再开启广播。
Sdk 9.0中的广播搞了好几个模式,做的有点麻烦,所以我对他做了比较大的改动。
首先 在main.c中 中的advertising_init函数需要改动。
主要修改还添加了红色部分。将 flag 改为了GENERAL。后面又将广播超时设置为0从而实现无线广播。
去掉了根据广播模式来设置广播数据的函数以及对扫描响应数据的设置。
void advertising_init(void)
{
uint32_t err_code;
ble_advdata_t advdata;
ble_advdata_t scanrsp;
memset(&advdata,0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.include_appearance = false;
advdata.flags =BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
staticble_advdata_manuf_data_t manuf_data;
staticuint8_t mydata = 0; //这里用的是静态数据
//这里做的动态广播就是每次调用这个函
//数,广播数据中的厂商定义字段都会加1
manuf_data.company_identifier= 0xffaa;
manuf_data.data.size= 1;
manuf_data.data.p_data= &mydata;
mydata++; //每次调用后加1
advdata.p_manuf_specific_data= &manuf_data;
err_code= ble_advdata_set(&advdata, NULL);
APP_ERROR_CHECK(err_code);
}
然后是启动广播函数。 Main 函数中用的是ble_advertising_start。
我们这里不用。直接实现一个自己的简单函数
void myadv_start(void){
ble_gap_adv_params_tadv_params;
adv_params.interval =1600; //这里广播间隔设置为 1s
adv_params.timeout = 0;//这里设置0和上面的flag配合实现无线广播
adv_params.type =BLE_GAP_ADV_TYPE_ADV_IND;
adv_params.channel_mask.ch_37_off= 0;
adv_params.channel_mask.ch_38_off= 0;
adv_params.channel_mask.ch_39_off= 0;
adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
adv_params.p_peer_addr= NULL;
adv_params.fp = BLE_GAP_ADV_FP_ANY;
adv_params.p_whitelist= NULL;
sd_ble_gap_adv_start(&adv_params);
}
之后我们做一个定时器。定时器的作用是以2s为周期 来关闭修改广播参数然后启动广播
在main 函数中做如下修改,创建一个 2s定时器 my_timer,并且开启它
int main(void)
{
uint32_t err_code;
bool erase_bonds;
uint8_t start_string[] = START_STRING;
app_timer_id_tmy_timer;
// Initialize.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
uart_init();
app_timer_create(&my_timer,APP_TIMER_MODE_REPEATED,
my_timer_handler);
buttons_leds_init(&erase_bonds);
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();
app_timer_start(my_timer,APP_TIMER_TICKS(2000,APP_TIMER_PRESCALER), NULL);
myadv_start(); //这里用的自己定义的启动广播函数
for (;;)
{
power_manage();
}
}
然后实现自己的定时器的溢出处理函数
void my_timer_handler(void *p_contex){
int i =50;
sd_ble_gap_adv_stop(); //关广播
advertising_init(); //修改厂商自定义字段中的数据
while(i--);
myadv_start(); //开启广播
}
这里做的动态广播是动态修改广播数据中的厂商自定义字段。每次调用
advertising_init 函数的时候厂商自定义字段的值都会递增。在advertising_init函数中有注释说明
到这里动态广播要做的事已经做完了。
不过在uart例子中还需要做一个改动,我们创建了一个自己的timer,不过uart例子中定义的 允许使用的最大的 timer数就是它已经使用的数量,所以我们再添加自己的timer会出错。
修改办法:找到main.c文件中的APP_TIMER_MAX_TIMERS宏将其增大1就可以了
之后烧录程序就能看到广播数据中的厂商自定义字段在动态改变了