SIYI AK28 遥控器接收机的SBUS口与STM32通讯

2023-05-16

SBUS介绍

SBUS是Futaba公司定义的一种串口通信协议,Futaba的产品应用越来越广泛,不论是航模,无人机,还是机器人,遥控车,总能有它的身影。SBUS是一个接收机串行总线输出,通过这根总线,可以获得遥控器上所有通道的数据。目前很多模型及无人机电子设备都支持SBUS总线的接入。使用SBUS总线获取通道数据,效率高的,而且节省硬件资源,只需要一根线即可获取所有通道的数据。
官网网址:

https://os.mbed.com/users/Digixx/notebook/futaba-s-bus-controlled-by-mbed/

硬件介绍

和TTL串口信号相比,sbus的逻辑电平是反的,并且是硬件取反,软件取反是无效的;硬件取反的电路图如下:
在这里插入图片描述

协议介绍

串口配置为波特率100kbps,8位数据,偶校验(even),2位停止位,无流控。
链接https://mbed.org/users/Digixx/notebook/futaba-s-bus-controlled-by-mbed/说明了S-bus帧格式。每帧25个字节,按照如下顺序排列:
[startbyte] [data1] [data2] … [data22] [flags][endbyte]
起始字节startbyte = 11110000b (0xF0),但实际上STM32(ARM核)收到的是0x0F。中间22个字节就是16个通道的数据了,为什么是16个通道?因为22x8=11x16,每个通道用11bit表示,范围是0-2047。波形图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本而言,data1为ch1的低8位,data2的低3位为ch1的高三位,data2的高5位是ch2的低5位,data3的低6位是ch2的高6位,以此类推,如下图所示:

在这里插入图片描述

代码介绍

