干货|BLE入门谈:从空中数据收发理解BLE(下)

原创 电子工程世界 2021-08-10 07:30

▲ 更多精彩内容 请点击上方蓝字关注我们吧!


点此查看>>从空中数据收发理解BLE(上)在使用带BLE功能的MCU进行应用开发的时候,需要先熟悉BLE的API. 然而,各厂家的BLE API风格差异很大,要比不同器件平台硬件驱动库HAL之间的差别更大。底层无线电部分的硬件,各家自有独立的设计(硬件寄存器也不一定开放),况且BLE协议栈有很大一部分是软件实现,它不光涉及无线电部分,还需要定时器和中断管理、电源管理,甚至用到动态内存分配。于是要用BLE通信,协议栈部分几十上百kB的代码占用是很常见的(有的平台把API实现放到ROM里能省部分),但难处在于不容易预测它的软件行为,如一个API调用的执行时间、什么时候会用回调函数、什么时候需要切换低功耗模式等等。每当接触一个新的BLE MCU平台时,对BLE API的学习时间要远多于GPIO、UART这些基础硬件。如果对BLE技术缺乏认识,学习这些API更容易一头雾水。
  
BLE协议栈包含的内容太多了,一下弄明白太难。作为MCU应用开发,又不一定需要了解那么多,只要能实现需要的数据通信就够了。跟手机用BLE通信会麻烦一点,但如果是MCU和MCU之间通信呢?用过NRF24L01吗?它的空中数据包和BLE的数据包很相似,因为协议简单了,没有BLE的Profile, Service那些概念,对MCU工程师友好很多。
 
BLE应用如果只做一个beacon的话,就是只管定期发出数据,不需要建立连接的那种,其实是用不着协议栈的,甚至可能BLE API都不用到——这么说是不是一下子简单了?比如,我只需要定时广播一个温度信息,真没必要那么复杂啊。理解了BLE的数据包,就可以用不复杂的办法来做。
  
这还有一个条件,就是能直接访问MCU上的无线电部分硬件:得有一个开放的硬件环境,有手册。本帖将用nRF51822来演示怎么直接操作硬件进行数据包的收发。nRF51822是比较老的BLE MCU了,很容易从拆机的手环类电路板上找到,它后一代的nRF52xxx系列性能更好,无线部分硬件变化不大。除了nRF51xxx之外,看手里的板子能不能直接操作无线电部分硬件,就查参考手册看对应有没有详细的寄存器描述。刚结束的RSL10大赛用的板子也是可以玩的。


下面是nRF51xxx手册中RADIO部分的硬件结构框图:


接收和发送部分大致是独立的,但不能同时工作,就是半双工的意思。要发送的数据包存放在RAM中,硬件通过DMA自动读取,然后会加上地址、CRC、同步头等,并经过whitening步骤,然后用GFSK调制发送出去。接收过程是类似的,硬件通过包头检测、地址匹配、CRC校验过程筛选合法的数据包,由DMA写到RAM中指定的地址。
  
nRF51822支持的数据包格式是这样的:


这和BLE spec中基础数据包格式是兼容的(不然怎么支持BLE),所以我们将它配置成BLE的格式,就可以直接收发数据了。
  
Preamble部分是0/1交错的同步码,0xAA或者0x55,取决于地址部分的LSB(最先发送的那一bit),硬件负责。
  
地址部分,nRF51822的地址长度可以是3~5字节,分被BASE和PREFIX两部分。BLE的Access Address是4字节,因此设置BASE长度为3字节。
  
接下来的S0、LENGTH、S1字段是可选的(长度可以设成0),如果用了,则需要看成BLE数据包的PDU的一部分。和后面的PAYLOAD部分一起组成PDU.
  
最后CRC部分由硬件负责,需要设置为24-bit, 要按照BLE要求设置。
 
先试验能否从空中捕捉到BLE的数据包。需要提供给RADIO硬件的参数还有:(1)信道,(2)地址,(3)包长度。关于信道,为了捕捉advertising类型的包,可以设置成37、38、39信道当中的一个。设成其它信道捕捉连接数据包,除了要根据跳频算法不断更改信道外,还需要知道Access Address才可以。BLE 37、38、39信道使用固定的Access Address: 0x8E89BED6, 但建立连接后用的Access Address是主设备随机生成的,在CONNECT_REQ包中提供给从设备。包长度在BLE包PDU的第2个字节,也就是把上面的S0字段长度设置为1字节后,LENGTH字段就可以对应BLE PDU长度。nRF51822的RADIO使用LENGTH字段的信息(接收时来自空中数据,发送时来自RAM数据)来决定收发数据长度,不然就只能采用固定长度了。
  
