nrf52832 学习笔记蓝牙从机广播

Posted 不咸不要钱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙从机广播相关的知识,希望对你有一定的参考价值。

nrf52832 学习笔记(三)蓝牙从机广播

蓝牙从机要想被主机连接,首先需要发送广播信息,周围主机通过扫描广播信号,根据从机的广播信息,判断是否连接。

蓝牙协议栈初始化

不管是主机还是从机,要想使用蓝牙功能,都需要对蓝牙协议栈进行初始化操作

/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(void)

    ret_code_t err_code;

	// 1.协议栈低速时钟初始化并注册状态观察者函数 
    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // 2.使用默认配置配置蓝牙协议栈
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    // 3.使能协议栈
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // 4.注册蓝牙事件观察者回调函数
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

蓝牙协议栈初始化做了四件事:

  • 协议栈时钟低速初始化并注册状态观察者函数

    协议栈运行除了主时钟外还需要一个低速时钟,低速时钟有三种来源,根据功耗和硬件选择合适的时钟源。

    // <0=> NRF_CLOCK_LF_SRC_RC    //内部RC时钟,比外部低速晶振耗电多10ua左右
    // <1=> NRF_CLOCK_LF_SRC_XTAL  //外部低速晶振,最省电但是需要外接低速晶振
    // <2=> NRF_CLOCK_LF_SRC_SYNTH //内部主时钟产生的低速时钟,最耗电
    
    #ifndef NRF_SDH_CLOCK_LF_SRC
    #define NRF_SDH_CLOCK_LF_SRC 1
    #endif
    nrf_clock_lf_cfg_t const clock_lf_cfg =
    
        .source       = NRF_SDH_CLOCK_LF_SRC,
        .rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
        .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        .accuracy     = NRF_SDH_CLOCK_LF_ACCURACY //时钟准确度
    ;
    

    注册的状态观察者函数其实就是一个中断服务函数的子函数,用户根据返回的状态信息做出相应处理。比如蓝牙协议栈使能失败,协议栈会触发一个软中断,软中断中调用注册的状态观察者函数,用户在状态观察者函数中根据状态信息点灯或者干别的事情,方便用户观察协议栈的运行状态。

  • 使用默认配置配置蓝牙协议栈

    默认配置信息可以在sdk_config.h中根据自己需要自行修改。

    // 空中包长度 = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + 4,提高蓝牙传输速率时,可以修改这里
    #ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
    #define NRF_SDH_BLE_GAP_DATA_LENGTH 27
    #endif
    
    // 从机角色个数,可以连接 ? 个主机
    #ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT
    #define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1
    #endif
    
    // 主机角色个数,可以连接 ? 个从机 
    #ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT
    #define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0
    #endif
    
    // 主机+从机 总的角色个数
    #ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT
    #define NRF_SDH_BLE_TOTAL_LINK_COUNT 1
    #endif
    
    // 一个连接间隔内可以用于数据传输的事件长度,以1.25 ms为单位。
    // 提高蓝牙传输速率时,可以修改这里和连接事件长度扩展相配合
    #ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
    #endif
    
    // MTU最大长度 蓝牙4.0 最大23  蓝牙4.2以上最大247
    #ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23
    #endif
    
    // <o> NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. 
    #ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE
    #define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408
    #endif
    
    // <o> NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs.
    // 主要每增加一个UUIDs 协议栈消耗RAM会增加0x10 
    #ifndef NRF_SDH_BLE_VS_UUID_COUNT
    #define NRF_SDH_BLE_VS_UUID_COUNT 10
    #endif
    
    // <q> NRF_SDH_BLE_SERVICE_CHANGED  - Include the Service Changed characteristic in the Attribute Table.
    #ifndef NRF_SDH_BLE_SERVICE_CHANGED
    #define NRF_SDH_BLE_SERVICE_CHANGED 0
    #endif
    
    
  • 使能协议栈

  • 注册蓝牙事件观察者回调函数

GAP初始化

Generic Access Profile(通用访问配置文件)也就是常说的GAP,所有蓝牙设备中必须存在的profile。NRF52832 SDK中对GAP的操作均在 ble_gap.h中。

GAP作用

