SBUS出现24个字节1帧或者0xF8开头的问题及其解决办法

问题

去年下半年接到导师给的任务:用一个航模遥控器控制一台需要多控制量的设备。由于单片机资源紧张,我只能使用一个串口接收SBUS,收到数据后再解算每个通道的值。上网查看了这篇文章:SBUS协议及编解码,C语言源码,了解到协议的构成,信心满满的自己焊了其中第一幅图的反相器,串口接上一看懵了。为什么别人读出来的是0x0F开头稳定的25字节1帧,我读出来的是0xF8开头的时而24字节时而25字节1帧呢?试了很多种办法,打了厂家客服电话,均没有结果。后来发现是反相器的原因。由于过程中在网上找不到相关错误,所以发个博客,万一以后有和我一样的新手朋友遇到这个问题,请按如下方法解决。

解决

反相器!

在这篇博客中,提到了两种反相器的结构。我自己焊的第一种反相器,虽然用表测出具有反向效果,但是并不适用于SBUS。建议大家使用第二种反相器结构:
反相器
注意:

1.没有合适的电容可以不加,但一定要加下拉电阻!
2.在使用STM32系列单片机时,该反相器芯片的供电要选择3.3V!!5V供电将不能正常读取SBUS!

我知道我犯得这种错误很多人都不会犯,但是万一有和我一样的新手朋友,遇到同样的问题,希望这篇文章能为你节省一些时间。