sbus.c
            #include "sbus.h"
             ==说明:我所用的遥控器通过推动摇杆得到的最小值是193、中间值是993、最大值是1793==
			#define RC_CHANNEL_MIN      (-800)
			#define RC_CHANNEL_MAX      800
			#define SBUS_MIN_OFFSET     193
			#define SBUS_MID_OFFSET     993
			#define SBUS_MAX_OFFSET   1793
	/**
	 *@brief      这是一个C语言版的MAP函数(映射函数)
	 *@param  val:实际通道值; I_Min:输入最小值; I_Max:输入最大值;O_Min:输出最小值;O_Max:输出最大值
	 *@retval   实际输出值;
	 *@note    none
	 */
			int  output[16]={0};
			float map(float val, float I_Min, float I_Max, float O_Min, float O_Max)
			{
					return(((val-I_Min)*((O_Max-O_Min)/(I_Max-I_Min)))+O_Min);
			}
			/**
			  *@brief     协议转换
			  *@param  none
			  *@retval   none
			  *@note     none
	          */
			void  sbusPreparePacket(void)
			{
				uint16_t SBUS_channels[16]={0};
				if(Usart6_rx_buffer[0]==0x0f&& Usart6_rx_buffer[24]==0x00)    //校验收到的数据是否正确
			  {
			    SBUS_channels[0]  = (( Usart6_rx_buffer[1]| Usart6_rx_buffer[2]<<8)                     & 0x07FF);
			    SBUS_channels[1]  = (( Usart6_rx_buffer[2]>>3 | Usart6_rx_buffer[3]<<5)                 & 0x07FF);
			    SBUS_channels[2]  = (( Usart6_rx_buffer[3]>>6 | Usart6_rx_buffer[4]<<2 | Usart6_rx_buffer[5]<<10)  & 0x07FF);
			    SBUS_channels[3]  = (( Usart6_rx_buffer[5]>>1 | Usart6_rx_buffer[6]<<7)                 & 0x07FF);
			    SBUS_channels[4]  = (( Usart6_rx_buffer[6]>>4 | Usart6_rx_buffer[7]<<4)                 & 0x07FF);
			    SBUS_channels[5]  = (( Usart6_rx_buffer[7]>>7 | Usart6_rx_buffer[8]<<1 | Usart6_rx_buffer[9]<<9)   & 0x07FF) ;
			    SBUS_channels[6]  = (( Usart6_rx_buffer[9]>>2 | Usart6_rx_buffer[10]<<6)                & 0x07FF) ;
			    SBUS_channels[7]  = (( Usart6_rx_buffer[10]>>5| Usart6_rx_buffer[11]<<3)                & 0x07FF) ;
			    SBUS_channels[8]  = (( Usart6_rx_buffer[12]   | Usart6_rx_buffer[13]<<8)                & 0x07FF) ;
			    SBUS_channels[9]  = (( Usart6_rx_buffer[13]>>3| Usart6_rx_buffer[14]<<5)                & 0x07FF) ;
			    SBUS_channels[10] = (( Usart6_rx_buffer[14]>>6| Usart6_rx_buffer[15]<<2| Usart6_rx_buffer[16]<<10) & 0x07FF) ;
			    SBUS_channels[11] = (( Usart6_rx_buffer[16]>>1| Usart6_rx_buffer[17]<<7)                & 0x07FF) ;
			    SBUS_channels[12] = (( Usart6_rx_buffer[17]>>4| Usart6_rx_buffer[18]<<4)                & 0x07FF) ;
			    SBUS_channels[13] = (( Usart6_rx_buffer[18]>>7| Usart6_rx_buffer[19]<<1| Usart6_rx_buffer[20]<<9)  & 0x07FF) ;
			    SBUS_channels[14] = (( Usart6_rx_buffer[20]>>2| Usart6_rx_buffer[21]<<6)                & 0x07FF) ;
			    SBUS_channels[15] = (( Usart6_rx_buffer[21]>>5| Usart6_rx_buffer[22]<<3)                & 0x07FF) ;
			  }
			  else 
			  {
					SBUS_channels[2]=993;
				     SBUS_channels[3]=993;  
			   }
				for(char i=0;i<16;i++)
				{
					output[i]=map(SBUS_channels[i],SBUS_MIN_OFFSET,SBUS_MAX_OFFSET, RC_CHANNEL_MIN, RC_CHANNEL_MAX);   //具体到通道值
				}
			
			}
			
          /**
			  *@brief    输出PWM(混控)
			  *@param  offset_y:实际通道1的值;offset_x:实际通道2的值;c:给定常数
			  *@retval   none
			  *@note     none
	          */
			//应用到具体的通道  实现pwm输出
			//以通道3为y轴,通道4为x轴
			 int a,b, pwm1_channels[2]={0};
			void PWM_Out(int offset_y,int offset_x,float c )
			{	
			 
				sbusPreparePacket();
				if(offset_y>=0)
				{
					a=(c*offset_y*offset_y+800*offset_x)/(800+c*offset_y);  //电机1
			   	    b=(c*offset_y*offset_y-800*offset_x)/(800+c*offset_y);  //电机2
					pwm1_channels[0]=map(a,0,800,1500,2000);
					pwm1_channels[1]=map(b,0,800,1500,2000);
				}
			
				if(offset_y<0)
				{
					a=(1-2*0.25)*offset_y-0.25*(100+offset_x);
					b=(1-2*0.25)*offset_y-0.25*(100-offset_x);
					pwm1_channels[0]=map(a,-800,0,1000,1500);
					pwm1_channels[1]=map(b,-800,0,1000,1500);
				}
				
				pwm_out1(	pwm1_channels[0]);
				pwm_out2(	pwm1_channels[1]);
			} 
sbus.h
            #ifndef __SBUS_H
			#define __SBUS_H
			#include "main.h"
			#include "usart.h"
			#include "tim.h"
			#include <stdbool.h>
			extern int  output[16];
			#define pwm_out1(pwm)     __HAL_TIM_SET_COMPARE(&htim15,TIM_CHANNEL_1,pwm)
			#define pwm_out2(pwm)     __HAL_TIM_SET_COMPARE(&htim15,TIM_CHANNEL_2,pwm) 
			uint16_t PWM_OUT1(uint16_t pwm_channel);
			uint16_t PWM_OUT2(uint16_t pwm_channel);
			float map(float val, float I_Min, float I_Max, float O_Min, float O_Max);
			void  sbusPreparePacket(void);
			void GET_SBUSDATA(void);
			void sbus_control(void);
			void   PWM_Out(int offset_y,int offset_x,float c );
			#endif

