BetaFlight模块设计之三十七:SBUS
- 1. 源由
- 2. sbus启动&动态任务
- 3. 主要函数
- 3.1 sbus初始化
- 3.2 sbusFrameStatus更新
- 3.3 rxFrameTimeUs
- 3.4 sbusDataReceive接收数据
- 4. 辅助函数
- 4.1 sbusChannelsDecode
- 5. 参考资料
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
对通道数据进行译码,并根据接收机内部信息判别FAILSAFE
和SIGNAL_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协议兼容硬件电气特性问题