一、简介
CRSF(Crossfire Radio System Protocol)协议,是一种用于遥控器和飞控之间低延迟、双向通信的协议,目前大量应用于FPV无人机等遥控飞行器中。
二、特点
- 低延迟、高速数据传输:波特率高达420000bps,能确保遥控器和飞控之间的低延迟通信,使操作者的指令能快速准确地传达到飞行器,实现更精准的操控。
- 多通道数据传输:支持16个通道数据传输,每个通道的数据被压缩成11位,可满足飞行器对多个控制通道的需求。
- 双向通信功能:①将遥控器的控制信号传输到飞控;②将飞行控制器的状态数据,如GPS数据、链路状态、电池电量等传输到遥控器。
- 高可靠性:采用CRC-8校验算法,校验多项式为 0xD5,校验值附加在数据包的最后,确保数据在传输过程中没有被损坏,增强了数据传输的可靠性和准确性。
三、系统分析
CRSF支持基于通用异步收发传输器(UART)和集成电路总线(I2C)的连接方式,以供端点之间进行通信。从实际应用来看,普遍基于UART实现。
遥控系统硬件组成可区分发射机与接收机,对基于UART的CRSF设备而言,发射机支持全双工和半双工两种模式,接收机支持全双工模式。
(一)全双工
全双工的CRSF使用两根线,即接收线(RX)和发送线(TX),其中空闲时为高电平,高电平便是“1”,没有流控制。全双工模式主要应用于接收机-飞控之间的通信。
(二)半双工
半双工的CRSF是通过单根线来双向传输数据的,其中空闲时为低电平,低电平表示1,没有流控制。半双工模式主要应用于遥控器-发射机之间的通信。
(三)UART 波特率
标准的接收机波特率据报道为416666波特。
对于CRSF v2版本,Betaflight、iNav、ExpressLRS使用420000波特。
对于CRSF v3版本,采用一种接收机波特率协商机制。基于EdgeTX的发射机、ELRS支持115.2K、400K、921.6K、1.87M、2.25M、3.75M、5.25M波特。波特率在遥控器端进行设置,模块会自动切换以适配遥控器的速率。在任意1秒时间段内,如果未通过CRC校验的数据包数量超过通过校验的数据包数量,就会执行自动波特率检测功能。发射机基于STM32时,将循环遍历各个波特率,每个波特率尝试1秒,如果检测失败就尝试下一个波特率;基于ESP32时,可使用硬件自动波特率寄存器预估输入波特率,并且应当使用上述列表中与之最接近的标准波特率(而不是直接测量得到的值)。ELRS的ESP32发射机还会尝试自动检测信号在半双工和全双工模式下是否是反相的。
三、通信流程分析
(一)遥控器与TX通信
首先,摇杆、按钮等通道数据被量化为数字信号;其次,按照CRSF协议组帧;最后,通过遥控器CRSF接口将数据发送给高频头。高频头协议不受限制,目前以CRSF和ELRS为主。
(二)TX与RX通信
实现遥控时,TX按照CRSF协议组帧后的数据将在调制后发射出去;RX时刻处于监听状态,一旦接收到信号,就会按照CRSF协议对收到信号进行解析解译,之后指令将送往飞控。
实现参数配置交互时,TX发起参数查询请求,RX以分块方式反馈参数信息(详见参数配置交互)。
(三)参数配置交互 {#para-config}
1. 设备发现阶段
- 主机发送探测请求:主机首先发送
CRSF_FRAMETYPE_DEVICE_PING
类型的数据包,以发现与之相连的设备,并且确定这些设备上可供配置的值的数量情况。 - 设备响应:所有与这个
PING
请求的“扩展目的”字段相匹配的设备,都会用它们的CRSF_FRAMETYPE_DEVICE_INFO
数据包来进行回应。
2. 参数查询阶段
对于每一个参数索引:
- 主机发送
CRSF_FRAMETYPE_PARAMETER_READ
(块为 0)的数据包来查询相应的参数。 - 设备在接收到参数查询请求后,会用
CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY
块来进行回应。 - 如果
SETTINGS_ENTRY
指示还有非零的块剩余,主机可能需要请求额外的分块来获取完整的参数信息。
3. 参数设置阶段
若要设置某个参数值,主机需发送带有更新后数值的CRSF_FRAMETYPE_PARAMETER_WRITE
指令。
4. 针对ExpressLRS的额外操作
- 对于ELRS,主机应当重新查询所有同级参数,以确定参数的更改是否影响了其他同级参数的数值或可选值。
四、协议解析
(一)通用数据包格式
总体结构:所有数据包都遵循CRSF格式,整个数据包最大总尺寸为64字节,其结构为:
[sync] [len] [type] [payload] [crc8]
sync
:同步字节,对于所有串行的CRSF数据包,通常是以0xC8
开始。不过,EdgeTX向外发送的通道/遥测数据包是个例外,它们以0xEE
开头。出于兼容性考虑,新的代码应该同时支持这两种同步字节情况,但所有向外传输的数据包按要求必须以0xC8
开头。另外,I2C CRSF数据包则是以CRSF地址开始的。len
:长度字段,表示后续字节(包括type
、payload
和crc8
)的长度,即有效载荷长度(PayloadLength)再加 2。整个数据包的长度计算方式为有效载荷长度加4(即包含sync
、len
、type
、crc
几个部分)。TYPE
:类型字段,由CRSF_FRAMETYPE
定义,详见数据包类型部分。PAYLOAD
:有效载荷,最大长度为60字节,不同类型的数据包其有效载荷内容不同。在遥控通道数据帧中,数据部分存储了16个通道的值,每个通道用11位表示,这些11位数据被紧密打包到22字节中进行传输,通道值范围通常为1000到2000,对应于舵机的标准PWM脉宽。在GPS数据包中,包含纬度、经度、地速、航向、高度等数据,纬度和经度各占4字节,地速和航向各占2字节,高度占2字节。CRC
:循环冗余校验字节,多项式为0xD5,该校验涵盖从type(也就是缓冲区中的第2个字节)到payload末尾的所有字节,用于检测数据包在传输过程中是否出现错误,保证数据完整性。
(二)扩展数据包格式
为支持通过CRSF协议将数据包 “隧道” 传输到远程端点,引入扩展数据包格式。此时,增加扩展的目的地址(ext dest)和源地址(ext src)作为有效载荷的一部分。所有CRSF_FRAMETYPE
值为0x28
及更高的数据包类型都会使用扩展数据包格式。扩展数据包总体结构为[sync] [len] [type] [[ext dest] [ext src] [payload]] [crc8]
。
在扩展数据包格式下,因前面两个字节是扩展的目的地址和源地址,LEN
字段实际上对应的是有效载荷长度(PayloadLength)再加 4。相应地,扩展数据包的最大有效载荷长度就变为了58字节。
(三)地址定义
Address | Enum | Description |
---|---|---|
0x00 | CRSF_ADDRESS_BROADCAST | 广播 |
0x10 | CRSF_ADDRESS_USB | USB |
0x12 | CRSF_ADDRESS_BLUETOOTH | 蓝牙 |
0x80 | CRSF_ADDRESS_TBS_CORE_PNP_PRO | TBS Core PNP Pro |
0x8A | CRSF_ADDRESS_RESERVED1 | 保留 |
0xC0 | CRSF_ADDRESS_CURRENT_SENSOR | 外部电流模块 |
0xC2 | CRSF_ADDRESS_GPS | 外置GPS |
0xC4 | CRSF_ADDRESS_TBS_BLACKBOX | 外部黑匣子记录设备 |
0xC8 | CRSF_ADDRESS_FLIGHT_CONTROLLER | 飞控(Betaflight/iNav) |
0xCA | CRSF_ADDRESS_RESERVED2 | 保留 |
0xCC | CRSF_ADDRESS_RACE_TAG | Race tag |
0xEA | CRSF_ADDRESS_RADIO_TRANSMITTER | 手柄 |
0xEC | CRSF_ADDRESS_CRSF_RECEIVER | CRSF接收机 |
0xEE | CRSF_ADDRESS_CRSF_TRANSMITTER | 射频模块 |
0xEF | CRSF_ADDRESS_ELRS_LUA | ELRS Lua |
(四)数据包类型{#packet-type}
Value | Enum | Payload Bytes | Telemetry | Description |
---|---|---|---|---|
0x02 | CRSF_FRAMETYPE_GPS | 15 | Y | 用于传输GPS位置、地速、航向、海拔、卫星数量等信息 |
0x07 | CRSF_FRAMETYPE_VARIO | 2 | - | 传输垂直速度信息 |
0x08 | CRSF_FRAMETYPE_BATTERY_SENSOR | 8 | Y | 包含电池电压、电流、mAh、剩余电量百分比等电池状态信息 |
0x09 | CRSF_FRAMETYPE_BARO_ALTITUDE | 3 | Y | 传输气压高度和可选的垂直速度信息 |
0x0B | CRSF_FRAMETYPE_HEARTBEAT | 2 | - | (CRSFv3)心跳信号,用于表示设备的存活状态 |
0x14 | CRSF_FRAMETYPE_LINK_STATISTICS | 10 | - | 信号状态,包括上行/下行RSSI、SNR、链路质量、RF帧率、发射功率等 |
0x16 | CRSF_FRAMETYPE_RC_CHANNELS_PACKED | 22 | - | 传输通道数据(遥控器到发射机、接收机到飞控) |
0x17 | CRSF_FRAMETYPE_SUBSET_RC_CHANNELS_PACKED | - | - | (CRSFv3)通道子集数据 |
0x1C | CRSF_FRAMETYPE_LINK_RX_ID | 5 | Y | 接收机RSSI百分比、功率等信息 |
0x1D | CRSF_FRAMETYPE_LINK_TX_ID | 6 | Y | 发射机RSSI百分比、功率、fps等信息 |
0x1E | CRSF_FRAMETYPE_ATTITUDE | 6 | Y | 传输姿态数据,包括俯仰角、横滚角、偏航角 |
0x21 | CRSF_FRAMETYPE_FLIGHT_MODE | 1 | Y | 飞控的飞行模式 |
0x28 | CRSF_FRAMETYPE_DEVICE_PING | 0 | - | 发送方请求所有目标设备的设备信息 |
0x29 | CRSF_FRAMETYPE_DEVICE_INFO | - | - | 设备名称、固件版本、硬件版本、序列号等设备信息,作为对设备ping请求的响应 |
0x2B | CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY | 8 | - | 配置项数据块 |
0x2C | CRSF_FRAMETYPE_PARAMETER_READ | 2 | - | 配置项读取请求 |
0x2D | CRSF_FRAMETYPE_PARAMETER_WRITE | - | - | 配置项写入请求 |
0x2E | CRSF_FRAMETYPE_ELRS_STATUS | - | - | ELRS的好坏数据包计数、状态标志等 |
0x32 | CRSF_FRAMETYPE_COMMAND | - | - | 执行CRSF命令 |
0x3A | CRSF_FRAMETYPE_RADIO_ID | - | - | 用于OpenTX同步的扩展类型 |
0x78 | CRSF_FRAMETYPE_KISS_REQ | - | - | KISS请求 |
0x79 | CRSF_FRAMETYPE_KISS_RESP | - | - | KISS响应 |
0x7A | CRSF_FRAMETYPE_MSP_REQ | - | - | MSP参数请求/命令 |
0x7B | CRSF_FRAMETYPE_MSP_RESP | - | - | MSP参数响应块 |
0x7C | CRSF_FRAMETYPE_MSP_WRITE | - | - | MSP参数写入 |
0x7D | CRSF_FRAMETYPE_DISPLAYPORT_CMD | - | - | (CRSFv3)MSP显示端口控制命令 |
0x80 | CRSF_FRAMETYPE_ARDPILOT_RESP | - | - | ArduPilot输出 |
(五)示例
IN: C8 06 2C EE EF 01 00 76
OUT: C8 3E 2B EA EE
01 01 00 09 50 61 63 6B 65 74 20 52 61 74 65 00
35 30 28 2D 31 31 37 64 62 6D 29 3B 31 35 30 28
2D 31 31 32 64 62 6D 29 3B 32 35 30 28 2D 31 30
38 64 62 6D 29 3B 35 30 30 28
E5
(1)0xC8为sync。
(2)In中长度为0x6,Out中长度为0x3E。
(3)In中,0x2C表示“配置项读取请求”;Out中,0x2B表示“配置项数据块”。
(4)Out中,0xEA表示“手柄”,0xEE表示“射频模块”。
(5)两端数据最后的0x76和0xE5分别为从type到payload末尾所有字节的CRC-8校验。