完结

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SIYI AK28 遥控器接收机的SBUS口与STM32通讯 的相关文章

  • STM32 F072上的软件如何跳转到bootloader(DFU模式)?

    STM32应用笔记2606对此进行了讨论 但没有简单的代码示例 该答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行了测试 这个答案使用 STM32标准外设库 仅此而已 请注意 验证您是否成功进入引导加载程序模式
  • 当数据大小较小时,内存到内存 DMA 传输是否需要权衡?

    我正在学习 STM32 F4 微控制器 我正在尝试找出使用 DMA 的限制 根据我的理解和研究 我知道如果数据量较小 即设备使用DMA生成或消耗少量数据 则开销会增加 因为DMA传输需要DMA控制器执行操作 从而不必要地增加系统成本 我做了
  • 139-基于stm32单片机老人居家监护报警系统Proteus仿真+源程序

    资料编号 139 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 MQ4传感器 电位器模拟 MQ2传感器 电位器模拟 蜂鸣器 电机 制作一个基于stm32单片机老人居家监护报警系统Proteus仿真 2 通过MQ2传
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • [MM32硬件]搭建灵动微MM32G0001A6T的简易开发环境

    作为学习单片机的经典 自然是通过GPIO点亮LED 或者是响应按钮的外部中断例程 这我们看看SOP8封装的芯片MM32G0001A6T得引脚 除了VDD和GND固定外 我们可以使用PA14 PA1 PA13 PA15 PA2 PA3这六个G
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 最终启动顺序错误 - STM32L476 的 Eclipse System Workbench 调试

    我正在尝试调试和运行 STM32L476 的简单汇编代码 我已经设置了 Eclipse Oxygen 在 Eclipse 中安装了最新版本的 System Workbench 插件并安装了 ST Link 驱动程序 IDE 成功构建了程序
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • 库函数点亮Led

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • C++文件服务器项目—项目总结与反向代理—7

    C 43 43 文件服务器项目 项目总结与反向代理 7 1 项目总结2 项目提炼3 web服务器的反向代理4 存储节点的反向代理 组件介绍基本写完了 xff0c 后续进行深入 本专栏知识点是通过零声教育的线上课学习 xff0c 进行梳理总结
  • https相关内容

    https相关内容 前言基础概念理解https传输过程 前言 本文写https相关内容 xff0c 持续补充 基础概念理解 对称加密 加解密秘钥是同一个 非对称加密 公钥 私钥 sa gt 公钥私钥都是两个数字ecc gt 椭圆曲线 两个点
  • TinyKv介绍

    TinyKv介绍 前言tinykv架构代码结构如何去写TinyKv参考内容 前言 开一个新坑 xff0c 将tinykv的4个project全部实现 虽然今天我点进去看的时候就萌生退意 好在没有放弃之前 xff0c 把project1完成了
  • TinyKv Project1 Standalone KV

    TinyKv Project1 Standalone KV 前言Project1 StandaloneKV 文档翻译文档的重点内容StandAloneStorageWriteReader Server单元测试 前言 project1还是比较
  • TinyKv Project2 PartA RaftKV

    TinyKv Project2a RaftKV 前言Project2 RaftKV 文档翻译Project2A重点内容抛出RaftLogRaftLog结构体字段详解RaftLog核心函数详解 RaftRaft 驱动规则Msg的作用与含义Ms
  • TinyKv Project2 PartB RaftKV

    TinyKv Project2 PartB RaftKV 前言Project2 PartB RaftKV 文档翻译PartB 到底想让我们做什么 xff1f 分析要实现的函数到底要干什么事情proposeRaftCommand 将上层命令打
  • TinyKv Project2 PartC RaftKV

    TinyKv Project2 PartC RaftKV 前言Project2 PartC RaftKV 文档翻译raft节点如何自动的compact压缩自己的entries日志生成快照与快照收收发日志压缩与快照收发总结疑难杂症 前言 pr
  • TinyKv Project3 PartA Multi-raft KV

    TinyKv Project3 PartA Multi raft KV 前言Project3 PartA Multi raft KV 文档翻译Add RemoveLeaderTransfer 前言 Project3是整个项目最难的部分 xf
  • TinyKv Project3 PartB Multi-raft KV

    TinyKv Project3 PartB Multi raft KV 前言Project3 PartB Multi raft KV 文档翻译发送请求LeaderTransfer 禅让ConfChange 集群成员变更Split regio
  • TinyKv Project3 PartC Multi-raft KV

    TinyKv Project3 PartC Multi raft KV 前言Project3 PartC Multi raft KV 文档翻译processRegionHeartbeatSchedule 前言 3C要求我们实现调度 3c按照
  • nodejs api学习:fs.createReadStreame()

    作用 这个api的作用是打开一个可读的文件流并且返回一个fs ReadStream对象 参数 createReadStream path option 该用来打开一个可读的文件流 xff0c 它返回一个fs ReadStream对象 64
  • TinyKv Project4 Transactions

    TinyKv Project4 Transactions 前言Project4 Transactions 文档翻译Project 4 TransactionsTinyKV中的事务Part APart BPart C Percolator x
  • sealos issue #2157 debug 思路流程记录

    sealos issues 2157 debug思路流程 前言分析issue剖析源码解决方案总结 前言 这个项目蛮有意思的 xff0c sealos 是以 kubernetes 为内核的云操作系统发行版 boss上看到 gt 沟通 gt 解
  • 系统设计场景题—MySQL使用InnoDB,通过二级索引查第K大的数,时间复杂度是多少?

    系统设计场景题 MySQL使用InnoDB xff0c 通过二级索引查第K大的数 xff0c 时间复杂度是多少 xff1f 前言明确场景对齐表的结构分析时间复杂度执行一条 select 语句 xff0c 期间发生了什么 xff1f 分析性能
  • 《嵌入式系统》 |(四) STM32软件架构 知识梳理

    系列索引 嵌入式系统 嵌入式系统 重点知识梳理 目录 CMSIS软件架构库文件说明 CMSIS软件架构 CMSIS概述 CMSIS软件架构由四层 xff1a 用户应用层 操作系统及中间件接口层 CMSIS层和硬件层 由三部分构成 核内外设访
  • Cmake链接第三方库的三种方法

    Cmake链接第三方库的三种方法 本文介绍链接第三方库的3种方法 以OpenBLAS举例 使用的工程名称为Test lib xff08 可执行文件名字 xff09 xff0c 主程序为library c 代码中的各路径请自行替代 xff1a
  • SADP功能使用

    SADP主要使用的是链路层多播及UDP多播的原理进行实现的 1 链路层多播 span class token function socket span span class token punctuation span PF PACKET
  • MatlabR2022b + Visual Studio环境配置

    在Matlab中输入 mex setup c 43 43 命令确认MEX使用VS2022编译环境 VC 43 43 目录 包含目录 添加 D Matlab2022b extern include VC 43 43 目录 库目录 添加 D M
  • ROS小车自主导航

    在进行ROS小车自主导航时 xff0c 需要用到三维可视化软件rviz xff0c 然而出现了问题 问题 xff1a 在运行rosrun rviz rviz xff0c 导入自己导航的程序后 xff0c 需要通过2D Pose Estima
  • SIYI AK28 遥控器接收机的SBUS口与STM32通讯

    SBUS介绍 SBUS是Futaba公司定义的一种串口通信协议 xff0c Futaba的产品应用越来越广泛 xff0c 不论是航模 xff0c 无人机 xff0c 还是机器人 xff0c 遥控车 xff0c 总能有它的身影 SBUS是一个