2、SBUS物理层特性:信号电平、反向逻辑与串口配置

好,咱们进入第二章。这一章讲的是SBUS最底层的物理特性。说白了,就是信号在线上怎么跑、用什么电压、什么格式。这些是基础中的基础,搞不懂的话,后面解析数据包全是白搭。

我记得刚接触SBUS那会儿,拿着逻辑分析仪一看波形,直接懵了——怎么跟我预想的完全不一样?后来才发现,SBUS这家伙,天生就是「反着来」的。嗯,咱们慢慢聊。

2.1 信号电平:3.3V还是5V?

SBUS的信号电平,其实没有你想象的那么死板。它既可以用3.3V,也可以用5V。但这里有个坑——不是所有接收机都兼容5V逻辑

我个人的习惯是:能用3.3V就用3.3V。为什么?因为现在主流的飞控主控芯片,比如STM32F4、F7系列,IO口基本都是3.3V耐受。你直接怼5V进去,虽然很多芯片标称「5V tolerant」,但长期下来,风险还是有的。

关键点:

  • SBUS信号电平:3.3V 或 5V,取决于接收机型号
  • 常见接收机(如FrSky X8R、R9MM):输出3.3V逻辑
  • 部分老款接收机:可能输出5V逻辑
  • 飞控端:建议使用3.3V电平,或加电平转换

⚠️ 我曾经踩过的坑:

有一次我用一个5V输出的接收机直接连到STM32F405的USART引脚上。刚开始跑得好好的,飞了大概20个起落后,突然串口收不到数据了。查了半天,发现那个引脚已经烧坏了。从那以后,我所有SBUS输入都加了一颗74LVC245做电平转换,再也没出过问题。

2.2 反向电平逻辑:SBUS为什么「反着来」?

这是SBUS最让人迷惑的地方。正常的UART信号,空闲时是高电平,起始位是低电平。但SBUS恰恰相反——空闲时是低电平,起始位是高电平

为什么会这样?其实是为了兼容性。SBUS最初设计时,为了能直接驱动某些老式的反相器电路,故意把逻辑反了。你想想看,如果接收机内部已经做了反相,那信号出来自然就是反的。

所以,你在飞控端接收SBUS数据时,必须做一件事:硬件反相软件反相

方案 实现方式 优缺点
硬件反相 用三极管或反相器(如74HC04) 稳定可靠,不占CPU资源
软件反相 在串口中断里手动取反每一位 省硬件,但增加CPU负担
STM32硬件反相 使用USART的RXINV位 最优雅,零成本

💡 我的建议:

如果你用STM32,直接开启USART的RXINV位(接收数据反转)就行。在CubeMX里勾上「RX Pin Inverted」,或者代码里写 USART1->CR2 |= USART_CR2_RXINV。这样硬件帮你反相,省心又省力。

2.3 波特率100000bps:为什么不是115200?

很多人第一次看到SBUS的波特率,都会问:为什么是100000,而不是更常见的115200?

嗯,这个问题我当年也纠结过。后来查了资料才明白:SBUS的帧长度是25字节,每字节10位(8数据位+1起始位+1停止位),总共250位。以100000bps传输,一帧正好耗时2.5ms。而SBUS的更新周期是9ms(约111Hz),2.5ms完全够用。

那为什么不用115200?因为100000是100kHz的整数倍,对某些晶振分频更友好。说白了,就是历史遗留设计选择。

波特率配置要点:

  • 波特率:100000 bps(不是115200!)
  • 误差容忍:±2%以内,否则丢帧
  • 常见晶振:8MHz、16MHz、72MHz都能精确分频到100000

2.4 8E2串口配置:奇偶校验和停止位

SBUS的串口配置是8E2。什么意思?

  • 8:8位数据位
  • E:偶校验(Even Parity)
  • 2:2位停止位

这和常见的8N1(无校验、1位停止位)完全不同。我刚开始做SBUS驱动时,就忘了配校验位,结果数据全是乱码。排查了半天才发现是校验位没设对。

偶校验的意思是:数据位中1的个数加上校验位,总共有偶数个1。接收端会检查这个,如果不对,就说明数据传错了。

⚠️ 注意:

很多串口库默认是8N1。如果你用Arduino的Serial.begin(),它不支持8E2。这时候你得用Serial1.begin(100000, SERIAL_8E2)这种写法。在STM32的HAL库里,要设置USART_InitStructure.Parity = USART_PARITY_EVENUSART_InitStructure.StopBits = USART_STOPBITS_2

2.5 知识体系总览

下面这张图,把SBUS物理层的核心要素串起来了。你可以把它当作一个快速参考。

SBUS物理层特性总览 信号电平 3.3V / 5V 建议3.3V 需电平转换 反向电平逻辑 空闲低电平 起始位高电平 需硬件/软件反相 波特率 100000 bps 非115200 误差±2%以内 串口配置 8E2 偶校验 2位停止位 核心要点总结 1. 电平:3.3V优先,必要时加电平转换芯片(如74LVC245) 2. 反相:STM32用RXINV位,其他平台用硬件反相器 3. 波特率:100000,别设成115200 4. 串口:8E2,偶校验+2位停止位,别用默认的8N1

2.6 实际配置示例

最后,给你一个Arduino和STM32的配置代码片段。直接拿去用就行。

Arduino(Teensy/STM32duino):

// SBUS串口初始化
Serial1.begin(100000, SERIAL_8E2);
// 注意:Arduino Uno/Mega不支持100000波特率,建议用Teensy或STM32

STM32 HAL库:

// USART句柄配置
huart1.Instance = USART1;
huart1.Init.BaudRate = 100000;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_2;
huart1.Init.Parity = UART_PARITY_EVEN;
huart1.Init.Mode = UART_MODE_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// 开启接收数据反转(硬件反相)
huart1.Init.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXINVERT_INIT;
huart1.Init.AdvancedInit.RxPinLevelInvert = UART_ADVFEATURE_RXINV_ENABLE;
HAL_UART_Init(&huart1);

💡 一个小技巧:

如果你用逻辑分析仪抓SBUS波形,记得把触发条件设为「上升沿」。因为SBUS空闲是低电平,起始位是高电平,上升沿才是数据开始的标志。我第一次抓波形时设成了下降沿,结果怎么都触发不了,折腾了半小时才发现问题。

好了,这一章就到这里。物理层搞定了,下一章咱们就可以真正开始解析SBUS数据帧了。到时候你会看到,25个字节里到底藏了什么秘密。


公众号:蓝海资料掘金营,微信deep3321