BLE功耗低的原因之一就是仅在数据收发时开启射频电路,这里有一个重要的参----连接间隔 connection interval,它约定了BLE双方碰头时间。当然连接间隔是可以根据需要灵活修改的(7.5ms – 4000ms),每个公司都有自己的规定,如果连接间隔不能统一规范的话(试想A公司蓝牙产品的连接间隔放在Aprofile里面,而B公司蓝牙产品的连接间隔放在Bprofile里面, A公司和B公司的蓝牙产品由于连接间隔不一样,不能建立稳定连接,也就是说不同品牌的蓝牙产品不能互联),不同蓝牙产品之间就不可以互联。为了解决这个问题,SIG规定将蓝牙的发现和连接相关的参数形成一个Generic Access Profile(通用访问配置文件),保证不同Bluetooth产品可以互相发现对方并建立连接。

GAP 安全模式

蓝牙配对时输入密码功能也是GAP的一部分,当然也可以选择开放模式(不用输入密码)则不用进行这里的静态密匙设置操作

/**@brief GAP connection security modes.
 *
 * Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\\n
 * Security Mode 1 Level 1: No security is needed (aka open link).\\n
 * Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\\n
 * Security Mode 1 Level 3: MITM protected encrypted link required.\\n
 * Security Mode 1 Level 4: LESC MITM protected encrypted link using a 128-bit strength encryption key required.\\n
 * Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\\n
 * Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\\n
 */
typedef struct

  uint8_t sm : 4;                     /**< Security Mode (1 or 2), 0 for no permissions at all. */
  uint8_t lv : 4;                     /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */
 ble_gap_conn_sec_mode_t;

//设置静态钥匙	
#define STATIC_PASSKEY "123456"	
static ble_opt_t m_static_pin_option;																	
uint8_t passkey[] = STATIC_PASSKEY;                                                     
m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);

GAP MAC地址设置

蓝牙的MAC地址分为两类

  • Public

    需要申请购买, 24bit(MSB)公司ID + 24bit设备地址

  • Random

    随机地址分为两种

    • 静态随机地址

      随机生成的,其中MSB最高两位必须为 11

    • 私有随机地址
      • Non-Resolvable

        不解析私有地址,MSB最高两位必须为 00,隔一段时间会自动变化一次

      • Resolvable

        解析私有地址, MSB最高两位必须为 01, 由24bit(MSB)随机数 + 24bit hash组成

一般静态随机地址比较常用,可以通过 sd_ble_gap_addr_set 函数在广播开始前设置蓝牙MAC地址。

ble_gap_addr_t gap_addr = 

     .addr_type = BLE_GAP_ADDR_TYPE_PUBLIC,
     .addr = 0x00, 0x11, 0x00, 0xE9, 0x81, 0xC9
;
sd_ble_gap_addr_set(&gap_addr);

GAP 蓝牙设备名称

GAP中包含了蓝牙的名称,但是蓝牙名称信息是通过广播包传递给周围设备的,因此想要其他设备可以获取自己的蓝牙名称,需要在广播初始化时向广播包中添加蓝牙名称信息。

#define DEVICE_NAME                     "Nordic_Blinky"    
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
sd_ble_gap_device_name_set(&sec_mode,(const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));

注意大多数手机使用的是UTF-8编码格式,因此想要手机上显示中文蓝牙设备名,需要修改MDK文件编码格式为UTF-8

GAP 蓝牙图标

GAP中包含了蓝牙的图标信息,但是蓝牙图标信息也是通过广播包传递给周围设备的,因此想要其他设备可以获取对应的蓝牙图标,需要在广播初始化时向广播包中添加蓝牙图标信息。

/** @defgroup BLE_APPEARANCES Bluetooth Appearance values
 *  @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
 * @ */
