nrf52832 一主机多从机

代码编写

1.添加device_stor()函数(保存设备地址和连接句柄函数)

//定义保存从机MAC地址的数组:
//NRF_SDH_BLE_CENTRAL_LINK_COUNT行,BLE_GAP_ADDR_LEN列
uint8_t addrs[NRF_SDH_BLE_CENTRAL_LINK_COUNT][BLE_GAP_ADDR_LEN];//mac地址保存
//保存设备地址和连接句柄
void device_stor(ble_nus_c_t * p_ble_nus_c, ble_gap_evt_t const * connect)
{
	p_ble_nus_c->addr.addr[0] = connect->params.connected.peer_addr.addr[0];
	p_ble_nus_c->addr.addr[1] = connect->params.connected.peer_addr.addr[1];
	p_ble_nus_c->addr.addr[2] = connect->params.connected.peer_addr.addr[2];
	p_ble_nus_c->addr.addr[3] = connect->params.connected.peer_addr.addr[3];
	p_ble_nus_c->addr.addr[4] = connect->params.connected.peer_addr.addr[4];
	p_ble_nus_c->addr.addr[5] = connect->params.connected.peer_addr.addr[5];
	//保存MAC地址到自己定义的数组			      
	memcpy(addrs[connect->conn_handle], connect->params.connected.peer_addr.addr, 6);
//	p_ble_nus_c->conn_handle=connect->conn_handle;	//保存连接句柄
}

2.多服务发现和句柄分配

//BLE_DB_DISCOVERY_DEF(m_db_disc);   //   BLE_ DB_ DISCOVERY_ DEF发现观察函数注册的本次发现
//BLE_NUS_C_DEF(m_ble_nus_c);  
BLE_NUS_C_ARRAY_DEF(m_ble_nus_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);   
BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_CENTRAL_LINK_COUNT);  /**< Database discovery module instances. */                                      /**< Database discovery module instance. */

3.修改ble_evt_handler()函数(蓝牙事件处理函数)

3.1 屏蔽单主机的服务查找代码

如下图:

3.2 添加一主机多从机连接代码


        case BLE_GAP_EVT_CONNECTED:
				//================发现从机服务添加===START
				//一主机多从机:屏蔽单从机的时候服务发现函数
//            err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
//            APP_ERROR_CHECK(err_code);
				//================发现从机服务添加===END

           //连接的时候指示灯亮
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
				    NRF_LOG_INFO("conn_handle: 0x%x",
                         p_gap_evt->conn_handle
                        );
            APP_ERROR_CHECK(err_code);
				    NRF_LOG_INFO("connect OK!");
						//主机发起PHY更新请求
				    err_code = sd_ble_gap_phy_update(p_gap_evt->conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
						//打印更新请求的参数值

				    NRF_LOG_INFO("LL_PHY_REQ!");
				    NRF_LOG_INFO("rx_phys: %d",phys.rx_phys);
					  NRF_LOG_INFO("tx_phys: %d",phys.tx_phys);
				
				//================发现从机服务添加===START
				//一主机多从机:屏蔽单从机的时候服务发现函数
//            NRF_LOG_INFO("start discovery services");//添加开始发现服务提示
//            // 添加主服务数据发现汗水//开启发现服务,nus客户端等地啊发现结果
//            err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
//            APP_ERROR_CHECK(err_code);
				//================发现从机服务添加===END
				//====一主机多从机添加==================
            APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);
				
             //分配不同的连接句柄
            err_code = ble_nus_c_handles_assign(&m_ble_nus_c[p_gap_evt->conn_handle],
                                                p_gap_evt->conn_handle,
                                                NULL);
            APP_ERROR_CHECK(err_code);
          // 开始发现服务,需要分配不同的句柄
            err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                              p_gap_evt->conn_handle);
				
            APP_ERROR_CHECK(err_code);
						
					   	 //打印MAC地址
				     printf("Connecting to target %02x%02x%02x%02x%02x%02x",
                      p_gap_evt->params.connected.peer_addr.addr[0],
                      p_gap_evt->params.connected.peer_addr.addr[1],
                      p_gap_evt->params.connected.peer_addr.addr[2],
                      p_gap_evt->params.connected.peer_addr.addr[3],
                      p_gap_evt->params.connected.peer_addr.addr[4],
                      p_gap_evt->params.connected.peer_addr.addr[5]
                      );
			     //打印MAC地址对应的连接句柄	
				    printf("Connection 0x%x established, starting DB discovery.",
                         p_gap_evt->conn_handle);
						
						device_stor(&m_ble_nus_c[p_gap_evt->conn_handle],p_gap_evt);
				    			      
				        			
						  if (err_code != NRF_ERROR_BUSY)
            {
                APP_ERROR_CHECK(err_code);
            }

            // Update LEDs status and check whether it is needed to look for more
            // peripherals to connect to.
            bsp_board_led_on(CENTRAL_CONNECTED_LED);//连接成功点亮LED指示
            if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
            {
                bsp_board_led_off(CENTRAL_SCANNING_LED);//连接完所有设备LED指示
            }
            else
            {
                // Resume scanning.
                bsp_board_led_on(CENTRAL_SCANNING_LED);
                scan_start();
            }
				//一主机多从机添加======================
            break;

3.3 添加LED宏定义

#define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0
#define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1

4.修改nus_c_init()函数(主机客户端初始化函数)

将主机初始化函数修改成如下内容:

