BetaFlight模块设计之三十七:SBUS

1. 源由

接着BetaFlight模块设计之三十六:SoftSerial,就Betaflight关于STM32F405 SBUS协议兼容硬件电气特性问题的代码支持问题做一个研读,看看目前设计上这个框架代码是否支持SBUS。

2. sbus启动&动态任务

main
 └──> init
     └──> rxInit
         └──> serialRxInit
             └──> sbusInit
main
 └──> run
     └──> scheduler
         └──> rxFrameCheck
             └──> rcFrameStatusFn(sbusFrameStatus)

[TASK_RX] = DEFINE_TASK("RX", NULL, rxUpdateCheck, taskUpdateRxMain, TASK_PERIOD_HZ(33), TASK_PRIORITY_HIGH), // If event-based scheduling doesn't work, fallback to periodic scheduling
 └──> taskUpdateRxMain
     └──> processRx
         └──> updateRcRefreshRate
             └──> rxGetFrameDelta
                 └──> rcFrameTimeUsFn(rxFrameTimeUs)

3. 主要函数

3.1 sbus初始化

sbusInit
 │   //支持SBUS_MAX_CHANNEL(18)个通道
 ├──> static uint16_t sbusChannelData[SBUS_MAX_CHANNEL];
 ├──> static sbusFrameData_t sbusFrameData;
 ├──> static uint32_t sbusBaudRate;
 │
 ├──> rxRuntimeState->channelData = sbusChannelData;
 ├──> rxRuntimeState->frameData = &sbusFrameData;
 │
 │   //初始化通道数据
 ├──> sbusChannelsInit(rxConfig, rxRuntimeState);
 │
 ├──> rxRuntimeState->channelCount = SBUS_MAX_CHANNEL;
 │
 │   //配置波特率SBUS_FAST_BAUDRATE(200000)/SBUS_BAUDRATE(6000)
 ├──> <rxConfig->sbus_baud_fast>
 │   └──> sbusBaudRate  = SBUS_FAST_BAUDRATE;
 ├──> < else >
 │   └──> sbusBaudRate  = SBUS_BAUDRATE;
 │
 │   //挂两个钩子函数:sbusFrameStatus/rxFrameTimeUs
 ├──> rxRuntimeState->rcFrameStatusFn = sbusFrameStatus;
 ├──> rxRuntimeState->rcFrameTimeUsFn = rxFrameTimeUs;
 │
 ├──> const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL);
 ├──> <!portConfig>
 │   └──> return false;
 │
 ├──> <USE_TELEMETRY>
 │   └──> bool portShared = telemetryCheckRxPortShared(portConfig, rxRuntimeState->serialrxProvider);
 ├──> <#else>
 │   └──> bool portShared = false;
 │
 │   //端口初始化,回调函数sbusDataReceive
 ├──> serialPort_t *sBusPort = openSerialPort(portConfig->identifier,
 │      FUNCTION_RX_SERIAL,
 │      sbusDataReceive,
 │      &sbusFrameData,
 │      sbusBaudRate,
 │      portShared ? MODE_RXTX : MODE_RX,
 │      SBUS_PORT_OPTIONS | (rxConfig->serialrx_inverted ? 0 : SERIAL_INVERTED) | (rxConfig->halfDuplex ? SERIAL_BIDIR : 0))
 ├──> <rxConfig->rssi_src_frame_errors>
 │   └──> rssiSource = RSSI_SOURCE_FRAME_ERRORS;
 │
 ├──> <USE_TELEMETRY><portShared>
 │   └──> telemetrySharedPort = sBusPort;
 └──> return sBusPort != NULL;

3.2 sbusFrameStatus更新

sbusFrameStatus
 │   //检查帧状态
 ├──> sbusFrameData_t *sbusFrameData = rxRuntimeState->frameData;
 ├──> <!sbusFrameData->done>
 │   └──> return RX_FRAME_PENDING;
 │
 ├──> sbusFrameData->done = false;
 │
 ├──> DEBUG_SET(DEBUG_SBUS, DEBUG_SBUS_FRAME_FLAGS, sbusFrameData->frame.frame.channels.flags);
 │   //帧数据解码
 ├──> const uint8_t frameStatus = sbusChannelsDecode(rxRuntimeState, &sbusFrameData->frame.frame.channels);
 │
 │   //更新最近一次有效帧时间戳
 ├──> <!(frameStatus & (RX_FRAME_FAILSAFE | RX_FRAME_DROPPED))>
 │   └──> rxRuntimeState->lastRcFrameTimeUs = sbusFrameData->startAtUs;
 │
 └──> return frameStatus;
 
typedef enum {
    RX_FRAME_PENDING = 0,
    RX_FRAME_COMPLETE = (1 << 0),
    RX_FRAME_FAILSAFE = (1 << 1),
    RX_FRAME_PROCESSING_REQUIRED = (1 << 2),
    RX_FRAME_DROPPED = (1 << 3)
} rxFrameState_e;

3.3 rxFrameTimeUs

获取最近一帧有效数据的时间。

timeUs_t rxFrameTimeUs(void)
{
    return rxRuntimeState.lastRcFrameTimeUs;
}

3.4 sbusDataReceive接收数据

在这里插入图片描述

