文章目录

  • 1. SBUS信号简介
  • 2. STM32F7解析SBUS信号例程
    • (1) 串口配置
    • (2) 串口中断接收
    • (3) 信号解析

1. SBUS信号简介

最近在搞一个项目的通信和控制,用到了SBUS,记录一下心得。


SBUS全称serial-bus,是一种串口通信协议,广泛应用于航模遥控器(接收机)中。只用一根信号线就能传输多达16通道的数据,比多路PWM捕获高效且省资源。

  1. 串口配置:
    100k波特率,8位数据位,2位停止位,偶校验(EVEN),无控流,25个字节。
  2. 协议格式:(8字节)
    [startbyte] [data1][data2]…[data22][flags][endbyte]
    startbyte=0x0f;
    endbyte=0x00;
    data1…data22: LSB(低位在前),对应16个通道(ch1-ch16),每个通道11bit(22 × 8=16 × 11);
    flag位标志遥控器的通讯状态,我使用的乐迪AT9S在遥控器通上的时候是0x00,断开的时候是0xC0,可以通过查询flag位来采取失控保护。
  3. 数据范围
    航模遥控器输出的PWM值是1000~2000,中值为1500,sbus输出的会不一样,例如乐迪AT9S的范围为300 ~ 1700,中值1000,这个我估计跟遥控器厂家有关。
  4. sbus的负逻辑
    这个地方一定要万分注意,必须加硬件反相器,因为SBUS的信号是采用的负逻辑,也就是电平相反,不要试图在软件里面取反,因为软件里面只能操作数据位(记得串口配置里面的数据位8么),你是操作不了停止位、校验位啥的!!
    如果是自己画板子也很简单,如图所示
    5. 数据读取
    一般的串口调试助手可能没有100K波特率的选项,推荐一个串口调试助手MicroLab,可以自定义串口波特率,还有其他好功能自己探索叭。

2. STM32F7解析SBUS信号例程

清楚了通信协议,解析就很简单了。我使用的是正点原子的阿波罗F7开发板,其他的板子是一样的。

(1) 串口配置

首先一些变量声明,串口uart.c里用到的

#define USART_REC_LEN            100     //定义最大接收字节数 200
#define RXBUFFERSIZE            1       //缓存大小u8 USART1_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
u16 USART1_RX_STA = 0; //接收状态标记
u8 aRxBuffer1[RXBUFFERSIZE];          //HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄

串口初始化函数

void uart1_init(u32 bound)
{//UART 初始化设置UART1_Handler.Instance = USART1;                  //USART1UART1_Handler.Init.BaudRate = bound;               //波特率UART1_Handler.Init.WordLength = UART_WORDLENGTH_9B; //字长为8位数据格式UART1_Handler.Init.StopBits = UART_STOPBITS_1;        //一个停止位UART1_Handler.Init.Parity = UART_PARITY_EVEN;       //无奇偶校验位UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控UART1_Handler.Init.Mode = UART_MODE_TX_RX;         //收发模式HAL_UART_Init(&UART1_Handler);                        //HAL_UART_Init()会使能UART1HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer1, RXBUFFERSIZE); //该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
}void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{//GPIO端口设置GPIO_InitTypeDef GPIO_Initure;if (huart->Instance == USART1) //如果是串口1,进行串口1 MSP初始化{__HAL_RCC_GPIOA_CLK_ENABLE();  //使能GPIOA时钟__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟GPIO_Initure.Pin = GPIO_PIN_9;            //PA9GPIO_Initure.Mode = GPIO_MODE_AF_PP;      //复用推挽输出GPIO_Initure.Pull = GPIO_PULLUP;       //上拉GPIO_Initure.Speed = GPIO_SPEED_FAST;      //高速GPIO_Initure.Alternate = GPIO_AF7_USART1; //复用为USART1HAL_GPIO_Init(GPIOA, &GPIO_Initure);      //初始化PA9GPIO_Initure.Pin = GPIO_PIN_10;       //PA10HAL_GPIO_Init(GPIOA, &GPIO_Initure); //初始化PA10#if EN_USART1_RXHAL_NVIC_EnableIRQ(USART1_IRQn);        //使能USART1中断通道HAL_NVIC_SetPriority(USART1_IRQn, 3, 2); //抢占优先级3,子优先级3
#endif}
}