static void nus_c_init(void)//主机客户端初始化
{
    ret_code_t       err_code;
    ble_nus_c_init_t init;

    init.evt_handler = ble_nus_c_evt_handler;

	 for (uint32_t i = 0; i < NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
    {
     err_code = ble_nus_c_init(&m_ble_nus_c[i], &init);
    APP_ERROR_CHECK(err_code); 
    }
   
}

5.  添加设备地址比较函数

//输入地址和连接的设备地址
//con_addr:连接设备的地址
//uart_addr:输入的地址
uint8_t compare_addr(uint8_t con_addr[BLE_GAP_ADDR_LEN],uint8_t  uart_addr[BLE_GAP_ADDR_LEN])
{
		for(uint8_t i=0;i<BLE_GAP_ADDR_LEN;i++)
		{
		    if(con_addr[i] != uart_addr[i])return 1;
		}
	  return 0;
}
//如果输入的地址符合连接的设备地址,则把连接地址的连接句柄赋值给本次输入
//p_ble_nus_c:本次连接结构
//addr:输入的地址
uint16_t set_con_handle(ble_nus_c_t * p_ble_nus_c,uint8_t * addr)
{
	for(uint32_t i=0;i<NRF_SDH_BLE_CENTRAL_LINK_COUNT;i++)
	{
		if((p_ble_nus_c->addr.addr[0] != 0x00) && (p_ble_nus_c->conn_handle != BLE_CONN_HANDLE_INVALID))
		{
		  
			if(compare_addr(&p_ble_nus_c->addr.addr[0],addr) == 0)//表示输入的地址和存储的地址相等
			{
				return p_ble_nus_c->conn_handle;//分配存储的地址对应的句柄
			}
		}
    p_ble_nus_c++;//如果不相等,继续搜寻		
	}
	return 0xFFFF;
}

6.修改db_disc_handler()函数(注册的数据发现事件处理函数:函数)

//发现处理事件需要区分不同的句柄
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
	
  NRF_LOG_DEBUG("call to ble_lbs_on_db_disc_evt for instance %d and link 0x%x!",
                  p_evt->conn_handle,
                  p_evt->conn_handle);
   ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
}

7.编写主机向从机发送函数

//主机向从机发送数据函数
void Master_to_slave(uint8_t *addr, uint8_t* data_array, uint8_t dataA_len)
{
	//获取连接句柄
	 uint16_t con_handle;
	for(uint8_t i = 0;i < NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
	{
		//遍历获取MAC地址对应的连接句柄
		con_handle	= set_con_handle(&m_ble_nus_c[i],addr);
		if(con_handle != 0xFFFF)
		{
			//如果获取到响应MAC地址的句柄,结束遍历
			break;
		}
	}
	uint32_t ret_val;
	if(con_handle != 0xFFFF)
	{
		//打印发送MAC地址
		NRF_LOG_INFO("Send to target:");
		NRF_LOG_HEXDUMP_DEBUG(addr, 6);//打印数组
		//打印发送的数据
		NRF_LOG_INFO("Send data:");
		NRF_LOG_HEXDUMP_DEBUG(data_array, dataA_len);//打印数组
		do
		{
	//向对应连接句柄的从机发送数据
			ret_val = ble_nus_c_string_send(&m_ble_nus_c[con_handle], data_array, dataA_len);
				if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
				{
						APP_ERROR_CHECK(ret_val);
				}
		} while (ret_val == NRF_ERROR_RESOURCES);
	}
	else
	{
		NRF_LOG_DEBUG("send con_handle 0x%x",con_handle);
	}
}

工程配置

1.修改ble_nus_c_s结构体

由于需要连接多个设备,需要添加保存设备MAC地址的数组;

struct ble_nus_c_s
{
	  ble_gap_addr_t            addr;//添加保存MAC地址的数组
    uint8_t                 uuid_type;      /**< UUID type. */
    uint16_t                conn_handle;    /**< Handle of the current connection. Set with @ref ble_nus_c_handles_assign when connected. */
    ble_nus_c_handles_t     handles;        /**< Handles on the connected peer device needed to interact with it. */
    ble_nus_c_evt_handler_t evt_handler;    /**< Application event handler to be called when there is an event related to the NUS. */
};

2.文件添加

2.1 添加头文件以及目录

添加头文件:#include "ble_conn_state.h"

添加文件目录

2.2 添加.c文件

添加文件ble_conn_state.c

添加文件nrf_atflags.c

3.配置sdk_config.h文件

 

错误调试

错误1,工程RAM设置不对

现象

原因

工程的RAM设置没有根据增加从机的数量而改变;

解决

将工程RAM按照log打印提示修改

结果:问题解决

错误2,运行卡在连接的地方

现象:

log打印:

断点运行如下图

原因

重启之后可以运行到断点1却不能运行到断点2,说明程序是卡在断点1的语句处;

这里我们可以注意到,断点1处是串口打印语句,是我们从18.《一主机多从机(串口主机)》例程复制代码的时候一起复制过来的,但是本工程并没有用到串口,我们使用了未初始化的外设,所以程序会卡着。

解决:

将串口相关代码替换成LOG打印;

测试与总结

测试连接设备

测试方法:开启蓝牙板作为从机,开启仿真之后,可以看到log打印:

在watch窗口查看保存MAC地址的数组,如下图:

设备MAC地址保存成功,说明连接成功;

测试数据发送:

连接成功之后,按下按键4,主机每2秒向从机发送一次0X02;

log打印:

打开抓包器软件查看从机收到的数据和从机收到的时间

测试数据接收

按下按键3停止定时发送,按下按键2向从机发送0x05,从机即可返回已拍摄照片张数;

log打印如下:

抓包器抓包如下:

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值