#define BLE_APPEARANCE_UNKNOWN                                0 /**< Unknown. */
#define BLE_APPEARANCE_GENERIC_PHONE                         64 /**< Generic Phone. */
#define BLE_APPEARANCE_GENERIC_COMPUTER                     128 /**< Generic Computer. */
#define BLE_APPEARANCE_GENERIC_WATCH                        192 /**< Generic Watch. */
#define BLE_APPEARANCE_WATCH_SPORTS_WATCH                   193 /**< Watch: Sports Watch. */
#define BLE_APPEARANCE_GENERIC_CLOCK                        256 /**< Generic Clock. */
#define BLE_APPEARANCE_GENERIC_DISPLAY                      320 /**< Generic Display. */
#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL               384 /**< Generic Remote Control. */
#define BLE_APPEARANCE_GENERIC_EYE_GLASSES                  448 /**< Generic Eye-glasses. */
#define BLE_APPEARANCE_GENERIC_TAG                          512 /**< Generic Tag. */
#define BLE_APPEARANCE_GENERIC_KEYRING                      576 /**< Generic Keyring. */
#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER                 640 /**< Generic Media Player. */
#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER              704 /**< Generic Barcode Scanner. */
#define BLE_APPEARANCE_GENERIC_THERMOMETER                  768 /**< Generic Thermometer. */
#define BLE_APPEARANCE_THERMOMETER_EAR                      769 /**< Thermometer: Ear. */
#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR            832 /**< Generic Heart rate Sensor. */
#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT    833 /**< Heart Rate Sensor: Heart Rate Belt. */
#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE               896 /**< Generic Blood Pressure. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM                   897 /**< Blood Pressure: Arm. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST                 898 /**< Blood Pressure: Wrist. */
#define BLE_APPEARANCE_GENERIC_HID                          960 /**< Human Interface Device (HID). */
#define BLE_APPEARANCE_HID_KEYBOARD                         961 /**< Keyboard (HID Subtype). */
#define BLE_APPEARANCE_HID_MOUSE                            962 /**< Mouse (HID Subtype). */
#define BLE_APPEARANCE_HID_JOYSTICK                         963 /**< Joystick (HID Subtype). */
#define BLE_APPEARANCE_HID_GAMEPAD                          964 /**< Gamepad (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE                 965 /**< Digitizer Tablet (HID Subtype). */
#define BLE_APPEARANCE_HID_CARD_READER                      966 /**< Card Reader (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITAL_PEN                      967 /**< Digital Pen (HID Subtype). */
#define BLE_APPEARANCE_HID_BARCODE                          968 /**< Barcode Scanner (HID Subtype). */
#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER               1024 /**< Generic Glucose Meter. */
#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR      1088 /**< Generic Running Walking Sensor. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE      1089 /**< Running Walking Sensor: In-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE      1090 /**< Running Walking Sensor: On-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP       1091 /**< Running Walking Sensor: On-Hip. */
#define BLE_APPEARANCE_GENERIC_CYCLING                     1152 /**< Generic Cycling. */
#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER            1153 /**< Cycling: Cycling Computer. */
#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR                1154 /**< Cycling: Speed Sensor. */
#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR              1155 /**< Cycling: Cadence Sensor. */
#define BLE_APPEARANCE_CYCLING_POWER_SENSOR                1156 /**< Cycling: Power Sensor. */
#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR        1157 /**< Cycling: Speed and Cadence Sensor. */
#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER              3136 /**< Generic Pulse Oximeter. */
#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP            3137 /**< Fingertip (Pulse Oximeter subtype). */
#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN           3138 /**< Wrist Worn(Pulse Oximeter subtype). */
#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE                3200 /**< Generic Weight Scale. */
#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT          5184 /**< Generic Outdoor Sports Activity. */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP         5185 /**< Location Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD          5187 /**< Location Pod (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD  5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */

//设置图标信息
sd_ble_gap_appearance_set(uint16_t appearance);

GAP 连接参数

主从机配对连接后,每隔一段时间,主机会向从机发送一包数据,从机接到主机数据后发一包数据给主机,用与主从机之间数据交换和连接状态判断(没有数据包会发生连接超时,断开连接)。

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(100, UNIT_1_25_MS)        /**< Minimum acceptable connection interval (0.5 seconds). */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(200, UNIT_1_25_MS)        /**< Maximum acceptable connection interval (1 second). */
#define SLAVE_LATENCY                   0                                       /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)         /**< Connection supervisory time-out (4 seconds). */

/**@brief Function for the GAP initialization.
 *
 * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
 *          device including the device name, appearance, and the preferred connection parameters.
 */
static void gap_params_init(void)

    ret_code_t              err_code;
    ble_gap_conn_params_t   gap_conn_params;

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

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);

连接参数解释
最小连接间隔范围 7.5ms - 4000ms 蓝牙连接后每隔一段时间唤醒一次射频模块进行主从机通信,连接间隔越长则越省电但是数据传输延迟和传输速率会越小
最大连接间隔当没有数据时,主从机为了省电使用最大连接间隔 发生空数据包保持连接状态
潜伏周期从机可以跳过连接数据包的次数。当潜伏周期为3时,如果从机没有数据需要发送则从机可以跳过三次连接数据包(不应答主机),从而降低从机功耗。
超时时间超过超时时间还没有接收到蓝牙数据包,会产生超时事件,可以在超时事件中断开蓝牙连接。范围 100ms - 32000ms。 超时时间 >= 连接间隔 * ( 潜伏周期 + 1)

