250|2

49

帖子

0

TA的资源

一粒金砂(中级)

SparkFun Pro nRF52840 Mini 蓝牙广播 + 软件收发数据 [复制链接]

本帖最后由 御坂10032号 于 2024-6-10 01:38 编辑

在这篇帖子中,我将详细讲解一个基于nRF52芯片的蓝牙低功耗(BLE)UART示例程序。该程序使用Adafruit的Bluefruit库来实现BLE功能,并包括了几个关键的BLE服务。我们将逐步解析代码,了解其每个部分的功能。此外,我们还将简要介绍蓝牙协议的基本概念。

蓝牙概述

蓝牙是一种短距离无线通信技术,广泛应用于各种设备之间的数据传输。蓝牙标准由蓝牙技术联盟(Bluetooth Special Interest Group,SIG)制定和维护。蓝牙技术主要有两种模式:

  1. 经典蓝牙(BR/EDR):适用于高数据传输速率和音频传输的应用,如无线耳机和音箱。
  2. 蓝牙低功耗(BLE):针对低功耗和间歇性数据传输的应用,如智能手表、健康监测设备和IoT设备。

蓝牙低功耗(BLE)

BLE是蓝牙4.0引入的技术,专门设计用于低功耗应用。其特点包括:

  • 低功耗:适用于电池供电设备。
  • 快速连接:可以快速建立和断开连接,节省能量。
  • 灵活的数据传输:支持小数据包的高效传输。

BLE设备主要分为两类:

  • 外围设备(Peripheral):广播其存在,并等待中心设备连接。
  • 中心设备(Central):扫描外围设备并发起连接。

 

蓝牙协议稍微复杂,不过好在Sparkfun 提供的Arduino支持中包括了对蓝牙的支持。同时还有大量的蓝牙demo供我们学习。这些Arduino蓝牙的适配大大的降低了使用这一块MCU开发项目时的困难程度。

 

我们可以在下述位置找到示例代码

 

image.png  

#include <bluefruit.h>

我们首先引入了Bluefruit库,它提供了对蓝牙功能的支持,使我们能够轻松地构建BLE应用。

 

// BLE Service
BLEDfu  bledfu;  // OTA DFU service
BLEDis  bledis;  // device information
BLEUart bleuart; // uart over ble
BLEBas  blebas;  // battery

 

之后,我们初始化了几个BLE服务对象,包括(OTA的服务暂时还没发现怎么用):

  • BLEDfu:支持空中下载(OTA)的DFU服务。
  • BLEDis:设备信息服务。
  • BLEUart:通过BLE实现的UART服务。
  • BLEBas:电池服务,用于监控电池状态。

 

