BLE5.3 使用1M 2M 500K或者 125Kbps通讯
蓝牙5特性二 【4X 远距离】
在4.2及以前的版本中蓝牙低功耗在信道传输中未使用纠错编码技术,标准规定的基准灵敏度为-70dBm(基本上每一家蓝牙芯片厂商都可以做到-90dBm)。
蓝牙5引入了卷积前向纠错编码(Convolutional Forward Error Correction Coding) 技术,提高了接收机的抗干扰能力,将接收机的参考灵敏度分别提高到-75dBm (S=2编码)和-82dBm (S=4编码), 同时提高了接收机的载干比(载干比:C/I=载波信号强度/干扰信号强度)性能。使得在保持TX相同功耗情况下,蓝牙的距离提升了4倍,下面来说说如何做到提高接收灵敏度,依靠的就是编码PHY。
BLE编码PHY
蓝牙5除硬件支持1M,2M PHY,还支持两种编码方式的PHY,这两种编码方式的PHY是基于1M PHY的基础,使用1M PHY的物理通道。新的编码分为两种,一种编码PHY为500kbps(S=2),另外一种编码PHY是125kbps(S=8)。
编码PHY的数据包类型和1M PHY/2M PHY 数据包类型略有不同,增加了CI(coding indicator)和TERM1和TERM2。CI和TERMx构成了FEC(Forward Error Correction)区块,利用FEC恢复在传输过程中的错误数据位,以提升接收灵敏度。经过S=2或者S=8的编码,接收灵敏度可以提升4-6dBm,距离相应提升2-4倍。
但是进化出一种新的能力必然会牺牲自己一项能力,和1M PHY相比,传输的距离提升了,但传输相同数据包,编码PHY的功耗比1M PHY就要高出一节 (BLE 规定的包长一致,部分payload变为FEC data,实际有效的传输数据减少)。数据流传递方式:
1M/2M PHY
在没有编码方式下,TX数据包数据bit流通过加密(可选项),CRC效验,白化之后发送出去;RX端接收到数据流解调后校验CRC,解密,得到原始数据包数据。
500kbps,125kbps 编码PHY
相对 1M/2M 未编码PHY的数据流,500k PHY, 125K phy多出两个部分:FEC(前向错误纠错) 编码和模式映射,大家肯定要问如何实现FEC,我们以编码PHY的流程来完整讲述一下数据流的编码和传输过程。错误检验 — CRC效验错误
接收机首先会检测接收到的Access Adrees是否正确,如果Access Adrees错误,丢弃该数据包,检测完Access Adrees,接收机会去效验整个数据包,判断24位CRC是否完全吻合。
白化
数据白化的目的是在传输数据遇到连续000000,或者连续111111序列时,进行合理编码,减少传输长串重复序列数据。
编码 — 前向错误编码
前向错误编码算法使得接收机有能比恢复该数据包中的传输错误数据位,通过把原始数据进行编码得到新的数据流,即使新的数据流在传输过程中有个别位数据错误,FEC解码也能恢复原始数据,从而提高了传输的误码率。
G0(a0)先进行传输,G1(a1)在G0传输完成之后传输。
模式映射 — Pattern Mapper
模式映射的目的是整理输出前向错误编码数据。
输出的方式分为两种模式(P symbols):一种P=1(S=2),一种P=4(S=8)。
两种模式下把前向错误编码数据进行加工,然后输出。
由下面的表格所示:
当P=1时,输出的data和输入保持不变,1位输入,1为输出;
当P=4时,编码为4位再输出。
所以可以看到P=4(S=8)时,输出的data数据量会更多,更进一部压缩实际可以传输的有效payload数据。
125kbps使用S=8模式,传输距离相对传统BLE提升4倍,相应牺牲的数据传输率最多。
500kbps使用S=2模式,传输距离相对传统BLE提升2倍。
长距离模式可以有效可以支持到400-500米范围内BLE通讯,
uint8 adv_type; adv_type = GAP_ADTYPE_EXT_CONN_UNDIRECT; // GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData_ext ), advertData_ext ); //设置扩展广播 GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE,sizeof(uint8_t),&adv_type); GAP_SetParamValue(TGAP_ADV_SECONDARY_PHY,GAP_PHY_VAL_LE_CODED); //125K GAP_SetParamValue(TGAP_ADV_PRIMARY_PHY, GAP_PHY_VAL_LE_CODED);//125K
链接以后协商PHY
case GAPROLE_CONNECTED: if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT) { Peripheral_LinkEstablished(pEvent); PRINT("Connected..\n"); tmos_start_task(Peripheral_TaskID, SBP_PHY_UPDATE_EVT, SBP_READ_RSSI_EVT_PERIOD); //启动协商PHY } break;
执行协商任务
if(events & SBP_PHY_UPDATE_EVT) { // start phy update PRINT("PHY Update %x...\n", GAPRole_UpdatePHY(peripheralConnList.connHandle, 0, GAP_PHY_BIT_LE_CODED, GAP_PHY_BIT_LE_CODED, 0)); return (events ^ SBP_PHY_UPDATE_EVT); }
协商完成
static void Peripheral_ProcessGAPMsg(gapRoleEvent_t *pEvent) { switch(pEvent->gap.opcode) { case GAP_SCAN_REQUEST_EVENT: { PRINT("Receive scan req from %x %x %x %x %x %x ..\n", pEvent->scanReqEvt.scannerAddr[0], pEvent->scanReqEvt.scannerAddr[1], pEvent->scanReqEvt.scannerAddr[2], pEvent->scanReqEvt.scannerAddr[3], pEvent->scanReqEvt.scannerAddr[4], pEvent->scanReqEvt.scannerAddr[5]); break; } case GAP_PHY_UPDATE_EVENT: { PRINT("Phy update Rx:%x Tx:%x ..\n", pEvent->linkPhyUpdate.connRxPHYS, pEvent->linkPhyUpdate.connTxPHYS); break; } default: break; } }
实测执行结果
不通速率下,接收灵敏度