这里有个诡异的地方就是stm32要设置成9个数据位,一个停止位,我一开始按照8个数据位、两个停止位读出来的数据是错的,后来改了之后才正常了。是不是和stm32内部的串口配置有关,哪位大神弄明白了告诉我哈。

(2) 串口中断接收

串口中断函数,在中断函数里面接收数据,进行SBUS信号解析。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{int i;while (huart->Instance == USART1) //如果是串口1{USART1_RX_BUF[USART1_RX_STA] = aRxBuffer1[0];if (USART1_RX_STA == 0 && USART1_RX_BUF[USART1_RX_STA] != 0x0F) break; //帧头不对,丢掉USART1_RX_STA++;if (USART1_RX_STA > USART_REC_LEN) USART1_RX_STA = 0;  ///接收数据错误,重新开始接收if (USART1_RX_BUF[0] == 0x0F && USART1_RX_BUF[24] == 0x00 && USART1_RX_STA == 25) //接受完一帧数据{update_sbus(USART1_RX_BUF);for (i = 0; i<25; i++)       //清空缓存区USART1_RX_BUF[i] = 0;USART1_RX_STA = 0;}break;}
}

(3) 信号解析

上面中断函数里面有一个update_sbus函数,原型为u8 update_sbus(u8 *buf),解析subs信号全靠它了!!新建一个sbus.c文件,输入如下代码

#include "sbus.h"SBUS_CH_Struct SBUS_CH;//将sbus信号转化为通道值
u8 update_sbus(u8 *buf)
{int i;if (buf[23] == 0){SBUS_CH.ConnectState = 1;SBUS_CH.CH1 = ((int16_t)buf[ 1] >> 0 | ((int16_t)buf[ 2] << 8 )) & 0x07FF;SBUS_CH.CH2 = ((int16_t)buf[ 2] >> 3 | ((int16_t)buf[ 3] << 5 )) & 0x07FF;SBUS_CH.CH3 = ((int16_t)buf[ 3] >> 6 | ((int16_t)buf[ 4] << 2 ) | (int16_t)buf[ 5] << 10 ) & 0x07FF;SBUS_CH.CH4 = ((int16_t)buf[ 5] >> 1 | ((int16_t)buf[ 6] << 7 )) & 0x07FF;SBUS_CH.CH5 = ((int16_t)buf[ 6] >> 4 | ((int16_t)buf[ 7] << 4 )) & 0x07FF;SBUS_CH.CH6 = ((int16_t)buf[ 7] >> 7 | ((int16_t)buf[ 8] << 1 ) | (int16_t)buf[9] << 9 ) & 0x07FF;SBUS_CH.CH7 = ((int16_t)buf[ 9] >> 2 | ((int16_t)buf[10] << 6 )) & 0x07FF;SBUS_CH.CH8 = ((int16_t)buf[10] >> 5 | ((int16_t)buf[11] << 3 )) & 0x07FF;SBUS_CH.CH9 = ((int16_t)buf[12] << 0 | ((int16_t)buf[13] << 8 )) & 0x07FF;SBUS_CH.CH10 = ((int16_t)buf[13] >> 3 | ((int16_t)buf[14] << 5 )) & 0x07FF;SBUS_CH.CH11 = ((int16_t)buf[14] >> 6 | ((int16_t)buf[15] << 2 ) | (int16_t)buf[16] << 10 ) & 0x07FF;SBUS_CH.CH12 = ((int16_t)buf[16] >> 1 | ((int16_t)buf[17] << 7 )) & 0x07FF;SBUS_CH.CH13 = ((int16_t)buf[17] >> 4 | ((int16_t)buf[18] << 4 )) & 0x07FF;SBUS_CH.CH14 = ((int16_t)buf[18] >> 7 | ((int16_t)buf[19] << 1 ) | (int16_t)buf[20] << 9 ) & 0x07FF;SBUS_CH.CH15 = ((int16_t)buf[20] >> 2 | ((int16_t)buf[21] << 6 )) & 0x07FF;SBUS_CH.CH16 = ((int16_t)buf[21] >> 5 | ((int16_t)buf[22] << 3 )) & 0x07FF;return 1;}else {SBUS_CH.ConnectState = 0;return 0;}
}u16 sbus_to_pwm(u16 sbus_value)
{float pwm;pwm = (float)SBUS_TARGET_MIN + (float)(sbus_value - SBUS_RANGE_MIN) * SBUS_SCALE_FACTOR;//                1000                                   300              1000/1400if (pwm > 2000) pwm = 2000;if (pwm < 1000) pwm = 1000;return (u16)pwm;
}

