BLE广播流程介绍 蓝牙广播 低功耗蓝牙广播的实现流流程介绍 /BLE Advertising flow ----- 蓝牙低功耗协议栈

零. 概述

主要介绍下蓝牙协议栈(bluetooth stack)低功耗蓝牙广播的流程以及协议栈的实现流程,BLE  Advertising flow

btsnoop以及流程在资料中的......\STM32_UBUNTU_BLUETOOTH\2-蓝牙资料\蓝牙协议分析\BLE广播.log

一. 声明

本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

扫描二维码关注公众号,回复: 12084300 查看本文章

第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

-------------------------------------------------------------------------------------------------------------------------

CSDN学院链接(进入选择你想要学习的课程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144

蓝牙交流扣扣群:970324688

Github代码:https://github.com/sj15712795029/bluetooth_stack

入手开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708

蓝牙学习目录https://blog.csdn.net/XiaoXiaoPengBo/article/details/107727900

--------------------------------------------------------------------------------------------------------------------------

二. BLE广播command以及event

整个流程如下(注意在初始化的时候有省略的步骤,只列出初始化的关键步骤)

我们再来看下ellisys的流程(跟Wireshark显示基本一样,主要是ellisys在流程中会自带解析,所以我顺便也贴下)

注意我们在截图初始化的时候只是截取了两个command以及event,一个是跟传统蓝牙有差别的set event mask,一个是write le host supported,其他可以参照传统蓝牙的初始化,步骤整理如下:

步骤1)发送设置事件掩码的command(set event mask)以及收到commnd complete event

步骤2)发送设置支持BLE的command(write le host support)收到command complete event

步骤3)发送BLE 设置广播参数的command(LE Set Advertising Parameters)

步骤4)发送BLE设置广播数据的command(LE Set Advertising Data)

步骤5)发送BLE开启广播的command(LE Set Advertising Enable)

步骤6)收到步骤4)5)6)的command complete

步骤7)发送BLE关闭广播的command(LE Set Advertising Enable)以及收到commnd complete event

下面我们就详细说下每个步骤

步骤1)发送设置事件掩码的command(set event mask)以及收到commnd complete event

此部分在上一个小节搜索广播的时候介绍过,不再重复

步骤2)发送设置支持BLE的command(write le host support)收到command complete event

此部分在上一个小节搜索广播的时候介绍过,不再重复

步骤3)发送BLE 设置广播参数的command(LE Set Advertising Parameters)

我们来看下这个command的格式:

我们直接来看下btsnoop

对应的代码如下:

err_t hci_le_set_adv_param(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
    uint8_t own_address_typ, uint8_t peer_address_type,struct bd_addr_t *peer_address, uint8_t channel_map, uint8_t filter_policy)
{
	struct bt_pbuf_t *p;
    uint8_t offset = 0;
    if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_PARAM_PLEN, BT_PBUF_RAM)) == NULL)
    {
        BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
        return BT_ERR_MEM;
    }
    /* Assembling command packet */
    p = hci_cmd_ass(p, HCI_LE_SET_ADV_PARAM, HCI_LE, HCI_SET_LE_ADV_PARAM_PLEN);
    offset += 3;
    bt_le_store_16((uint8_t *)p->payload,offset,adv_int_min);
    offset += 2;
    bt_le_store_16((uint8_t *)p->payload,offset,adv_int_max);
    offset += 2;
    ((uint8_t *)p->payload)[offset] = adv_type;
    offset += 1;
	((uint8_t *)p->payload)[offset] = own_address_typ;
    offset += 1;
	((uint8_t *)p->payload)[offset] = peer_address_type;
    offset += 1;
	memcpy(((uint8_t *)p->payload)+offset, peer_address->addr, BD_ADDR_LEN);
	offset += BD_ADDR_LEN;
	((uint8_t *)p->payload)[offset] = channel_map;
    offset += 1;
    ((uint8_t *)p->payload)[offset] = filter_policy;
    phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
    bt_pbuf_free(p);

    return BT_ERR_OK;
}

步骤4)发送BLE设置广播数据的command(LE Set Advertising Data)

我们来看下HCI command格式:

此命令是设置广播数据的,广播数据的格式在上个小节,搜索广播的时候已经说到,我们就不再重复了,我们直接来看下我们设置的代码以及btsnoop

为了测试简单,我自己也就广播了一个蓝牙名称,广播数据如下:

广播调用如下:

实现如下:

err_t hci_le_set_adv_data(uint8_t adv_len,uint8_t *adv_data)
{
	struct bt_pbuf_t *p;
    uint8_t offset = 0;
    if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_DATA_PLEN, BT_PBUF_RAM)) == NULL)
    {
        BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
        return BT_ERR_MEM;
    }
    /* Assembling command packet */
    p = hci_cmd_ass(p, HCI_LE_SET_ADV_DATA, HCI_LE, HCI_SET_LE_ADV_DATA_PLEN);
    offset += 3;
	((uint8_t *)p->payload)[offset] = adv_len;
    offset += 1;

	memset(((uint8_t *)p->payload) + offset,0,HCI_SET_LE_ADV_DATA_PLEN-offset);
	memcpy(((uint8_t *)p->payload)+offset, adv_data, adv_len);

    phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
    bt_pbuf_free(p);

    return BT_ERR_OK;
}

此部分要注意的是不管你的广播数据是什么,都要填满31Byte,第一个参数广播数据是你真是的广播长度

最后来看下btsnoop:

步骤5)发送BLE开启广播的command(LE Set Advertising Enable)

我们来看下command格式:

参数很简单,就是简单的开启跟关闭

我们来看下代码实现:

err_t hci_le_set_adv_enable(uint8_t enable)
{
	struct bt_pbuf_t *p;
    uint8_t offset = 0;
    if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_ENABLE_PLEN, BT_PBUF_RAM)) == NULL)
    {
        BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
        return BT_ERR_MEM;
    }
    /* Assembling command packet */
    p = hci_cmd_ass(p, HCI_LE_SET_ADV_ENABLE, HCI_LE, HCI_SET_LE_ADV_ENABLE_PLEN);
    offset += 3;
	((uint8_t *)p->payload)[offset] = enable;

    phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
    bt_pbuf_free(p);

    return BT_ERR_OK;
}

最后我们来看下btsnoop:

步骤6)收到步骤4)5)6)的command complete

这个command我们已经在传统蓝牙HCI介绍了,我直接贴下这3个command complete的event

步骤7)发送BLE关闭广播的command(LE Set Advertising Enable)以及收到commnd complete event

这个在步骤5)已经介绍,我们直接来截图btsnoop

猜你喜欢

转载自blog.csdn.net/XiaoXiaoPengBo/article/details/109327581