其中图中M为主机发送的数据包, S为从机发送的数据包,当潜伏周期为0时,每个主机数据包从机均需要应答,而当潜伏周期为3时,从机可以跳过三个数据包应答一次主机。

连接参数初始化

在NRF52832协议栈中,当主从机连接后,如果想要修改GAP连接参数,需要从机向主机发起连接参数更新请求(从机发起连接参数请求前,使用主机的连接参数),主机收到连接参数更新请求后,如果同意更新GAP参数则会更改自身GAP参数然后向从机发送同意连接参数更新。从机是何时发起连接参数更新请求?

ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init)

    ret_code_t err_code;

    VERIFY_PARAM_NOT_NULL(p_init);

    m_conn_params_config = *p_init;
    m_conn_params_config.p_conn_params = &m_preferred_conn_params;

    if (p_init->p_conn_params != NULL)
    
        // Set the connection params in stack.
        err_code = sd_ble_gap_ppcp_set(p_init->p_conn_params);
        if (err_code != NRF_SUCCESS)
        
            return err_code;
        
        m_preferred_conn_params = *p_init->p_conn_params;
    
    else
    
        // Get the (default) connection params from stack.
        err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
        if (err_code != NRF_SUCCESS)
        
            return err_code;
        
    

    //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0
    for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i++)
    
        ble_conn_params_instance_t * p_instance = &m_conn_params_instances[i];

        instance_free(p_instance);
        p_instance->timer_id = &m_timer_data[i];

        err_code = app_timer_create(&p_instance->timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            update_timeout_handler);
        if (err_code != NRF_SUCCESS)
        
            return NRF_ERROR_INTERNAL;
        
    
    //lint -restore

    return NRF_SUCCESS;

/**@brief Function for initializing the Connection Parameters module.
 */
static void conn_params_init(void)

    ret_code_t             err_code;
    ble_conn_params_init_t cp_init;

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

    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; //主从机连接后,延时多长时间进行第一次参数更新请求
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;  //延时多长时间进行第二次参数更新请求
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;   //最大尝试更新次数
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;        //GAP 通知服务句柄
    cp_init.disconnect_on_fail             = false;                          //更新不成功自动断开连接?
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;

    err_code = ble_conn_params_init(&cp_init);
    APP_ERROR_CHECK(err_code);

ble_conn_params_init 函数其实就是创建了几个软件定时器,在软件定时器超时回调函数 update_timeout_handler 中发送参数更新请求。ble_conn_params.c中注册了一个观察者回调函数,当主从机连接成功后,会在 on_connect(p_ble_evt); 函数中开启参数更新软件定时器。

/**
 * @brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt       Event received from the BLE stack.
 * @param[in]   p_context       Context.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)

    switch (p_ble_evt->header.evt_id)
    
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_ble_evt);
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:
            on_write(p_ble_evt);
            break;

        case BLE_GAP_EVT_CONN_PARAM_UPDATE:
            on_conn_params_update(p_ble_evt);
            break;

        default:
            // No implementation needed.
            break;
    

广播初始化

广播格式

普通广播包最长为31 byte,如果不够还可以将广播信息放到广播回包中,广播回包也是31 byte。

蓝牙5.1以后引入拓展广播包以支持蓝牙测向(AOA,DOA)功能,但是没用过nrf52832也不支持。

#define BLE_GAP_ADV_SET_DATA_SIZE_MAX                    (31) 
static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];                    /**< Buffer for storing an encoded advertising set. */
static uint8_t m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];         /**< Buffer for storing an encoded scan data. */

/**@brief Struct that contains pointers to the encoded advertising data. */
static ble_gap_adv_data_t m_adv_data =

    .adv_data =
    
        .p_data = m_enc_advdata,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    ,
    .scan_rsp_data =
    
        .p_data = m_enc_scan_response_data,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
;
以上是关于nrf52832 学习笔记蓝牙从机广播的主要内容,如果未能解决你的问题,请参考以下文章

nrf52832 学习笔记蓝牙主机扫描

nrf52832 学习笔记蓝牙主机扫描

nrf52832 学习笔记蓝牙从机Proflies开发

nrf52832 学习笔记蓝牙从机Proflies开发

nrf52832 学习笔记蓝牙从机Proflies开发

nrf52832 学习笔记蓝牙主从机连接和连接参数更新