当前位置: 首页 > news >正文

基于无人机边沿相关 ------- IBUS、SBUS协议和PPM信号

文章目录

  • 一、IBUS协议
  • 二、SBUS协议
  • 三、PPM信号


一、IBUS协议

IBUS(Intelligent Bus)是一种用于电子设备之间通信的协议,采用串行通信方式,允许多设备通过单一数据线通信,较低延迟,支持多主机和从机结构,常用于遥控器与天空端之间,富斯官网已公开协议,协议格式如下可见:
在这里插入图片描述
一共32字节,2 字节帧头+28字节数据位 + 2字节校验位组成

解码如下:

#define IBUS_USER_CHANNELS		10		
#define IBUS_LENGTH				0x20	
#define IBUS_COMMAND40			0x40	
#define IBUS_MAX_CHANNLES		14uint8_t rx_buffer[32] = {0};
uint16_t channel[IBUS_USER_CHANNELS] = {0};
uint16_t checksum_cal, checksum_ibus;void IBUS_READ_CHANNEL(uint8_t user_channels)
{uint16_t channel_buffer[IBUS_MAX_CHANNLES] = {0};if(rx_buffer[0] == IBUS_LENGTH && rx_buffer[1] == IBUS_COMMAND40){checksum_cal = 0xffff - rx_buffer[0] - rx_buffer[1];for(int i = 0; i < IBUS_MAX_CHANNLES; i++){channel_buffer[i] = (uint16_t)(rx_buffer[i * 2 + 3] << 8 | rx_buffer[i * 2 + 2]);checksum_cal = checksum_cal - rx_buffer[i * 2 + 3] - rx_buffer[i * 2 + 2];}checksum_ibus = rx_buffer[31] << 8 | rx_buffer[30];if(checksum_cal == checksum_ibus){for(int j = 0; j < user_channels; j++){channel[j] = channel_buffer[j];}}}HAL_UART_Receive_IT(IBUS_UART, rx_buffer, 32);
}

二、SBUS协议

SBUS(Serial Bus)也是一种用于遥控模型、无人机和其他应用程序中的串行通信协议,特别是在飞控系统和遥控设备之间,以实现高效的数据传输。

采用串行通信,单线信号传输,支持最多16个通道的控制,实时性强,可反向兼容PWM,设计考虑冗余性。

协议格式共有25字节数据,由首部(1字节)+ 数据(22字节)+ 标志位(1字节)+ 结束符(1字节)组成

  • 帧头: 0x0F
  • 数据: 22 字节的数据,分别代表16个通道的数据,也即是每个通道的值用了 11 位来表示,22x8/16 = 11,每个通道的取值范围为 0~2047,低位在前、高位在后
  • 标志位: 1字节,高四位从高到低依次表示:
    bit7:CH17数字通道
    bit6:CH16数字通道
    bit5:帧丢失(Frame lost)
    bit4:安全保护(Failsafe):失控保护激活位(0x10)判断飞机是否失控
    bit3~bit0:低四位不用
  • 结束符: 0x00

通道解析:
在这里插入图片描述
解码如下:

