ExpressLRS CRSF协议详解:与BetaFlight的无缝集成
什么是CRSF协议?
CRSF(Crossfire)协议是一种高效的无线电通信协议,专为RC(遥控)应用设计,尤其适用于需要低延迟和高可靠性的场景。在ExpressLRS项目中,CRSF协议扮演着关键角色,它负责在遥控器和设备之间传输控制信号和遥测数据。与传统的PWM或SBUS协议相比,CRSF协议具有更高的带宽利用率和更低的延迟,这使得它成为高性能FPV飞行的理想选择。
ExpressLRS项目通过src/lib/CrsfProtocol/crsf_protocol.h文件实现了CRSF协议的核心功能。该文件定义了协议的帧结构、数据类型和各种常量,为整个系统的通信提供了基础。
CRSF协议帧结构
CRSF协议采用了紧凑的帧结构设计,以最大限度地提高数据传输效率。一个典型的CRSF帧由以下几个部分组成:
- 设备地址(Device Address):标识消息的发送者和接收者
- 帧大小(Frame Size):指示帧的总长度
- 帧类型(Frame Type):指定帧中数据的类型
- 有效载荷(Payload):实际传输的数据内容
- CRC校验(CRC Checksum):确保数据完整性
帧结构定义
在src/lib/CrsfProtocol/crsf_protocol.h中,CRSF帧结构被定义为:
typedef struct crsf_header_s
{
uint8_t device_addr; // 来自crsf_addr_e
uint8_t frame_size; // 从该字节开始计数,因此必须是有效载荷大小 + 2(类型和crc)
crsf_frame_type_e type;
uint8_t payload[0];
} PACKED crsf_header_t;
这种紧凑的结构设计使得CRSF协议能够在有限的带宽下传输更多的信息,同时保持低延迟特性。
设备地址
CRSF协议定义了一系列设备地址,用于标识不同类型的设备:
typedef enum : uint8_t
{
CRSF_ADDRESS_BROADCAST = 0x00,
CRSF_ADDRESS_USB = 0x10,
CRSF_ADDRESS_TBS_CORE_PNP_PRO = 0x80,
CRSF_ADDRESS_RESERVED1 = 0x8A,
CRSF_ADDRESS_CURRENT_SENSOR = 0xC0,
CRSF_ADDRESS_GPS = 0xC2,
CRSF_ADDRESS_TBS_BLACKBOX = 0xC4,
CRSF_ADDRESS_FLIGHT_CONTROLLER = 0xC8,
CRSF_ADDRESS_RESERVED2 = 0xCA,
CRSF_ADDRESS_RACE_TAG = 0xCC,
CRSF_ADDRESS_RADIO_TRANSMITTER = 0xEA,
CRSF_ADDRESS_CRSF_RECEIVER = 0xEC,
CRSF_ADDRESS_CRSF_TRANSMITTER = 0xEE,
CRSF_ADDRESS_ELRS_LUA = 0xEF
} crsf_addr_e;
其中,CRSF_ADDRESS_FLIGHT_CONTROLLER(0xC8)是与BetaFlight飞控通信时使用的地址。
帧类型
CRSF协议支持多种帧类型,以适应不同的数据传输需求:
typedef enum : uint8_t
{
CRSF_FRAMETYPE_GPS = 0x02,
CRSF_FRAMETYPE_VARIO = 0x07,
CRSF_FRAMETYPE_BATTERY_SENSOR = 0x08,
CRSF_FRAMETYPE_BARO_ALTITUDE = 0x09,
CRSF_FRAMETYPE_AIRSPEED = 0x0A,
CRSF_FRAMETYPE_HEARTBEAT = 0x0B,
CRSF_FRAMETYPE_RPM = 0x0C,
CRSF_FRAMETYPE_TEMP = 0x0D,
CRSF_FRAMETYPE_CELLS = 0x0E,
CRSF_FRAMETYPE_LINK_STATISTICS = 0x14,
CRSF_FRAMETYPE_RC_CHANNELS_PACKED = 0x16,
CRSF_FRAMETYPE_ATTITUDE = 0x1E,
CRSF_FRAMETYPE_FLIGHT_MODE = 0x21,
// 扩展头帧,范围:0x28 到 0x96
CRSF_FRAMETYPE_DEVICE_PING = 0x28,
CRSF_FRAMETYPE_DEVICE_INFO = 0x29,
CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY = 0x2B,
CRSF_FRAMETYPE_PARAMETER_READ = 0x2C,
CRSF_FRAMETYPE_PARAMETER_WRITE = 0x2D,
CRSF_FRAMETYPE_ELRS_STATUS = 0x2E, // ELRS好坏包计数和状态标志
CRSF_FRAMETYPE_COMMAND = 0x32,
CRSF_FRAMETYPE_HANDSET = 0x3A,
// KISS帧
CRSF_FRAMETYPE_KISS_REQ = 0x78,
CRSF_FRAMETYPE_KISS_RESP = 0x79,
// MSP命令
CRSF_FRAMETYPE_MSP_REQ = 0x7A, // 使用msp序列作为命令的响应请求
CRSF_FRAMETYPE_MSP_RESP = 0x7B, // 回复58字节分块二进制
CRSF_FRAMETYPE_MSP_WRITE = 0x7C, // 写入8字节分块二进制(OpenTX出站遥测缓冲区限制)
// Ardupilot帧
CRSF_FRAMETYPE_ARDUPILOT_RESP = 0x80,
} crsf_frame_type_e;
其中,CRSF_FRAMETYPE_RC_CHANNELS_PACKED(0x16)是用于传输RC通道数据的关键帧类型,而CRSF_FRAMETYPE_MSP_REQ、CRSF_FRAMETYPE_MSP_RESP和CRSF_FRAMETYPE_MSP_WRITE则支持与BetaFlight飞控的MSP协议通信。
通道数据编码
CRSF协议采用了高效的通道数据编码方式,将16个RC通道的数据压缩到单个帧中。每个通道使用11位表示,取值范围为172至1811,对应传统PWM信号的987us至2012us。
typedef struct crsf_channels_s
{
unsigned ch0 : 11;
unsigned ch1 : 11;
unsigned ch2 : 11;
unsigned ch3 : 11;
unsigned ch4 : 11;
unsigned ch5 : 11;
unsigned ch6 : 11;
unsigned ch7 : 11;
unsigned ch8 : 11;
unsigned ch9 : 11;
unsigned ch10 : 11;
unsigned ch11 : 11;
unsigned ch12 : 11;
unsigned ch13 : 11;
unsigned ch14 : 11;
unsigned ch15 : 11;
} PACKED crsf_channels_t;
这种紧凑的编码方式使得CRSF协议能够在单个帧中传输16个通道的数据,同时保持低延迟和高刷新率。
与BetaFlight的集成
CRSF协议与BetaFlight飞控的集成主要通过MSP(MultiWii Serial Protocol)协议实现。ExpressLRS通过CRSF帧封装MSP消息,使得遥控器能够直接与BetaFlight飞控通信,实现参数配置、飞行模式切换等功能。
MSP消息封装
在src/lib/CrsfProtocol/crsf_protocol.h中,定义了用于封装MSP消息的结构:
#define MSP_REQUEST_PAYLOAD_LENGTH(len) 7 + len // 状态 + 标志 + 2 功能 + 2 长度 + crc + 有效载荷
#define MSP_REQUEST_LENGTH(len) (sizeof(crsf_ext_header_t) + MSP_REQUEST_PAYLOAD_LENGTH(len) + CRSF_FRAME_CRC_SIZE)
#define MSP_REQUEST_FRAME_SIZE(len) (MSP_REQUEST_PAYLOAD_LENGTH(len) + CRSF_FRAME_LENGTH_EXT_TYPE_CRC)
这种封装方式允许CRSF协议传输任意的MSP消息,从而实现与BetaFlight飞控的全面集成。
VTX配置示例
作为CRSF与BetaFlight集成的一个具体示例,我们来看一下VTX(视频发射机)配置的实现:
typedef struct mspVtxConfigPacket_s
{
uint8_t vtxType;
uint8_t band;
uint8_t channel;
uint8_t power;
uint8_t pitmode;
uint16_t freq;
uint8_t deviceIsReady;
uint8_t lowPowerDisarm;
uint16_t pitModeFreq;
uint8_t vtxTableAvailable;
uint8_t bands;
uint8_t channels;
uint8_t powerLevels;
} PACKED mspVtxConfigPacket_t;
这个结构定义了通过MSP协议配置VTX所需的所有参数。通过CRSF协议传输这个结构,遥控器可以直接调整BetaFlight飞控上的VTX设置,无需额外的配置工具。
数据转换函数
为了确保不同系统之间的数据兼容性,CRSF协议实现了一系列数据转换函数。这些函数在src/lib/CrsfProtocol/crsf_protocol.h中定义,用于在CRSF格式和其他常用格式之间进行转换。
CRSF与PWM转换
// 将CRSF值转换为微秒(us)
static inline uint16_t ICACHE_RAM_ATTR CRSF_to_US(uint16_t val)
{
return fmap(val, CRSF_CHANNEL_VALUE_MIN, CRSF_CHANNEL_VALUE_MAX, 988, 2012);
}
// 将10位值缩放到CRSF值
static inline uint16_t ICACHE_RAM_ATTR UINT10_to_CRSF(uint16_t val)
{
return fmap(val, 0, 1023, CRSF_CHANNEL_VALUE_MIN, CRSF_CHANNEL_VALUE_MAX);
}
这些函数确保了CRSF协议与传统PWM信号之间的无缝转换,使得使用CRSF的系统能够与各种RC设备兼容。
Switch转换
CRSF协议还提供了专门的函数用于处理开关输入:
static inline uint8_t ICACHE_RAM_ATTR CRSF_to_SWITCH3b(uint16_t ch)
{
// AUX2-7是低分辨率,"7pos" 6+中心 (3-bit)
// 输出均匀映射到6个输出值 (0-5)
// 使用特殊值7表示中间位置,因此它适用于
// 具有中间位置的开关以及6位置开关
const uint16_t CHANNEL_BIN_COUNT = 6;
const uint16_t CHANNEL_BIN_SIZE = (CRSF_CHANNEL_VALUE_MAX - CRSF_CHANNEL_VALUE_MIN) / CHANNEL_BIN_COUNT;
// 如果通道在中间位置的1/4 BIN范围内,则使用特殊值7
if (ch < (CRSF_CHANNEL_VALUE_MID-CHANNEL_BIN_SIZE/4)
|| ch > (CRSF_CHANNEL_VALUE_MID+CHANNEL_BIN_SIZE/4))
return CRSF_to_N(ch, CHANNEL_BIN_COUNT);
return 7;
}
这个函数将CRSF通道值转换为3位开关值,支持普通开关和带中间位置的开关,增强了系统的灵活性。
遥测数据传输
CRSF协议不仅支持控制信号的传输,还能高效地传输各种遥测数据。这对于实时监控设备状态至关重要。
电池遥测
typedef struct crsf_sensor_battery_s
{
unsigned voltage : 16; // mv * 100 大端序
unsigned current : 16; // ma * 100
unsigned capacity : 24; // mah
unsigned remaining : 8; // %
} PACKED crsf_sensor_battery_t;
这个结构定义了电池遥测数据的格式,包括电压、电流、容量和剩余电量等关键信息。
GPS数据
typedef struct crsf_sensor_gps_s
{
int32_t latitude; // 度 / 10`000`000
int32_t longitude; // 度 / 10`000`000
uint16_t groundspeed; // km/h / 10
uint16_t gps_heading; // 度 / 100
uint16_t altitude; // 米 1000m 偏移
uint8_t satellites_in_use; // 数量
} PACKED crsf_sensor_gps_t;
GPS数据结构允许精确的位置跟踪,这对于自主飞行和返航功能至关重要。
链路质量
typedef struct crsfPayloadLinkstatistics_s
{
uint8_t uplink_RSSI_1;
uint8_t uplink_RSSI_2;
uint8_t uplink_Link_quality;
int8_t uplink_SNR;
uint8_t active_antenna;
uint8_t rf_Mode;
uint8_t uplink_TX_Power;
uint8_t downlink_RSSI_1;
uint8_t downlink_package_success_rate;
int8_t downlink_SNR;
} PACKED crsfLinkStatistics_t;
链路质量数据为用户提供了实时的通信链路状态信息,帮助用户评估当前的飞行环境是否安全。
总结
CRSF协议通过紧凑的帧结构、高效的数据编码和灵活的扩展性,为ExpressLRS与BetaFlight的无缝集成提供了强大的通信基础。通过src/lib/CrsfProtocol/crsf_protocol.h中定义的各种结构和函数,系统实现了低延迟、高可靠性的控制信号和遥测数据传输。
无论是对于普通的RC爱好者还是专业的FPV飞行员,这种集成都带来了显著的优势:更精确的控制、更丰富的遥测数据和更简化的系统配置流程。随着ExpressLRS项目的不断发展,CRSF协议将继续发挥核心作用,推动RC应用技术的进步。
要深入了解CRSF协议的实现细节,建议查阅项目源代码,特别是src/lib/CrsfProtocol目录下的文件。这些文件包含了协议实现的完整细节,对于理解整个系统的工作原理至关重要。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



