最近在搞蓝牙主从通信这块,公司里面是有之前的代码的,但是自己想在自己52832开发板上弄一个主从通信。从机板子是52832的,从机代码采用官方的串口例程,主机是公司的51822板子,主机代码也是公司的,因为对这块不熟悉,造成主从不能通信,最后请教老员工才知道,他们把蓝牙服务的UUID更改成蓝牙技术联盟的基本UUID的问题,找到问题后,自己改了一下UUID类型,也就成功了,刚好趁这次机会,把UUID从128bit改成16bit的方式,也做个笔记,写出来。本次运用的sdk依旧是SDK12.3版本。好了,先说简单的更改UUID这块。

1、UUID更改步骤以及注意事项

如果你是使用官方的标准128bitUUID,也就不需要经过这个步骤,但是,如果遇到需要更改的时候,可以参考一下。更改了UUID位数,要注意的是主从通信时候,主机会根据从机的主服务UUID名和类型,来和从机通信的,这点要注意。我们先说从机的更改,主机的更改放在主从通信这块来讲解。

步骤1:在从机串口服务初始化函数里面,我们修改一下红色地方

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_UUID更改


第一个地方,直接屏蔽掉,

第2的地方,我们要更改一下服务类型,为BLE_UUID_TYPE_BLE

第3,4,5,的地方,我们要更改一下主服务,RX,TX的UUID宏定义

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_nrf51822主从通信_02


第4,5函数里面更改的地方是一样的,贴出一个就行了

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_初始化_03


最后,我们更改的地方是广播数组

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_初始化_04


更改完成以后,我们顺便把广播名更改了,因为此次例程是根据设备名来寻找从机设备的,主机寻找的设备名要和从机的一样。

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_UUID更改_05


更改好以后,下载进开发板里面,我们可以看到广播与以前 的不一样的地方。

以前的是:

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_设备名_06


更改以后是;

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_UUID更改_07


到这里,就已经完成了,下面我们开始讲主从通信这块。主从通信例程这块,大家可以对照官网给的例程查看,路径为D:\nRF5_SDK_12.3.0_d7731ad\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay;我也是在这个例程上修改的。

1、修改宏定义,其实这个官网例程已经修改好了,也可以不必须修改。

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_nrf51822主从通信_08


可以看图片上的宏定义,CENTRAL_LINK_COUNT是作为主机时候,可以连接多少设备,PERIPHERAL_LINK_COUNT是作为从机时候,可以连接多少设备。此处均设为1。也就是说,作为从机时候,连接一个主设备。作为主机时候,连接一个从机设备。

2、向下可以到协议栈初始化,协议栈初始化没什么改变,主要是他的回调函数里面,与之前不一样。我们看一下

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_UUID更改_09


我们可以看出,作为从机时候,里面的派发函数与之前官网的一样,但是,我们是让他作为主机,这里我们不必过多查看,主要看作为主机时候的三个派发函数:

1、static void on_ble_central_evt(const ble_evt_t * const p_ble_evt) //主机事假派发函数

2、void ble_db_discovery_on_ble_evt(ble_db_discovery_t * const p_db_discovery,

const ble_evt_t * const p_ble_evt) //数据发现事件派发函数

3、ble_nus_c_on_ble_evt(&central_to_perihterial, p_ble_evt) //主从通信事件派发函数

我们按照主机发现设备—>连接设备----->数据交互过程讲解。

首先是发现设备:在on_ble_central_evt()函数里面会有报告BLE_GAP_EVT_ADV_REPORT,可以跳过去看一下这个代码

case BLE_GAP_EVT_ADV_REPORT:
        {
					  //¼ìÑéÐźÅ
					 uint8_t rssi_val = p_ble_evt->evt.gap_evt.params.adv_report.rssi;
					{
						if(rssi_val>0xC9)
						{
               if (strlen(m_target_periph_name) != 0)
								{
										if (find_adv_name(&p_gap_evt->params.adv_report, m_target_periph_name))
										{
												// Initiate connection.
												err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr,
																											&m_scan_params,
																											&m_connection_param);
										  
											
												if (err_code != NRF_SUCCESS)
												{
														NRF_LOG_INFO("Connection Request Failed, reason %d\r\n", err_code);
												}
										}
								}
					  }
					}
//            else
//            {
//               /** We do not want to connect to two peripherals offering the same service, so when
//                *  a UUID is matched, we check that we are not already connected to a peer which
//                *  offers the same service. */
//                if ((find_adv_uuid(&p_gap_evt->params.adv_report, 0xA8A0)&&
//                     (m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID)))
//                {
//                    // Initiate connection.
//                    err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr,
//                                                  &m_scan_params,
//                                                  &m_connection_param);
//                    if (err_code != NRF_SUCCESS)
//                    {
//                        NRF_LOG_INFO("Connection Request Failed, reason %d\r\n", err_code);
//                    }
//                }
//            }
        } break; // BLE_GAP_ADV_REPORT

在这里后面的通过UUID查找设备我屏蔽掉了,用到按照设备名寻找设备,我们可以看一下函数find_adv_name();

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_设备名_10


我用RTT打印了一下发现设备名的名称。看到函数,我们可以发现就是获取到设备名以后,通过对比我们设置的需要连接的设备名数组