#define USART_BUF_SIZE      8       
#define SBUS_DATA_SIZE      25      
struct SBUS_t{uint8_t head;                   // 1字节帧头uint16_t ch[16];                // 16个通道数据uint8_t flag;                   // 1字节标志位uint8_t end;                    // 1字节结束
};uint8_t usart_buf[USART_BUF_SIZE];
uint8_t sbus_rx_head = 0;               // 发现起始字节 0x0F
uint8_t sbus_rx_sta = 0;                // sbus 接收状态,0:未完成,1:已完成一帧接收
uint8_t sbus_rx_index;                  // 接收字节计数
uint8_t sbus_rx_buf[SBUS_DATA_SIZE];    // 接收sbus数据缓冲区struct SBUS_t sbus;                     // SBUS 结构体实例化void USART2_IRQHandler(void)                                            //中断函数
{uint8_t chr;if ((__HAL_UART_GET_FLAG(&UART2_Handler, UART_FLAG_RXNE) != RESET)) // 接收中断{HAL_UART_Receive(&UART2_Handler, &chr, 1, 1000);                // 接收一个字符if (sbus_rx_sta == 0)                                           // 接收未完成{if ((chr == 0x0F) || sbus_rx_head)                          // 找到首字节或已经找到首字节{sbus_rx_head = 1;                                       // 标明已经找到首字母if (sbus_rx_index < SBUS_DATA_SIZE)                     // 未接收到25个字符{sbus_rx_buf[sbus_rx_index] = chr;                   // 不断接收sbus_rx_index ++;}else                                                    // 接收到25个字符了{sbus_rx_sta = 1;                                    // 接收完成sbus_rx_head = 0;                                   // 清零,准备下一次接收sbus_rx_index = 0;}}}}HAL_UART_IRQHandler(&UART2_Handler);
}/* 对SBUS协议数据进行解析                                                      */
/* 实现对S.BUS协议缓存,头部为 0x0F,结尾为 0x00, 中间22Bytes16通道数据,1Byte标志符 */
void SbusParseTask(void *arg)
{while (1){if(sbus_rx_sta==1)                          // 接收完一帧{NVIC_DisableIRQ(USART2_IRQn);           // 要关闭中断,防止读写混乱sbus.head = sbus_rx_buf[0];             // 首部sbus.flag = sbus_rx_buf[23];            // 标志符sbus.end  = sbus_rx_buf[24];            // 结尾sbus.ch[0] =((sbus_rx_buf[2]<<8)  + (sbus_rx_buf[1])) & 0x07ff;          sbus.ch[1] =((sbus_rx_buf[3]<<5)  + (sbus_rx_buf[2]>>3)) & 0x07ff;sbus.ch[2] =((sbus_rx_buf[5]<<10) + (sbus_rx_buf[4]<<2) + (sbus_rx_buf[3]>>6)) & 0x07ff;sbus.ch[3] =((sbus_rx_buf[6]<<7)  + (sbus_rx_buf[5]>>1)) & 0x07ff;sbus.ch[4] =((sbus_rx_buf[7]<<4)  + (sbus_rx_buf[6]>>4)) & 0x07ff;sbus.ch[5] =((sbus_rx_buf[9]<<9)  + (sbus_rx_buf[8]<<1) + (sbus_rx_buf[7]>>7)) & 0x07ff;  sbus.ch[6] =((sbus_rx_buf[10]<<6) + (sbus_rx_buf[9]>>2)) & 0x07ff;sbus.ch[7] =((sbus_rx_buf[11]<<3) + (sbus_rx_buf[10]>>5)) & 0x07ff;sbus.ch[8] =((sbus_rx_buf[13]<<8)  + sbus_rx_buf[12]) & 0x07ff;sbus.ch[9] =((sbus_rx_buf[14]<<5)  + (sbus_rx_buf[13]>>3)) & 0x07ff;sbus.ch[10]=((sbus_rx_buf[16]<<10) + (sbus_rx_buf[15]<<2) + (sbus_rx_buf[14]>>6)) & 0x07ff;sbus.ch[11]=((sbus_rx_buf[17]<<7)  + (sbus_rx_buf[16]>>1)) & 0x07ff;sbus.ch[12]=((sbus_rx_buf[18]<<4)  + (sbus_rx_buf[17]>>4)) & 0x07ff;sbus.ch[13]=((sbus_rx_buf[20]<<9)  + (sbus_rx_buf[19]<<1) + (sbus_rx_buf[18]>>7)) & 0x07ff;sbus.ch[14]=((sbus_rx_buf[21]<<6) + (sbus_rx_buf[20]>>2)) & 0x07ff;sbus.ch[15]=((sbus_rx_buf[22]<<3) + (sbus_rx_buf[21]>>5)) & 0x07ff;delay_ms(500);                          // 先做完延时再开启中断与下一次捕获,否则延时期间中断到来,没有达到预期效果NVIC_EnableIRQ(USART2_IRQn);            // 打开串口中断sbus_rx_sta = 0;                        // 准备下一次接收   }else{delay_ms(500);                          // 免得异常时,到此处使得低优先级任务无法执行}}
}

三、PPM信号

PPM(Pulse Position Modulation,脉冲位置调制)信号是一种用于传输控制信号的调制方式,尤其在遥控系统中非常常见。PPM信号通过改变脉冲在时间上的位置来代表不同的信息,在遥控模型、无人机和一些工业控制系统中被广泛应用。

采用串行通信,信号频率只有50Hz,略逊于ibus和sbus,对于一些高精度仪器不可用。

这里提一下,PWM表示脉冲宽度调制,也就是高电平维持的时间,而PPM实质上就是将多个通道的PWM放到“一根线”上进行传输,一个完整的PPM信号帧包含了多个通道的PWM值。
在这里插入图片描述
PPM信号一帧数据分为低电平(0.5ms)+高电平(0.5ms-1.5ms),高电平长度与PWM占空比成正比。因为一帧信号最多要2ms,信号周期为20ms,所以理论一次PPM信号可以发送10帧数据,但是由于要确定帧头信号,所以要加入同步帧,真正的PPM信号里面最多有9帧数据帧。

解析方式:①外部中断 ②定时器输入捕获

考虑安全条件下,建议使用定时器输入捕获方式进行解码,具体解码参考如下:

uint16_t PPM_Sample_Cnt=0;
uint32_t PPM_Time=0;
uint16_t PPM_Okay=0;
uint16_t PPM_Databuf[8]={0};   //PPM信号存储
uint8_t TIM2_CH2_CAPTURE_STA=0;void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_CC2)==!RESET)//捕获中断{if(TIM2_CH2_CAPTURE_STA&0x01)//符合条件的话说明上次捕获了高电平,那么这次捕获的一定是低电平{PPM_Time=TIM_GetCapture2(TIM2);if(PPM_Time>0)PPM_Time++;			if(PPM_Okay==1){PPM_Databuf[PPM_Sample_Cnt]=PPM_Time;PPM_Sample_Cnt++;if(PPM_Sample_Cnt>8)PPM_Okay=0;}if(PPM_Time>7000)//识别到帧尾{PPM_Okay=1;PPM_Sample_Cnt=0;}    TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising);TIM2_CH2_CAPTURE_STA=0;//清掉标志位准备开始下一次上升沿和下降沿检测}else{TIM_SetCounter(TIM2,0);//以上为清零            TIM2_CH2_CAPTURE_STA|=0x01;//高电平指示被赋值TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //当捕获上升沿后改为捕获下降沿}        }TIM_ClearITPendingBit(TIM2, TIM_IT_CC2|TIM_IT_Update); //清除中断标志位,一定不要忘,要不然下次进不了中断    
}