为了接收37信道(中心频率2402MHz)的advertising类型数据包,用这样的配置:


  • NRF_RADIO->RXADDRESSES = 1; // enable address 0


  • NRF_RADIO->FREQUENCY = 2; // 2402MHz, CH37

  • NRF_RADIO->DATAWHITEIV = 37;


  • NRF_RADIO->MODE = (RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos);


  • NRF_RADIO->PREFIX0 = 0x8E;

  • NRF_RADIO->BASE0 = 0x89BED600;


  • // LFLEN=6 bits, S0LEN=1Byte, S1LEN=2bit

  • NRF_RADIO->PCNF0 = 0x00020106;

  • // STATLEN=6, MAXLEN=37, BALEN=3, ENDIAN=0 (little), WHITEEN=1

  • NRF_RADIO->PCNF1 = 0x02030025;


  • NRF_RADIO->CRCCNF = 0x103; // only PDU, 3 octets

  • NRF_RADIO->CRCINIT = 0x555555; // for advertising packet

  • NRF_RADIO->CRCPOLY = 0x100065b;


  • // set receive buffer

  • NRF_RADIO->PACKETPTR = (uint32_t)pkt_buf;

  

启动接收过程或发送过程要通过nRF51的task型寄存器。先看下RADIO部分的状态转移图:


在DISABLED状态通过TXEN或RXEN task启动硬件,到TXIDLE或RXDILE的准备状态,然后用START来进行一次传输。从接收切换到发送,以及从发送切换到接收,必须先转回DISABLED状态。
  
在接收状态下,硬件会监听指定地址的数据包,接收完成后转到RXIDLE状态,并产生END event.



当收到END event时,表示收到了一个数据包(地址匹配有效),然后可以访问CRCSTATUS寄存器判断CRC校验是否正确。若CRC有错,可能是数据包被干扰破坏,或者格式不正确。接收数据包的S0、LENGTH、S1、PAYLOAD字段存放到RAM中,稍有变化的是LENGTH和S1字段都被扩展成了字节存储。

  

我写了一个循环来持续接收数据包,进行37信道的监听。使用双缓冲区轮流存放收到的数据包,以便一边解析数据一边接收。


  • for(;;)

  • {

  • NRF_RADIO->PACKETPTR = (uint32_t)pkt_buf1;

  • NRF_RADIO->EVENTS_END = 0;

  • NRF_RADIO->TASKS_START = 1;

  • if(crcok2)

  • show_pkt(pkt_buf2);

  • else

  • uart_wstr(".");

  • if(NRF_RADIO->EVENTS_END)

  • uart_wstr("!");

  • while(! NRF_RADIO->EVENTS_END)

  • {}

  • crcok1=NRF_RADIO->CRCSTATUS;

  • NRF_RADIO->CRCINIT = 0x555555; // for advertising packet

  • NRF_RADIO->PACKETPTR = (uint32_t)pkt_buf2;

  • NRF_RADIO->EVENTS_END = 0;

  • NRF_RADIO->TASKS_START = 1;

  • if(crcok1)

  • show_pkt(pkt_buf1);

  • else

  • uart_wstr(".");

  • if(NRF_RADIO->EVENTS_END)

  • uart_wstr("!");

  • while(! NRF_RADIO->EVENTS_END)

  • {}

  • crcok2=NRF_RADIO->CRCSTATUS;

  •   }


 

通过对PDU第一个字节的低4位,可以判断数据包类型,然后识别余下数据。


  • static inline void show_pkt(volatile uint8_t *buf)

  • {

  • switch(buf[0]&0xF)

  • {

  • case 6: // ADV_SCAN_IND

  • uart_wstr("s");

  • add_log(buf);

  • break;

  • case 0: // ADV_IND

  • uart_wstr("A");

  • add_log(buf);

  • break;

  • case 2: // ADV_NONCONN_IND

  • uart_wstr("n");

  • add_log(buf);

  • break;

  • case 4: // SCAN_RESP

  • uart_wstr("R");

  • break;

  • case 1: // ADV_DIRECT_IND

  • uart_wstr("i");

  • break;

  • case 3: // SCAN_REQ

  • uart_wstr("+");

  • break;

  • case 5: // CONN_REQ

  • uart_wstr("C");

  • break;

  • default:

  • uart_wstr("?");

  • break;

  • }

  • }

  

