pc-ble-driver 搭建环境

本文基于pc-ble-driver v4.1.1,介绍如何在Windows上搭建开发环境。

以前写过一个入门教程(链接),最近的版本更新改动很大,那篇文章中介绍的方法已经过时。我仍然建议预先读它,然后再看本文。

pc-ble-driver是什么

它是一个PC端的BLE开发平台。

我们在开发板中烧录一个中间层固件,通过PC给固件发指令,与外部BLE设备(比如手机或一个BLE从设备)进行通信。

PC端可以用C/C++、Python、Javascript 语言进行编程。本文介绍的方案是基于C语言。

pc-ble-driver 部署在github中,可以从该页面获得它的全部信息。

生成静态库文件

首先要安装Visual Studio 2019,它有多个开发语言,我们这里只需要C++。

安装好以后,我们能够打开VS的项目文件(.sln)和工程文件(.vcxproj),同时也得到了一个编译工具MSBuild.exe,它的路径应该在:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe

然后安装cmake工具。

下载pc-ble-driver的源文件:https://github.com/NordicSemiconductor/pc-ble-driver/releases

页面中有多个选项:

  • nrf-ble-driver-4.1.1-win_x86_32.zip
  • nrf-ble-driver-4.1.1-win_x86_64.zip
  • Source code (zip)
  • Source code (tar.gz)

需要下载Source Code (zip)那一项。

将源文件解压到一个开发目录下,我这里是:C:\repo\pc-ble-driver-repos\pbd

开始之前需要明确我们要干什么!

pc-ble-driver 在PC端实现了一个库,这个库可以调用softdevice,实现BLE的功能。我们写的代码直接调用这个库文件暴露的接口。

在上面的下载页面,下载nrf-ble-driver-4.1.1-win_x86_64.zip文件,里面就包含了这个库,理想情况是我们能够拿它直接使用,但奇怪的是我这里使用它的库会报错。无奈只能自己生成一个库来用。

所以我们的目标是,编译源文件,生成一个静态库文件(.lib)。

下载必要的第三方VC库:

  • asio
  • catch2 (只有一个catch.hpp文件)
  • spdlog

将它们放在目录:C:\repo\pc-ble-driver-repos\pbd\ext

注意,官方页面上使用vcpkg来下载它们,还要设置一堆环境变量,把问题复杂化,这里我们直接下需要的库,不管vcpkg。

在pbd下面创建一个build文件夹: C:\repo\pc-ble-driver-repos\pbd\build。打开cmd窗口,cd到该文件夹,然后执行:

cmake -DASIO_INCLUDE_DIR=C:\repo\pc-ble-driver-repos\source\ext\asio-1.12.2\include -DCatch2_DIR=C:\repo\pc-ble-driver-repos\source\ext\catch-2.10.0 -DCONNECTIVITY_VERSION=4.1.1 -DNRF_BLE_DRIVER_VERSION=6.1.1 -G "Visual Studio 16 2019" -A Win32 ..

值得看一下各个参数:

  • -DXXX表示增加一个变量,也可以通过设置环境变量的方式进行(有坑,不推荐)
  • CONNECTIVITY_VERSION和NRF_BLE_DRIVER_VERISON 按实际版本进行配置,因为可能过几天又有新版本了
  • -G “Visual Studio 16 2019″,这个跟官方页面上的-G Ninja不同,我发现用Ninja有坑
  • -A Win32表示生成Win32的库,可选项还包括:x64, ARM, ARM64。(链接)如果这里使用了Win32,后面创建VS工程时候,也得使用Win32。

命令执行完毕,会在build下生成大量文件,我们关心的是:项目文件(nrf-ble-driver.sln) 和好几个工程文件(*.vcxproj)。

这时候可以双击打开sln项目文件,或者用命令:

"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" nrf-ble-driver.sln

编译完毕,在pbd\build\Debug目录下就能看到多个lib文件,找到:nrf-ble-driver-sd_api_v6-mt-static-gd-6_1_1.lib,它就是我们生成的静态库文件,后面我们利用它来编写代码。

搭建开发环境

在C:\repo\pc-ble-driver-repos目录下新建几个目录:

  • include
  • lib
  • project\hrs和project\hrs_c
  • hex

将pbd\include文件夹下的东西复制到这个include中。其实只复制common和sd_api_v6两个文件夹即可。