相关文章:

基于无人机边沿相关 ------- IBUS、SBUS协议和PPM信号

文章目录 一、IBUS协议二、SBUS协议三、PPM信号 一、IBUS协议 IBUS&#xff08;Intelligent Bus&#xff09;是一种用于电子设备之间通信的协议&#xff0c;采用串行通信方式&#xff0c;允许多设备通过单一数据线通信&#xff0c;较低延迟&#xff0c;支持多主机和从机结构&a…...

django学习入门系列之第十点《A 案例: 员工管理系统4》

文章目录 6 部门管理&#xff08;原始方式&#xff09;6.6 添加界面的导入&#xff08;数据库&#xff09;6.7 删除按键的应用6.8 编辑按键的应用6.81 传值的另一种方式 6.9 提交按键的应用 往期回顾 6 部门管理&#xff08;原始方式&#xff09; 6.6 添加界面的导入&#xff…...

【2024】Math-Shepherd:无需人工注释即可逐步验证和强化法学硕士。

搜索词&#xff1a; Math-shepherd: Verify and reinforce llms step-by-step without human annotations P Wang, L Li, Z Shao, R Xu, D Dai, Y Li, D Chen, Y Wu, Z Sui Proceedings of the 62nd Annual Meeting of the Association for …, 2024•aclanthology.org 摘要…...

[苍穹外卖]-08微信支付详解

