NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID

最近在搞蓝牙主从通信这块,公司里面是有之前的代码的,但是自己想在自己52832开发板上弄一个主从通信。从机板子是52832的,从机代码采用官方的串口例程,主机是公司的51822板子,主机代码也是公司的,因为对这块不熟悉,造成主从不能通信,最后请教老员工才知道,他们把蓝牙服务的UUID更改成蓝牙技术联盟的基本UUID的问题,找到问题后,自己改了一下UUID类型,也就成功了,刚好趁这次机会,把UUID从128bit改成16bit的方式,也做个笔记,写出来。本次运用的sdk依旧是SDK12.3版本。好了,先说简单的更改UUID这块。
1、UUID更改步骤以及注意事项
如果你是使用官方的标准128bitUUID,也就不需要经过这个步骤,但是,如果遇到需要更改的时候,可以参考一下。更改了UUID位数,要注意的是主从通信时候,主机会根据从机的主服务UUID名和类型,来和从机通信的,这点要注意。我们先说从机的更改,主机的更改放在主从通信这块来讲解。
步骤1:在从机串口服务初始化函数里面,我们修改一下红色地方
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第1张图片
第一个地方,直接屏蔽掉,
第2的地方,我们要更改一下服务类型,为BLE_UUID_TYPE_BLE
第3,4,5,的地方,我们要更改一下主服务,RX,TX的UUID宏定义
在这里插入图片描述
第4,5函数里面更改的地方是一样的,贴出一个就行了
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第2张图片
最后,我们更改的地方是广播数组
在这里插入图片描述
更改完成以后,我们顺便把广播名更改了,因为此次例程是根据设备名来寻找从机设备的,主机寻找的设备名要和从机的一样。
在这里插入图片描述
更改好以后,下载进开发板里面,我们可以看到广播与以前 的不一样的地方。
以前的是:
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第3张图片
更改以后是;

NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第4张图片
到这里,就已经完成了,下面我们开始讲主从通信这块。主从通信例程这块,大家可以对照官网给的例程查看,路径为D:\nRF5_SDK_12.3.0_d7731ad\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay;我也是在这个例程上修改的。
1、修改宏定义,其实这个官网例程已经修改好了,也可以不必须修改。
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第5张图片
可以看图片上的宏定义,CENTRAL_LINK_COUNT是作为主机时候,可以连接多少设备,PERIPHERAL_LINK_COUNT是作为从机时候,可以连接多少设备。此处均设为1。也就是说,作为从机时候,连接一个主设备。作为主机时候,连接一个从机设备。
2、向下可以到协议栈初始化,协议栈初始化没什么改变,主要是他的回调函数里面,与之前不一样。我们看一下
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第6张图片
我们可以看出,作为从机时候,里面的派发函数与之前官网的一样,但是,我们是让他作为主机,这里我们不必过多查看,主要看作为主机时候的三个派发函数:
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(¢ral_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();

NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第7张图片
我用RTT打印了一下发现设备名的名称。看到函数,我们可以发现就是获取到设备名以后,通过对比我们设置的需要连接的设备名数组
static const char m_target_periph_name[] = “lvyapeng”;是否一样,
如果一样,就开始进行连接,如果不是,搜索下一个。如果连接成功,就会触发连接事件BLE_GAP_EVT_CONNECTED,还是在这个函数里面,我们可以看一下。
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第8张图片
首先判断结构体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)函数里面,我们要修改的地方在下面
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第9张图片
因为这里就是判断哪个服务是自己要进行通信的,之前我们修改了从机的类型和服务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和类型,这里也要修改,具体如下
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第10张图片
步骤和从机一样,把服务类型和uuID修改了
在这里插入图片描述
简单修改就行,这里主要注意他的回调函数。
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)
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第11张图片
两者进行数据交互的时候,首先是触发数据发现事件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
};

我在这里就不细说了,直接截屏网上的一段资料给大家
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第12张图片
6、发送函数,是定义一个软件定时,10ms触发一次回调函数
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第13张图片
这样就可以打开RTT,把主从程序下载进去,查看一下数据就行了,条件可以,也可以仿真一下,数据发送与接收的对不对,我的测试是没有问题的。
NRF51822学习笔记之主从通信讲解,另外附加把UUID更改成蓝牙技术联盟的基本UUID_第14张图片

你可能感兴趣的:(技术,初学)