jj1989 发表于 2022-2-9 09:03

【Silicon Labs BG22-EK4108A 蓝牙开发评测】四:NCP Mode 上位机开发

本帖最后由 jj1989 于 2022-2-9 09:04 编辑

<div class="parsedown-markdown">
<h1>【Silicon Labs BG22-EK4108A 蓝牙开发评测】四:NCP Mode 上位机开发</h1>

<h2>前言</h2>

<p>原本计划进行功耗测试,看到有网友已经做了相关测试,并且需要使用额外的板子才能使用 power 工具,遂作罢。</p>

<p>在之前的文章中提到, <a href="https://www.silabs.com/documents/public/quick-start-guides/qsg169-bluetooth-sdk-v3x-quick-start-guide.pdf" target="_blank">QSG169:《蓝牙 SDK v3.x 快速入门指南》</a>中关于蓝牙协议栈,介绍了三种工作模式。本人对其中的 NCP 模式比较感兴趣,这次就来研究一下。</p>

<h2>NCP Mode</h2>

<p>NCP 全称为:network Co-Processor(NCP) Mode,官方对其介绍如下:</p>

<blockquote>
<p>Network Co-Processor (NCP) mode, where the Bluetooth stack runs in an EFR32 and the application runs on a separate host MCU. For this use case, the Bluetooth stack can be configured into NCP mode where the API is exposed over a serial inter- face such as UART.</p>
</blockquote>

<p>其功能结构框图如下:</p>

<p></p>

<p>如上图,蓝牙 SOC 只负责协议栈相关的处理。我们的应用程序运行在单独的设备上,可以是其它 MCU 或者 PC 上位机。可以通过名为 BGAPI 的软件接口,使用 UART 硬件接口进行蓝牙协议栈的配置。</p>

<p>在第二篇文章<a href="https://bbs.eeworld.com.cn/thread-1192192-1-1.html" target="_blank">【Silicon Labs BG22-EK4108A 蓝牙开发评测】二:开发环境初体验</a> 中,我们简单体验了一下 NCP 模式,当时使用官方提供的图形化工具 -- <em>Bluetooth NCP Commander</em> 进行蓝牙协议栈的配置。</p>

<p>继续研究,发现官方提供了一个名为 <a href="https://pypi.org/project/pybgapi/" target="_blank">PyBGAPI</a> 的 python 库。对 PyBGAPI 的介绍如下:</p>

<blockquote>
<p>This package provides a Python interface for the BGAPI binary protocol. It reads the BGAPI definition file and dynamically generates a parser for it.</p>
</blockquote>

<p>这意味着我们可以通过 python 语言来很方便地进行蓝牙协议栈的配置。接下来就以我们<a href="https://bbs.eeworld.com.cn/thread-1192920-1-1.html" target="_blank">上一篇</a>中介绍的官方例程 Bluetooth-Soc Blinky 为参考,通过 python 控制运行于 NCP 模式下的 EFR32BG22 SOC 来实现 Blinky 例程功能。</p>

<h2>代码解析</h2>

<p>关于 PyBGAPI 库的使用,可以参考官方给出的<a href="https://github.com/SiliconLabs/pybgapi-examples" target="_blank">例程</a>。这里在 empty 例程的基础上添加代码,实现我们需要的功能。 修改蓝牙名字等这些简单操作就不一一介绍了,这里讲一下关于蓝牙服务的添加及控制数据的处理。</p>

<h3>GATT 配置</h3>

<p>首先是添加蓝牙 Blinky 服务,服务 UUID 可以在官方 Blinky 例程中找到。然后是添加 Button 和 LED 两个特征,特征 UUID 同样参考官方例程。注意这里的 Button 特征属性为 Read 和 Notify,LED 特征属性为 Write 和 Read。 在 <em>gattdb_init</em> 方法中增加如下代码:</p>

<pre>
<code class="language-python">   # Blinky service
      _, service = self.lib.bt.gattdb.add_service(
            session,
            self.lib.bt.gattdb.SERVICE_TYPE_PRIMARY_SERVICE,
            self.lib.bt.gattdb.SERVICE_PROPERTY_FLAGS_ADVERTISED_SERVICE,
            b"x24x12xb5xcbxd4x60x80x0cx15xc3x9bxa9xacx5ax8axde"
      )
      # Report button
      _, self.gattdb_report_button = self.lib.bt.gattdb.add_uuid128_characteristic(
            session,
            service,
            self.lib.bt.gattdb.CHARACTERISTIC_PROPERTIES_CHARACTERISTIC_READ |
            self.lib.bt.gattdb.CHARACTERISTIC_PROPERTIES_CHARACTERISTIC_NOTIFY,
            0,
            0,
            b"x9cxd2x70x2ax65x6dx53x9axd0x60xc3x41xa4x85xa8x61",
            self.lib.bt.gattdb.VALUE_TYPE_FIXED_LENGTH_VALUE,
            1,
            b"x00"
      )
      self.lib.bt.gattdb.start_service(session, service)

      # LED Contorl
      _, self.gattdb_led_control = self.lib.bt.gattdb.add_uuid128_characteristic(
            session,
            service,
            self.lib.bt.gattdb.CHARACTERISTIC_PROPERTIES_CHARACTERISTIC_READ |
            self.lib.bt.gattdb.CHARACTERISTIC_PROPERTIES_CHARACTERISTIC_WRITE,
            0,
            0,
            b"x7ax08x6ax73x6cxbexd8x46x97xc2x88x40x10x65x02x5b",
            self.lib.bt.gattdb.VALUE_TYPE_FIXED_LENGTH_VALUE,
            1,
            b"x00"
      )
      self.lib.bt.gattdb.start_service(session, service)
</code></pre>

<h3>用户控制响应</h3>

<p>这里仅介绍 LED 控制状态的处理。在 <em>event_handler</em> 方法中添加如下代码:</p>

<pre>
<code class="language-python">      elif evt == "bt_evt_gatt_server_attribute_value":
            if evt.att_opcode == self.lib.bt.gatt.ATT_OPCODE_WRITE_REQUEST:
                led_status_update(evt.value)</code></pre>

<p>当 LED 特征执行写入请求操作时,就会调用 <em>led_status_update</em> 方法,进行 LED 状态的更新操作。这里仅通过打印日志反应 LED 状态,代码如下:</p>

<pre>
<code class="language-python">def led_status_update(value):
    if value== b'x00':
      print("led off.")
    elif value == b'x01':
      print("led on.")
    else:
      print("Invalid value.")</code></pre>

<h2>演示</h2>

<p>原计划是基于 python 开发一个桌面端的图形上位机,结合 EFR Connect 进行更直观的功能演示。奈何 iOS 端的 EFR Connect 最近更新后似乎有 bug,在 Demo 页面搜索不到对应的设备,记得上一个版本是可以的。于是乎一切从简,就做一个简单的演示吧。</p>

<p><em>注:开发板需要提前烧录好 NCP 固件。</em></p>

<p></p>

<h2>总结</h2>

<p>EFR32BG22 的这个 NCP 模式给应用开发提供了更多的选择,同时可玩性也大大提高。比如我们可以将开发板作为一个蓝牙鼠标接收器。由于提供了 python 库,因此开发也变得很简单,可轻松实现跨平台。</p>
</div>

<p>&nbsp;</p>

Jacktang 发表于 2022-2-10 07:45

<p>关于CP 模式谢谢解析</p>
页: [1]
查看完整版本: 【Silicon Labs BG22-EK4108A 蓝牙开发评测】四:NCP Mode 上位机开发