地址簿管理 分析需求: 查询地址列表/新增地址/修改地址/删除地址/设置默认地址/查询默认地址 接口设计 新增地址接口 查询用户所有的地址接口 查询默认地址接口 根据id修改地址接口 根据id删除地址接口 根据id查询地址接口 设置默认地址接口 数据库设计: 收货地址簿(address_…...

教你五句在酒桌上和领导说的话语

1、今天很荣幸能和领导一起吃饭&#xff0c;我敬领导一杯希望领导工作顺利身体健康!生意兴隆!2、我敬领导一杯感谢领导平时对我的关照先干为敬!3、谢谢领导这次给我这个机会我一定会好好把握的请领导放心我一定会好好工作绝对不辜负领导对我的期望4.领导能来这里我们感到非常骄…...

景联文科技:专业图像采集服务,助力智能图像分析

景联文科技是专业数据服务公司&#xff0c;致力于为人工智能企业提供从数据采集、清洗到标注的全流程解决方案。协助客户解决AI开发过程中数据处理环节的关键问题&#xff0c;助力企业实现智能化转型。 1.多样化的图像采集服务 景联文科技提供多样化的图像采集服务&#xff0c…...

QT QTcpSocket作为客户端

前言 QTcpSocket是Qt提供的关于TCP网络通信的类。QTcpSocket是一个异步的类&#xff0c;能够非阻塞式发送和接收数据。QTcpSocket内部封装了网络通信相关细节&#xff0c;对外提供便利的接口去帮助开发人员实现简历连接、断开连接、数据收发。 主要内容 基本使用方式 项目文…...

【系统架构设计师-2023年】综合知识-答案及详解

更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【第1~2题】【第3题】【第4~5题】【第6题】【第7题】【第8题】【第9题】【第10~11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第21~22题】【第23题】【第24~…...

树莓派3B点灯(1)-- 四种方法

先做个简单一丢丢的吧。。。正好最近工作也要用这个。这次直接给够四种方法&#xff0c;给好给满。分别是Python点&#xff0c;用户空间配置GPIO点&#xff0c;设备树配置内核Leds驱动点&#xff0c;自己写驱动点。 用的板子是树莓派3B&#xff0c;GPIO 26口&#xff0c;蓝光L…...

Android解析XML格式数据

文章目录 Android解析XML格式数据搭建Web服务器Pull解析方式SAX解析方式 Android解析XML格式数据 通常情况下&#xff0c;每个需要访问网络的应用程序都会有一个自己的服务器&#xff0c;我们可以向服务器提交数据&#xff0c;也可以从服务器上获取数据。不过这个时候就出现了…...

数学建模笔记—— 灰色关联分析[GRA]

数学建模笔记—— 灰色关联分析[GRA] 灰色关联分析(GRA)1. 相关概念1.1 灰色系统1.2 什么是关联分析&#xff1f;1.3 灰色关联分析 2. 关联分析步骤3. 典型例题3.1 关联分析例题3.2 灰色关联综合评价 4. python代码实现4.1 关联分析4.2 灰色关联综合评价 灰色关联分析(GRA) 1.…...

ICM20948 DMP代码详解(13)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;12&#xff09; 上一回完成了对inv_icm20948_set_chip_to_body_axis_quaternion函数第2步即inv_rotation_to_quaternion函数的解析。回到inv_icm20948_set_chip_to_body_axis_quaternion中来&#xff0c;继续往下进行…...

【论软件需求获取方法及其应用】

摘要 2023 年 3 月&#xff0c;我所在的公司承接了某油企智慧加油站平台的建设工作。该项目旨在帮助加油站提升运营效率、降低运营成本和提高销售额。我在该项目中担任系统架构设计师&#xff0c;负责整个项目的架构设计工作。 本文以该项目为例&#xff0c;详细论述软件需求获…...

使用ESP8266和OLED屏幕实现一个小型电脑性能监控

前言 最近大扫除&#xff0c;发现自己还有几个ESP8266MCU和一个0.96寸的oled小屏幕。又想起最近一直想要买一个屏幕作为性能监控&#xff0c;随机开始自己diy。 硬件&#xff1a; ESP8266 MUColed小屏幕杜邦线可以传输数据的数据线 环境 Windows系统Qt6Arduino Arduino 库…...

Nexpose v6.6.266 for Linux Windows - 漏洞扫描

Nexpose v6.6.266 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Aug 21, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.o…...

ess6新特性

1、let、const 块级作用域声明变量和常量 2、箭头函数 不能构建函数 不能new 没.prototype属性 没有this指向 this指向是根据上下文的 往上层查找 没有arguments(参数) 3、模板字符串 ${} 字符串中嵌入表达式 4、解构赋值 5、Promise 处理异步操作的标准机制 6、for of 遍历…...

C语言蓝桥杯:语言基础

竞赛常用库函数 最值查询 min_element和max_element在vector(迭代器的使用) nth_element函数的使用 例题lanqiao OJ 497成绩分析 第一种用min_element和max_element函数的写法 第二种用min和max的写法 二分查找 二分查找只能对数组操作 binary_search函数&#xff0c;用于查找…...

axure之变量

一、设置我们的第一个变量 1、点击axure上方设置一个全局变量a 3 2、加入按钮、文本框元件点击按钮文档框展示变量值。 交互选择【单击时】【设置文本】再点击函数。 点击插入变量和函数直接选择刚刚定义的全局变量&#xff0c;也可以直接手动写入函数(注意写入格式。) 这…...

vue缓存用法

Store 临时缓存 特点&#xff1a;需要定义&#xff0c;有初始值、响应式、全局使用、刷新重置 Pinia官方文档 https://pinia.vuejs.org 创建 store 缓存 示例代码 import {defineStore} from pinia import {store} from //storeexport const useMyStore defineStore({// 定义…...

栈入门,括号匹配问题

利用栈这道题应该很轻松可以解决&#xff0c;下面给出常用的代码&#xff1a; public static boolean isValid(String s) {// 创建一个栈来保存左括号Stack<Character> stack new Stack<>();// 遍历字符串中的每个字符for (char c : s.toCharArray()) {// 如果是…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...