将刚才生成的 nrf-ble-driver-sd_api_v6-mt-static-gd-6_1_1.lib 复制到lib中。

将pbd\hex\sd_api_v6下的connectivity_4.1.1_1m_with_s132_6.1.1.hex和connectivity_4.1.1_1m_with_s140_6.1.1.hex复制到hex中,二者分别用于nRF52832和nRF52840芯片。

project\hrs用于放HRS示例工程,project\hrs_c用于放HRS_C示例工程。将 pbd\examples\heart_rate_monitor\main.c 复制到hrs目录下,将 pbd\examples\heart_rate_collector\main.c 复制到hrs_c目录下。

下面介绍如何制作一个HRS工程。

在Visual Studio 2019中,新建一个空白工程,执行以下操作:

先添加main.c到工程。

在工程设置C/C++ -> Additional Include Directories中,添加

  • C:\repo\pc-ble-driver-repos\include\sd_api_v6
  • C:\repo\pc-ble-driver-repos\include\common
  • C:\repo\pc-ble-driver-repos\include\common\config
  • C:\repo\pc-ble-driver-repos\include\common\internal
  • C:\repo\pc-ble-driver-repos\include\common\internal\transport
  • C:\repo\pc-ble-driver-repos\include\common\sdk_compat

C/C++ -> Compile AS设置为Compile As C Code。

C/C++ -> Precompiled Header File设置为Not Using Precompiled Headers

C/C++ -> Process Definitions添加:

  • WIN32
  • _WINDOWS
  • NRF_SD_BLE_API=6
  • _WIN32_WINNT=0x0502
  • NOMINMAX
  • ASIO_STANDALONE
  • SD_RPC_EXPORTS
  • HCI_LINK_CONTROL
  • _CRT_SECURE_NO_WARNINGS
  • PC_BLE_DRIVER_STATIC
  • CMAKE_INTDIR=”Debug”
  • _DEBUG
  • _CONSOLE

Linker -> Additional Dependencies添加:C:\repo\pc-ble-driver-repos\lib\nrf-ble-driver-sd_api_v6-mt-static-gd-6_1_1.lib

Linker -> Generate Debug Info改成:Debug Information optimized for faster links (/DEBUG:FASTLINK)

保存好后打开main.c,按F7编译一下,如果不报错就说明一切完好,可以连上开发板测试了。

hrs_c工程设置过程与之一模一样。

可以从这里下载我配置好的工程作为参考:https://gitee.com/isyq/pc-ble-driver-demo

测试HRS工程

准备一个52开发板,连上电脑。擦除并烧录C:\repo\pc-ble-driver-repos\hex\connectivity_4.1.1_1m_with_s132_6.1.1.hex

查看开发板的串口号,比如是COM58,那么在main.c中,找到DEFAULT_UART_PORT_NAME定义,将其修改为COM58。

然后在VS中按F5进行调试,就会打开有一个cmd窗口,通过打印的内容可以看到它正在广播,如下:

这时候用手机与它连接,发现可以连接但是无法正常发现服务。这是因为这个main.c没有处理Data Length Update事件,导致超时断开。

解决办法是,找到ble_evt_dispatch()函数,增加处理该事件,代码如下:

case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
{
    ble_gap_data_length_params_t dl_params;

    memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t));
    err_code = sd_ble_gap_data_length_update(adapter, p_ble_evt->evt.gap_evt.conn_handle,
        &dl_params, NULL);
    if (err_code != NRF_SUCCESS)
    {
        printf("Data len update error: %x\n", err_code);
        fflush(stdout);
    }
} break;

然后手机就可以跟它进行连接和通信了。

值得注意的是,pc-ble-driver与nRF5 SDK 同根同源,这个版本直接使用SDK 15.3的softdevice,但是二者的编程模型不同,SDK 中使用了大量的XXX_DEF 和XXX_OBSERVER 的编程模型,许多BLE库也都是基于这个实现的,在pc-ble-driver中则完全无法使用,所有的扫描、连接、发现操作都得用最原始的API去实现,给使用带来了不少难度。

另外,pc-ble-driver 与PC 之间使用串口进行通信,尽管采用了1M的比特率,但是仍然不同于单芯片方案,有诸多限制。pc-ble-driver 不支持data length extension, data length只能使用27, 意味着它的通信速度跑不起来。

(完)