ExpressLRS CRSF协议详解:与BetaFlight的无缝集成

ExpressLRS CRSF协议详解:与BetaFlight的无缝集成

【免费下载链接】ExpressLRS ESP32/ESP8285-based High-Performance Radio Link for RC applications 【免费下载链接】ExpressLRS 项目地址: https://gitcode.com/GitHub_Trending/ex/ExpressLRS

什么是CRSF协议?

CRSF(Crossfire)协议是一种高效的无线电通信协议,专为RC(遥控)应用设计,尤其适用于需要低延迟和高可靠性的场景。在ExpressLRS项目中,CRSF协议扮演着关键角色,它负责在遥控器和设备之间传输控制信号和遥测数据。与传统的PWM或SBUS协议相比,CRSF协议具有更高的带宽利用率和更低的延迟,这使得它成为高性能FPV飞行的理想选择。

ExpressLRS项目通过src/lib/CrsfProtocol/crsf_protocol.h文件实现了CRSF协议的核心功能。该文件定义了协议的帧结构、数据类型和各种常量,为整个系统的通信提供了基础。

CRSF协议帧结构

CRSF协议采用了紧凑的帧结构设计,以最大限度地提高数据传输效率。一个典型的CRSF帧由以下几个部分组成:

  1. 设备地址(Device Address):标识消息的发送者和接收者
  2. 帧大小(Frame Size):指示帧的总长度
  3. 帧类型(Frame Type):指定帧中数据的类型
  4. 有效载荷(Payload):实际传输的数据内容
  5. 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_REQCRSF_FRAMETYPE_MSP_RESPCRSF_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目录下的文件。这些文件包含了协议实现的完整细节,对于理解整个系统的工作原理至关重要。

【免费下载链接】ExpressLRS ESP32/ESP8285-based High-Performance Radio Link for RC applications 【免费下载链接】ExpressLRS 项目地址: https://gitcode.com/GitHub_Trending/ex/ExpressLRS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值