上面定义了一个SBUS_CH_Struct 结构体类型的变量SBUS_CH,该结构体在sbus.h中定义

typedef struct
{uint16_t CH1;//通道1数值uint16_t CH2;//通道2数值uint16_t CH3;//通道3数值uint16_t CH4;//通道4数值uint16_t CH5;//通道5数值uint16_t CH6;//通道6数值uint16_t CH7;//通道7数值uint16_t CH8;//通道8数值uint16_t CH9;//通道9数值uint16_t CH10;//通道10数值uint16_t CH11;//通道11数值uint16_t CH12;//通道12数值uint16_t CH13;//通道13数值uint16_t CH14;//通道14数值uint16_t CH15;//通道15数值uint16_t CH16;//通道16数值uint8_t ConnectState;//遥控器与接收器连接状态 0=未连接,1=正常连接
}SBUS_CH_Struct;

u16 sbus_to_pwm(u16 sbus_value)很好理解了,就是把sbus的值转化为标准的1000-2000的pwm值,因为我用的遥控器sbus值是300-1700,大家用的时候具体数值到时候可以通过串口直接读出来看看。
这样就读出了16个通道的数据啦。同时通过读取ConnectState位判断遥控器的状态,在主函数中采取失控保护。


上面这段解析数据的代码是国际通用的,可以用在任何使用sbus协议的场合,可以很方便的移植到arduino、51、树莓派上面。

最后main函数里面就很简单了,只注意初始化串口设置为100K波特率。

void main()
{/* 省略 */uart1_init(100000);/* 省略 */
}

本文代码已上传至CSDN,独乐乐不如众乐乐,提供免费下载,点击下载,欢迎交流讨论。别忘了点个赞哦!

