【单片机】nRF52832 实现停止蓝牙广播接口

前言

      有一个项目使用了 nRF52832 芯片作为主控,其中有用到蓝牙功能。在对蓝牙接口进一步封装的时候,发现 SDK 居然没有停止广播的接口,咨询了代理 FAE,对方也没有找到关闭广播的接口。后来通过分析代码,修改了 SDK 解决了这个问题。这次发出来是因为遇到很多人在问这个问题,记得自己解决过,就发出来。

     遗憾的是,当初为了赶项目,很多问题解决之后没有及时做记录,现在已经记不清当时的解决思路了,毕竟第一次接触 Nordic 芯片,后面又基本没用上,不过 Nordic SDK 的代码风格还是很赞的。

     想不明白,为什么 Nordic 不提供关闭蓝牙广播的接口,SDK已经迭代了那么多个版本了,可能是因为对功耗影响不大所以没有必要提供了?还是说有其他的方式可以关闭蓝牙广播接口?

补丁

适用于 SDK15

From 67a4b2c241626e51192f6e1d528a07ba0ac4ab8d Mon Sep 17 00:00:00 2001
From: lmx 
Date: Thu, 6 Jun 2019 18:37:50 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9SDK:=20ble=5Fadvertising,=20?=
 =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=8F=AF=E4=BB=A5=E9=9A=8F=E6=84=8F=E5=81=9C?=
 =?UTF-8?q?=E6=AD=A2=E5=B9=BF=E6=92=AD=E7=9A=84=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ble/ble_advertising/ble_advertising.c     | 29 ++++++++++++++-----
 .../ble/ble_advertising/ble_advertising.h     | 11 +++++++
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/components/ble/ble_advertising/ble_advertising.c b/components/ble/ble_advertising/ble_advertising.c
index e09c2dd..5907b2f 100644
--- a/components/ble/ble_advertising/ble_advertising.c
+++ b/components/ble/ble_advertising/ble_advertising.c
@@ -459,6 +459,7 @@ uint32_t ble_advertising_init(ble_advertising_t            * const p_advertising
     p_advertising->error_handler                  = p_init->error_handler;
     p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID;
     p_advertising->p_adv_data                     = &p_advertising->adv_data;
+	p_advertising->flags						   = BLE_ADVERTISING_FLAGS_ENABLE;		// add lmx 20190606
 
     memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address));
 
@@ -531,6 +532,18 @@ static bool phy_is_valid(uint32_t const * const p_phy)
     }
 }
 
+// add lmx 20190606 设置标志位
+uint32_t ble_advertising_set_flag(ble_advertising_t * const p_advertising, ble_advertising_flags_t flags)
+{
+    if (p_advertising->initialized == false)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+		
+	p_advertising->flags = flags;
+		
+	return NRF_SUCCESS;
+}
 
 uint32_t ble_advertising_start(ble_advertising_t * const p_advertising,
                                ble_adv_mode_t            advertising_mode)
@@ -644,18 +657,20 @@ uint32_t ble_advertising_start(ble_advertising_t * const p_advertising,
 
     if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE)
     {
-
         ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params);
         if (ret != NRF_SUCCESS)
         {
             return ret;
         }
-        ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag);
-
-        if (ret != NRF_SUCCESS)
-        {
-            return ret;
-        }
+		// add lmx 20190606
+		if(BLE_ADVERTISING_FLAGS_ENABLE == p_advertising->flags)
+		{
+			ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag);
+			if (ret != NRF_SUCCESS)
+			{
+				return ret;
+			}
+		}
     }
 
     if (p_advertising->evt_handler != NULL)
diff --git a/components/ble/ble_advertising/ble_advertising.h b/components/ble/ble_advertising/ble_advertising.h
index 8840821..96ef6f2 100644
--- a/components/ble/ble_advertising/ble_advertising.h
+++ b/components/ble/ble_advertising/ble_advertising.h
@@ -141,6 +141,13 @@ typedef void (*ble_adv_evt_handler_t) (ble_adv_evt_t const adv_evt);
 /**@brief   BLE advertising error handler type. */
 typedef void (*ble_adv_error_handler_t) (uint32_t nrf_error);
 
+// add lmx 20190606
+typedef enum
+{
+	BLE_ADVERTISING_FLAGS_ENABLE,						// 表示可以启用广播
+	BLE_ADVERTISING_FLAGS_DISABLE,						// 表示禁止启用广播
+}ble_advertising_flags_t;
+
 typedef struct
 {
     bool                    initialized;
@@ -166,6 +173,7 @@ typedef struct
     bool                    whitelist_temporarily_disabled;                   /**< Flag to keep track of temporary disabling of the whitelist. */
     bool                    whitelist_reply_expected;                         /**< Flag to verify that the whitelist is only set when requested. */
     bool                    whitelist_in_use;                                 /**< This module needs to be aware of whether or not a whitelist has been set (e.g. using the Peer Manager) in order to start advertising with the proper advertising params (filter policy). */
+		ble_advertising_flags_t	flags;																						// add lmx 20190606
 } ble_advertising_t;
 
 typedef struct
@@ -257,6 +265,9 @@ void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, u
 uint32_t ble_advertising_start(ble_advertising_t * const p_advertising,
                                ble_adv_mode_t            advertising_mode);
 
+// add lmx 20190606 设置标志位
+uint32_t ble_advertising_set_flag(ble_advertising_t * const p_advertising, ble_advertising_flags_t flags);
+
 
 /**@brief   Function for setting the peer address.
  *
-- 
2.21.0.windows.1

应用

启动蓝牙并等待连接

// 启动蓝牙并等待连接
int8_t bluetooth_start(void)
{
	uint32_t err_code = 0;
	
	if(BLE_ADV_EVT_IDLE != ble_adv_event)
	{
		NRF_LOG_ERROR("ble_adv_event != BLE_ADV_EVT_IDLE...");
		NRF_LOG_FLUSH();
		return -2;
	}	
	
	ble_advertising_set_flag(&m_advertising, BLE_ADVERTISING_FLAGS_ENABLE);
	err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
	APP_ERROR_CHECK(err_code);
	
	return 0;
}

停止蓝牙广播并断开连接


// 停止蓝牙广播并断开连接
int8_t bluetooth_stop(void)
{
	uint32_t err_code;
	
	if(BLE_ADV_EVT_FAST != ble_adv_event)
	{
		return -2;
	}	

	ble_advertising_set_flag(&m_advertising, BLE_ADVERTISING_FLAGS_DISABLE);
	if(m_conn_handle != BLE_CONN_HANDLE_INVALID)
	{
		err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
		APP_ERROR_CHECK(err_code);
		
                // 这里建议增加超时机制, 不宜死循环一直等待
		while (m_conn_handle != BLE_CONN_HANDLE_INVALID)
		{
			NRF_LOG_INFO("wait disconnect...");
			NRF_LOG_FLUSH();
			nrf_delay_ms(10);
		}
	}

	sd_ble_gap_adv_stop(m_advertising.adv_handle);
	err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE);
        APP_ERROR_CHECK(err_code);

	return 0;
}

注意

这里省略了初始化部分,提供启动和停止两个函数的实现意在表明使用方法,具体可参考 SDK 示例代码。

你可能感兴趣的:(单片机,#nRF52832)