void startAdv(void)
{
  // 设置广播数据包
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();

  // Include bleuart 128-bit uuid 设置蓝牙广播的唯一标识
  Bluefruit.Advertising.addService(bleuart);

  // Secondary Scan Response packet (optional)
  Bluefruit.ScanResponse.addName();
  
  /* Start Advertising 开始广播
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}

 

startAdv函数负责设置并启动蓝牙广播:

  1. 设置广告包

    • 添加标志信息,指示设备为普通可连接模式。
    • 添加发射功率信息。
    • 添加BLE UART服务的UUID。
  2. 设置扫描响应包

    • 添加设备名称,这样在扫描响应时可以显示设备名称。
  3. 启动广告

    • 配置在断开连接时自动重新开始广播。
    • 设置广播间隔和超时时间。
    • 开始广播,参数为0表示广播将持续进行直到设备连接 (如果持续没有设备连接的话,开发板上的LED灯将持续闪烁)。

 

void connect_callback(uint16_t conn_handle)
{
  // 获取当前连接的引用
  BLEConnection* connection = Bluefruit.Connection(conn_handle);

  char central_name[32] = { 0 };
  connection->getPeerName(central_name, sizeof(central_name));

  Serial.print("Connected to ");
  Serial.println(central_name);
}

/**
 * 连接断开时调用的回调函数
 * @param conn_handle 连接句柄
 * @param reason 断开原因
 */
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  Serial.println();
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

 

这些回调函数在设备连接和断开连接时被调用:

  1. 连接回调函数

    • 当设备连接时,获取并打印中央设备的名称。
  2. 断开连接回调函数

    • 当设备断开连接时,打印断开原因。

 

 

void loop()
{
  // Forward data from HW Serial to BLEUART
  while (Serial.available())
  {
    // 延迟以等待足够的输入,因为我们有一个有限的传输缓冲区
    delay(2);

    uint8_t buf[64];
    int count = Serial.readBytes(buf, sizeof(buf));
    bleuart.write(buf, count);
  }

  // 从BLEUART转发到HW Serial
  while (bleuart.available())
  {
    uint8_t ch;
    ch = (uint8_t) bleuart.read();
    Serial.write(ch);
  }
}

 

loop函数实现了串口和BLE UART之间的数据转发:

  1. 从硬件串口转发数据到BLE UART

    • 如果串口有数据可读,读取数据到缓冲区,并通过BLE UART发送出去。
  2. 从BLE UART转发数据到硬件串口

    • 如果BLE UART有数据可读,读取一个字节并通过串口发送出去。

 

上述程序实现的基本功能是初始化串口,和蓝牙。并且开启蓝牙的广播功能。 当用户连接或者断开于当前蓝牙的连接的时候会触发上述的回调函数。当用户使用APP发送消息给Sparkfun开发板的时候。开发板将会以串口的方式发送给上位机。同时上位机也可以通过串口的方式通过蓝牙发送消息给APP(用户) 

 

此时我们我们将代码编译并且下载到开发板中

 

设备未连接蓝牙的时候

cff9e3839450b2e9e8d9254eb0b07656

 

完整使用手机APP 发送和接收数据演示

 

6月10日

 

此帖出自RF/无线论坛

最新回复

这个写的真好,使我对蓝牙有了更好的认识,感谢博主,博主一切顺利   详情 回复 发表于 2024-6-11 10:47

回复
举报

49

帖子

0

TA的资源

一粒金砂(中级)

苹果用户我建议大家使用BleTools 我视频上的那个广告太多了。 BleTools 没有广告
此帖出自RF/无线论坛

回复

22

帖子

0

TA的资源

一粒金砂(中级)

这个写的真好,使我对蓝牙有了更好的认识,感谢博主,博主一切顺利

此帖出自RF/无线论坛

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

推荐帖子
DS12C887调试心得

沉寂了好多天,没闲着,做了点儿项目相关的事儿,调了一个很常用的片子——DS12C887(一个实时时钟芯片),是达拉斯公司生产的。 ...

我的第一个电子制作--万年历

这个作品是参加学校的电子设计大赛的参赛作品,电路是我抄来焊接,程序也是我参与移植的,报告不是我写的,是另外一个队友。 现 ...

【DIY新作】LED点阵时钟.3种字体.4种动画.自动旋屏.GPS校时【附原理图】

半年来一直在DIY辉光管、荧光管的时钟,其实算来,我最早DIY的时钟是LED点阵的。 时隔3年,再次汇集这段时间以来的想法,重新DI ...

LPC1114--音乐频谱

本帖最后由 季夏木槿 于 2014-7-28 23:37 编辑 http://v.youku.com/v_show/id_XNjMyMjMwMDg0.html 参考资料: 1334301334 ...

一个比较奇怪的运放, 大佬看下

有点看不懂这个运放,有几处不太明白,请大佬指点: 1.负反馈看不太懂,增益怎么算 2.反向输入的两个电容串联起什么作用 3.同 ...

开发在线编译esp32的mpy固件平台

我要做一个在线编译esp32固件的平台, 把常用的库搞成多选框 想要啥功能就选择一下 也可以上传自己的py文件打包到固件 编译 ...

【求助】在 锂电池 的 电源模块 设计中,为什么说 锂电池的每1V电压都是很宝贵 的??

在设计锂电池的电源模块的反接电路时,常常不使用二极管方案,是因为二极管导通会造成0.7V压降,而往往采用NMOS方案。 为什么 ...

模拟电路供电质量

各位, 请问你们工作中常规运放、DAC等模拟电路里的电源质量最好能到什么指标。最简单的就常规DCDC+LDO供电模式下,你们的电源 ...

关于Mos管最基本的一个参数选型

就是用在全桥LLC上面的Mos管,我的测试出来的瞬态电压应力假如480V,我需要预留0.75的裕量的话,就是640V,那么在选择Mos管类型 ...

求一个自举电路工作原理。

为什么全桥驱动需要自举电路,自举电路工作原理是什么。目前一知半解,求一个详细解释,越详细越好。

快速回复 返回顶部 返回列表