static const char m_target_periph_name[] = “lvyapeng”;是否一样,

如果一样,就开始进行连接,如果不是,搜索下一个。如果连接成功,就会触发连接事件BLE_GAP_EVT_CONNECTED,还是在这个函数里面,我们可以看一下。

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_数据_11


首先判断结构体m_conn_handle_nus_c是否等于BLE_CONN_HANDLE_INVALID,其中,我修改了地方是定义一个全局结构体

static uint16_t m_conn_handle_nus_c = BLE_CONN_HANDLE_INVALID;

官方之前定义了两个,我给删除了,用了自己的,因为后面的主从通信要用到。建议最好用自己定义的,把官网定义的替换掉。

在这里,我定义了一个bool类型的全局变量Send_cmd_flag,来判断是否可以发送数据给从机。函数ble_db_discovery_start()是进行数据发现和连接的功能。因为这些地方都没修改,所以简单讲解一下。后面的两个函数ble_db_discovery_on_ble_evt()和ble_nus_c_on_ble_evt(),也是一样没有修改的地方,不做讲解。

3、蓝牙数据发现初始化

static void db_discovery_init(void)
{
    ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
    APP_ERROR_CHECK(err_code);
}

这个没什么好说的,不过,我们要在他的回调里面增加数据发现处理

static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
//    ble_rscs_on_db_disc_evt(&m_ble_rsc_c, p_evt);
//    ble_hrs_on_db_disc_evt(&m_ble_hrs_c, p_evt);
    ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt);

}

在void ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)函数里面,我们要修改的地方在下面

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_数据_12


因为这里就是判断哪个服务是自己要进行通信的,之前我们修改了从机的类型和服务UUID,所以这里也要修改。

4、主机到从机数据流向。

nus_c_init();就是初始化主从数据通信这块了,我们可以跳进去看一下

static void nus_c_init(void)
{
    uint32_t           err_code;
    ble_nus_c_init_t   nus_c_init_obj;

    nus_c_init_obj.evt_handler = ble_nus_c_evt_handler;

    err_code = ble_nus_c_init(&m_ble_nus_c, &nus_c_init_obj);
    APP_ERROR_CHECK(err_code);
}

这些就是主从通信数据交互的初始化,、因为从机修改了服务UUID和类型,这里也要修改,具体如下

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_初始化_13


步骤和从机一样,把服务类型和uuID修改了

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_nrf51822主从通信_14


简单修改就行,这里主要注意他的回调函数。

static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, const ble_nus_c_evt_t * p_ble_nus_evt)

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_设备名_15


两者进行数据交互的时候,首先是触发数据发现事件BLE_NUS_C_EVT_DISCOVERY_COMPLETE

如果需要从机发送数据给主机,就使能rx_notify。使能以后,就可接收数据,触发BLE_NUS_C_EVT_NUS_RX_EVT事件,这里我只是打印一个数据就行了。

这两个函数,ble_nus_c_handles_assign是获得校验从机服务参数的
ble_nus_c_rx_notif_enable是发现有RX通知特性,就打开RX使能,进行数据接收。
4、当主从连接好以后,就可以使用发送函数ble_nus_c_string_send(),我在测试过程中,发现虽然我的标志位Send_cmd_flag置1,主循环判断标志位,然后发送,但是会出现发送失败现象,经过测试,发现需要在连接成功以后,延时一段时间在发送才行,我是延时1s在发送数据的。

uint32_t ble_nus_c_string_send(ble_nus_c_t * p_ble_nus_c, uint8_t * p_string, uint16_t length)

发送数据。
5、主机开始扫描

static void adv_scan_start(void)
{
    ret_code_t err_code;
    uint32_t count;
    //check if there are no flash operations in progress
    printf"scan_start%02x\r\n",count);
    if (count == 0)
    {
        scan_start();
        err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
}

在这里面,主要是开始扫描和广播开始,我们关注扫描函数

static void scan_start(void)
{
    ret_code_t err_code;

    (void) sd_ble_gap_scan_stop();

    err_code = sd_ble_gap_scan_start(&m_scan_params);
    // It is okay to ignore this error since we are stopping the scan anyway.
    if (err_code != NRF_ERROR_INVALID_STATE)
    {
        APP_ERROR_CHECK(err_code);
    }
}

这个函数里面有一个结构体

static const ble_gap_scan_params_t m_scan_params =
{
    .active   = 1,
    .interval = SCAN_INTERVAL,
    .window   = SCAN_WINDOW,
    .timeout  = SCAN_TIMEOUT,
    #if (NRF_SD_BLE_API_VERSION == 2)
        .selective   = 0,
        .p_whitelist = NULL,
    #endif
    #if (NRF_SD_BLE_API_VERSION == 3)
        .use_whitelist = 0,
    #endif
};

我在这里就不细说了,直接截屏网上的一段资料给大家

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_设备名_16


6、发送函数,是定义一个软件定时,10ms触发一次回调函数

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_UUID更改_17


这样就可以打开RTT,把主从程序下载进去,查看一下数据就行了,条件可以,也可以仿真一下,数据发送与接收的对不对,我的测试是没有问题的。

3568 Android11 BluetoothAdapter更改蓝牙名称 修改蓝牙uuid_初始化_18