sbusDataReceive
 ├──> sbusFrameData_t *sbusFrameData = data;
 ├──> const timeUs_t nowUs = microsISR();
 ├──> const timeDelta_t sbusFrameTime = cmpTimeUs(nowUs, sbusFrameData->startAtUs);
 │
 │   //超时500,从新SBUS数据帧开始算(数据中断异常)
 ├──> <sbusFrameTime > (long)(SBUS_TIME_NEEDED_PER_FRAME + 500)>
 │   └──> sbusFrameData->position = 0;
 │
 │   //确保帧起始位置
 ├──> <sbusFrameData->position == 0>
 │   ├──> <c != SBUS_FRAME_BEGIN_BYTE>
 │   │   └──> return;
 │   └──> sbusFrameData->startAtUs = nowUs;
 │
 │   //读取一帧数据
 └──> <sbusFrameData->position < SBUS_FRAME_SIZE>
     ├──> sbusFrameData->frame.bytes[sbusFrameData->position++] = (uint8_t)c;
     ├──> <sbusFrameData->position < SBUS_FRAME_SIZE>
     │   └──> sbusFrameData->done = false;
     └──> < else >
         ├──> sbusFrameData->done = true;
         └──> DEBUG_SET(DEBUG_SBUS, DEBUG_SBUS_FRAME_TIME, sbusFrameTime);

typedef struct sbusChannels_s {
    // 176 bits of data (11 bits per channel * 16 channels) = 22 bytes.
    unsigned int chan0 : 11;
    unsigned int chan1 : 11;
    unsigned int chan2 : 11;
    unsigned int chan3 : 11;
    unsigned int chan4 : 11;
    unsigned int chan5 : 11;
    unsigned int chan6 : 11;
    unsigned int chan7 : 11;
    unsigned int chan8 : 11;
    unsigned int chan9 : 11;
    unsigned int chan10 : 11;
    unsigned int chan11 : 11;
    unsigned int chan12 : 11;
    unsigned int chan13 : 11;
    unsigned int chan14 : 11;
    unsigned int chan15 : 11;
    uint8_t flags;
} __attribute__((__packed__)) sbusChannels_t;
#define SBUS_CHANNEL_DATA_LENGTH sizeof(sbusChannels_t)
#define SBUS_FRAME_SIZE (SBUS_CHANNEL_DATA_LENGTH + 2)

4. 辅助函数

4.1 sbusChannelsDecode

对通道数据进行译码,并根据接收机内部信息判别FAILSAFESIGNAL_LOSS事件。

sbusChannelsDecode
 │   //16通道赋值
 ├──> uint16_t *sbusChannelData = rxRuntimeState->channelData;
 ├──> sbusChannelData[0] = channels->chan0;
 ├──> sbusChannelData[1] = channels->chan1;
 ├──> sbusChannelData[2] = channels->chan2;
 ├──> sbusChannelData[3] = channels->chan3;
 ├──> sbusChannelData[4] = channels->chan4;
 ├──> sbusChannelData[5] = channels->chan5;
 ├──> sbusChannelData[6] = channels->chan6;
 ├──> sbusChannelData[7] = channels->chan7;
 ├──> sbusChannelData[8] = channels->chan8;
 ├──> sbusChannelData[9] = channels->chan9;
 ├──> sbusChannelData[10] = channels->chan10;
 ├──> sbusChannelData[11] = channels->chan11;
 ├──> sbusChannelData[12] = channels->chan12;
 ├──> sbusChannelData[13] = channels->chan13;
 ├──> sbusChannelData[14] = channels->chan14;
 ├──> sbusChannelData[15] = channels->chan15;
 │
 │   //根据Flag标识赋值MAX/MIN
 ├──> <channels->flags & SBUS_FLAG_CHANNEL_17>
 │   └──> sbusChannelData[16] = SBUS_DIGITAL_CHANNEL_MAX;
 ├──> < else >
 │   └──> sbusChannelData[16] = SBUS_DIGITAL_CHANNEL_MIN;
 │
 │   //根据Flag标识赋值MAX/MIN
 ├──> <channels->flags & SBUS_FLAG_CHANNEL_18>
 │   └──> sbusChannelData[17] = SBUS_DIGITAL_CHANNEL_MAX;
 ├──> < else >
 │   └──> sbusChannelData[17] = SBUS_DIGITAL_CHANNEL_MIN;
 │
 │   //接收机标识FAILSAFE
 ├──> <channels->flags & SBUS_FLAG_FAILSAFE_ACTIVE>
 │   │  // internal failsafe enabled and rx failsafe flag set
 │   │  // RX *should* still be sending valid channel data (repeated), so use it.
 │   └──> return RX_FRAME_COMPLETE | RX_FRAME_FAILSAFE;
 │
 │   //接收机标识SIGNAL_LOSS
 ├──> <channels->flags & SBUS_FLAG_SIGNAL_LOSS>
 │   │  // The received data is a repeat of the last valid data so can be considered complete.
 │   └──> return RX_FRAME_COMPLETE | RX_FRAME_DROPPED;
 │
 └──> return RX_FRAME_COMPLETE;

5. 参考资料

【1】BetaFlight开源代码框架简介
【2】BetaFlight模块设计之三十六:SoftSerial
【3】Betaflight关于STM32F405 SBUS协议兼容硬件电气特性问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值