如果是包含advertising数据的包,可以将地址、数据记录下来,待收集一段时间后进行统计。


  • void add_log(uint8_t *buf)

  • {

  • int i;

  • for(i=0;i<32;i++)

  • {

  • if(adv_log.count) // not blank

  • {

  • if(memcmp(adv_log.addr, buf+3, 6)==0 && adv_log.type==buf[0]) // match

  • {

  • adv_log.count++;

  • return;

  • }

  • }

  • else // add entry

  • {

  • memcpy(adv_log.addr, buf+3, 6);

  • adv_log.type = buf[0];

  • adv_log.len = buf[1]-6;

  • memcpy(adv_log.payload, buf+9, adv_log.len);

  • adv_log.count=1;

  • return;

  • }

  • }

  • }


 

这样就可以发现周围的一部分BLE设备了。现在我的程序只是接收,没有主动发起“扫描”。但是我的程序收到了许多主动扫描的包,表明附近有设备在持续进行疯狂扫描……


以上演示的是单向接收。单向发送也是容易实现的,只要填充一个advertising包,把要发送的数据包含在内,用TX模式发送出去就是了。发送的设置和接收基本一样。

  • void radio_adv_tx(uint8_t *pdu, uint8_t len)

  • {

  • uint8_t txpkt[40];


  • NRF_RADIO->EVENTS_READY = 0;

  • NRF_RADIO->TASKS_TXEN = 1;

  • while (NRF_RADIO->EVENTS_READY == 0);

  • // now in TXIDLE state


  • txpkt[0]=0x42; // private TX address, non-connectable

  • if(len>31)

  • len=31;

  • txpkt[1]=len+6;

  • txpkt[2]=0;

  • txpkt[3]=0x37; txpkt[4]=0x5A; txpkt[5]=0x29;

  • txpkt[6]=0xC6; txpkt[7]=0x8B; txpkt[8]=0x04;

  • memcpy(txpkt+9, pdu, len);

  • NRF_RADIO->PACKETPTR = (uint32_t)txpkt;

  • NRF_RADIO->EVENTS_END = 0;

  • NRF_RADIO->TASKS_START = 1;

  • while(! NRF_RADIO->EVENTS_END)

  • {}

  • }


  
使用一个包含名称的advertising数据,调用上面的函数。设备地址是04:8B:C6:29:5A:37, 写在发送函数中了。

  • const uint8_t dummy_adv[]={0x02,0x01,0x06, // flags

  • 15,0x09,'A','D','V','_','D','e','m','o',' ','5','1','8','2','2'};

  • radio_adv_tx(dummy_adv,sizeof(dummy_adv));

  
定期(比如1秒)发送一次,在手机上用BLE扫描工具可以发现这个设备。当然现在仅仅广播了一个名称而已,要添加自定的传感器数据也很简单,不过要注意31个字节长度的限制。


以上只是最初级的直接操作硬件进行BLE数据包收发的演示,只用了单向数据,因此简单了。如果要两个设备有应答地交互,就需要发送方在数据包发送之后切换到接收状态,等待一小段时间看是否有应答。BLE的连接建立起来后,主从双方的收发方向就是在不断地切换,如果要自己编程操作硬件实现这些,而不使用协议栈的API, 理论上是可以做的,问题在于有没有必要了。
  
利用BLE MCU的无线电硬件部分,做一些调试工具是可行而且有用的。还可以做自己的私有协议通讯,那样就不能再叫做BLE了。
 

推荐阅读

干货|BLE入门谈:从空中数据收发理解BLE(上)

干货 | 示波器探头各种作用及工作原理,你都理解清楚了吗?

干货 | 元器件热设计:热阻是什么?散热路径图解

众号内回复您想搜索的任意内容,如问题关键字、技术名词、bug代码等,就能轻松获得与之相关的专业技术内容反馈。快去试试吧!


由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。


或将我们的公众号设为星标。进入公众号主页后点击右上角「三个小点」,点击「设为星标」,我们公众号名称旁边就会出现一个黄色的五角星(Android 和 iOS 用户操作相同)。


聚焦行业热点, 了解最新前沿
敬请关注EEWorld电子头条
http://www.eeworld.com.cn/mp/wap
复制此链接至浏览器或长按下方二维码浏览
以下微信公众号均属于
 EEWorld(www.eeworld.com.cn)
欢迎长按二维码关注!
EEWorld订阅号:电子工程世界
EEWorld服务号:电子工程世界福利社
电子工程世界 关注EEWORLD电子工程世界,即时参与讨论电子工程世界最火话题,抢先知晓电子工程业界资讯。
评论
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 60浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 108浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 56浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 84浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 66浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 69浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 62浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 59浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 82浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 43浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 59浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