STM32解析SBUS信号例程详解相关推荐

  1. STM32 USB设备远程唤醒机制详解

    目录 1.USB Resume信号 2.USB远程唤醒的方式 3.J状态和K状态 4.STM32 USB设备远程唤醒机制详解 5.主机对设备远程唤醒功能状态的获取.清除和设置 1.USB Resume ...

  2. 进阶篇——树莓派OLED模块的使用 大量例程详解

    树莓派OLED模块的使用教程大量例程详解 #树莓派# 简介 Python有两个可以用的OLED库 [Adafruit_Python_SSD1306库]->只支持SSD1306 [Luma.ole ...

  3. python cv2 轮廓的包络 面积_Python 基于FIR实现Hilbert滤波器求信号包络详解

    在通信领域,可以通过希尔伯特变换求解解析信号,进而求解窄带信号的包络. 实现希尔伯特变换有两种方法,一种是对信号做FFT,单后只保留单边频谱,在做IFFT,我们称之为频域方法:另一种是基于FIR根据传 ...

  4. ISO7816协议深度解析-简单易懂协议详解(一)-- 复位,字符帧,及ATR

    1. 摘要 IC卡必须支持T=0或T=1的协议,但不是同时支持这两种协议,而终端则必须同时支持T=0和T=1的协议. • T=0通讯协议是异步半双工字符传输协议: • T=1通讯协议是异步半双工块传输 ...

  5. STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

    STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号 一. 问题描述 二. 方法一--使用HAL_UART_Receive_DMA 三. 方法二--使用HAL_UARTEx_Rece ...

  6. python3d动态图-Python图像处理之gif动态图的解析与合成操作详解

    本文实例讲述了Python图像处理之gif动态图的解析与合成操作.分享给大家供大家参考,具体如下: gif动态图是在现在已经司空见惯,朋友圈里也经常是一言不合就斗图.这里,就介绍下如何使用python ...

  7. STM32接口FSMC/FMC难点详解

    STM32接口FSMC/FMC难点详解 转载   http://blog.sina.com.cn/s/blog_808bca130102x94k.html STM32F767的FMC将外部存储器划分为 ...

  8. STM32之NVIC的深入详解

    朋友们,如果你需要在STM32上移植RTOS,那么首先必须深入理解它的中断系统.[转载]STM32之NVIC的深入详解 什么是NVIC?即嵌套向量中断控制器(Nested Vectored Inter ...

  9. Halcon例程详解(植物测量) —— measure_plant.hdev

    文章目录 前言 一.过程 1.1 筛选ROI区域 1.2 分割 1.3 三维建模与仿射变换 1.4 确定叶子的角度分布和高度 1.5 确定叶子的面积和树干的直径 1.6 对叶子的角度进行分析 二.例程 ...

  10. Halcon例程详解(基于卡尺工具的匹配测量方法) —— measure_stamping_part.hdev

    前言 1卡尺工具介绍 Halcon中的Metrology方法即为卡尺工具,可用来拟合线,圆,这种方法对于目标比背景很明显的图像尺寸测量是很方便的,不需要用blob进行边缘提取等,但缺点也很明显,需要目 ...

最新文章

  1. 怎么写遮罩层 css,css案例 - mask遮罩层的华丽写法
  2. 用数学方法构造神经网路的迭代次数1-9
  3. 计算机期末考试操作题简单,计算机期末考试操作题及答案计算机期末考试操作题及答案.doc...
  4. linux:gpg加密和解密
  5. MySQL的环境变量配置详细步骤
  6. iview vue 打包图标不显示_VueCLI3.0干货系列之集成iview
  7. MapReduce 学习指南
  8. java编程思想(注释文档)
  9. 【转】What is an entity system framework for game development?
  10. Rayman的绝顶之路——Leetcode每日一题打卡19
  11. xp计算机无法正常启动,Windows XP电脑开机出错无法正常启动的解决方法
  12. iOS 开发 申请299美金企业开发账号
  13. 感谢同事的临别赠言,愿自己一路顺风。
  14. unity3d的playmaker插件使用教程,五、进入区域改变平台颜色
  15. Android百度地图SDK:隐藏比例尺,隐藏百度LOGO,隐藏缩放控件
  16. 【日语口语词典学习】第0004页
  17. spring boot 2.0 redis 分布式锁
  18. 汇编:裴波那契数列前50项
  19. 帝国cms插件支持7.0/7.2 7.5/UTF-8 微信登入插件 一键登入
  20. [开发探索]知行合一

热门文章

  1. 是德科技N9020A 频谱分析仪技术资料说明
  2. java导论pdf下载,操作系统导论 PDF 下载
  3. 架构之美-读书笔记之二
  4. NOD32反病毒系统升级
  5. GBK 汉字编码转换
  6. java基于SSM房屋租赁管理系统
  7. Bcm96xx 系列芯片 SDK介绍(二)
  8. android实现应用商店开发,基于Android平台的应用商店客户端的设计与实现
  9. Unity开发游戏时可以用到的一些插件介绍
  10. javascript 常用插件库