学习不止,实践出真知。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个基本的S.Bus通信代码示例,仅供参考: ```c // 定义S.Bus通道数据结构体 typedef struct { uint16_t ch0; uint16_t ch1; uint16_t ch2; uint16_t ch3; uint16_t ch4; uint16_t ch5; uint16_t ch6; uint16_t ch7; uint16_t ch8; uint16_t ch9; uint16_t ch10; uint16_t ch11; uint16_t ch12; uint16_t ch13; uint16_t ch14; uint16_t ch15; } SBUSChannels; // 定义全局SBUSChannels sbusChannels; // 定义S.Bus接收中断函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { static uint8_t sbusBuf[25]; static uint8_t sbusIndex = 0; if (huart->Instance == USART1) { // UART1为S.Bus接收口 sbusBuf[sbusIndex++] = sbusData; if (sbusIndex == 25) { // 一S.Bus数据为25个字节 sbusIndex = 0; if (sbusBuf[0] == 0x0f && sbusBuf[24] == 0x00) { // 判断头和sbusChannels.ch0 = ((uint16_t)sbusBuf[1] | (uint16_t)(sbusBuf[2] << 8)) & 0x07ff; sbusChannels.ch1 = ((uint16_t)sbusBuf[2] >> 3 | (uint16_t)(sbusBuf[3] << 5)) & 0x07ff; sbusChannels.ch2 = ((uint16_t)sbusBuf[3] >> 6 | (uint16_t)(sbusBuf[4] << 2) | (uint16_t)(sbusBuf[5] << 10)) & 0x07ff; sbusChannels.ch3 = ((uint16_t)sbusBuf[5] >> 1 | (uint16_t)(sbusBuf[6] << 7)) & 0x07ff; sbusChannels.ch4 = ((uint16_t)sbusBuf[6] >> 4 | (uint16_t)(sbusBuf[7] << 4)) & 0x07ff; sbusChannels.ch5 = ((uint16_t)sbusBuf[7] >> 7 | (uint16_t)(sbusBuf[8] << 1) | (uint16_t)(sbusBuf[9] << 9)) & 0x07ff; sbusChannels.ch6 = ((uint16_t)sbusBuf[9] >> 2 | (uint16_t)(sbusBuf[10] << 6)) & 0x07ff; sbusChannels.ch7 = ((uint16_t)sbusBuf[10] >> 5 | (uint16_t)(sbusBuf[11] << 3)) & 0x07ff; sbusChannels.ch8 = ((uint16_t)sbusBuf[12] | (uint16_t)(sbusBuf[13] << 8)) & 0x07ff; sbusChannels.ch9 = ((uint16_t)sbusBuf[13] >> 3 | (uint16_t)(sbusBuf[14] << 5)) & 0x07ff; sbusChannels.ch10 = ((uint16_t)sbusBuf[14] >> 6 | (uint16_t)(sbusBuf[15] << 2) | (uint16_t)(sbusBuf[16] << 10)) & 0x07ff; sbusChannels.ch11 = ((uint16_t)sbusBuf[16] >> 1 | (uint16_t)(sbusBuf[17] << 7)) & 0x07ff; sbusChannels.ch12 = ((uint16_t)sbusBuf[17] >> 4 | (uint16_t)(sbusBuf[18] << 4)) & 0x07ff; sbusChannels.ch13 = ((uint16_t)sbusBuf[18] >> 7 | (uint16_t)(sbusBuf[19] << 1) | (uint16_t)(sbusBuf[20] << 9)) & 0x07ff; sbusChannels.ch14 = ((uint16_t)sbusBuf[20] >> 2 | (uint16_t)(sbusBuf[21] << 6)) & 0x07ff; sbusChannels.ch15 = ((uint16_t)sbusBuf[21] >> 5 | (uint16_t)(sbusBuf[22] << 3)) & 0x07ff; } } } } // 定义S.Bus发送函数 void sendSbusData(void) { static uint8_t sbusBuf[25]; sbusBuf[0] = 0x0f; // 头为0x0f sbusBuf[23] = 0x00; // 最后一个字节为0x00 sbusBuf[24] = 0x00; // 最后一个字节为0x00 sbusBuf[1] = (sbusChannels.ch0 & 0x00ff); sbusBuf[2] = ((sbusChannels.ch0 & 0x07ff) >> 8) | ((sbusChannels.ch1 & 0x07ff) << 3); sbusBuf[3] = (sbusChannels.ch1 & 0x07ff) >> 5 | ((sbusChannels.ch2 & 0x07ff) << 6); sbusBuf[4] = (sbusChannels.ch2 & 0x07ff) >> 2; sbusBuf[5] = ((sbusChannels.ch2 & 0x07ff) >> 10) | ((sbusChannels.ch3 & 0x07ff) << 1); sbusBuf[6] = (sbusChannels.ch3 & 0x07ff) >> 7 | ((sbusChannels.ch4 & 0x07ff) << 4); sbusBuf[7] = (sbusChannels.ch4 & 0x07ff) >> 4 | ((sbusChannels.ch5 & 0x07ff) << 7); sbusBuf[8] = (sbusChannels.ch5 & 0x07ff) >> 1; sbusBuf[9] = ((sbusChannels.ch5 & 0x07ff) >> 9) | ((sbusChannels.ch6 & 0x07ff) << 2); sbusBuf[10] = (sbusChannels.ch6 & 0x07ff) >> 6 | ((sbusChannels.ch7 & 0x07ff) << 5); sbusBuf[11] = (sbusChannels.ch7 & 0x07ff) >> 3; sbusBuf[12] = (sbusChannels.ch8 & 0x00ff); sbusBuf[13] = ((sbusChannels.ch8 & 0x07ff) >> 8) | ((sbusChannels.ch9 & 0x07ff) << 3); sbusBuf[14] = (sbusChannels.ch9 & 0x07ff) >> 5 | ((sbusChannels.ch10 & 0x07ff) << 6); sbusBuf[15] = (sbusChannels.ch10 & 0x07ff) >> 2; sbusBuf[16] = ((sbusChannels.ch10 & 0x07ff) >> 10) | ((sbusChannels.ch11 & 0x07ff) << 1); sbusBuf[17] = (sbusChannels.ch11 & 0x07ff) >> 7 | ((sbusChannels.ch12 & 0x07ff) << 4); sbusBuf[18] = (sbusChannels.ch12 & 0x07ff) >> 4 | ((sbusChannels.ch13 & 0x07ff) << 7); sbusBuf[19] = (sbusChannels.ch13 & 0x07ff) >> 1; sbusBuf[20] = ((sbusChannels.ch13 & 0x07ff) >> 9) | ((sbusChannels.ch14 & 0x07ff) << 2); sbusBuf[21] = (sbusChannels.ch14 & 0x07ff) >> 6 | ((sbusChannels.ch15 & 0x07ff) << 5); sbusBuf[22] = (sbusChannels.ch15 & 0x07ff) >> 3; HAL_UART_Transmit(&huart1, sbusBuf, 25, 1000); // UART1为S.Bus发送口 } ``` 以上代码仅供参考,具体实现可能会因为硬件平台和工程环境的不同而有所差异。在实际使用中,需要根据具体情况进行调试和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值