当前位置: 首页 > 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()) {// 如果是…...

Vue入门学习笔记-表单

可以使用v-model 指令在表单控件元素上创建双向数据绑定。 引言&#xff1a; Vue采用了MVVM&#xff08;Model-View-ViewModel&#xff09;架构模式&#xff0c;通过指令可以快速实现数据和视图的双向绑定 修改视图层时&#xff0c;模型层也会改变&#xff1b;修改模型层&#…...

TCP通信三次握手、四次挥手

目录 前言 一、三次握手 TCP三次握手的详细过程 二、四次挥手 四次挥手的详细过程 前言 前面我说到了&#xff0c;UDP通信的实现&#xff0c;但我们经常说UDP通信不可靠&#xff0c;是因为他只会接收和发送&#xff0c;并不会去验证对方收到没有&#xff0c;那么我们说TCP通…...

【实施文档】软件项目实施方案(Doc原件2024实际项目)

软件实施方案 二、 项目介绍 三、 项目实施 四、 项目实施计划 五、 人员培训 六、 项目验收 七、 售后服务 八、 项目保障措施软件开发管理全套资料包清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&am…...

BeanFactory vs. ApplicationContext

在Spring框架中&#xff0c;BeanFactory和ApplicationContext都是用于管理Spring容器中的bean的接口&#xff0c;但它们在功能和应用场景上有所不同。下面是它们的主要区别&#xff1a; 1. 基础功能 vs. 扩展功能 BeanFactory: 是Spring框架的最基础的IoC容器&#xff0c;提供…...

JDBC客户端连接Starrocks 2.5

<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://ma…...

004——双向链表和循环链表

目录 双向链表 双向链表的初始化&#xff08;与单链表类似&#xff09; 增&#xff1a; Ⅰ&#xff09;头插法 Ⅱ&#xff09;尾插法 Ⅲ&#xff09;中间插入 删 改 查 整体代码示例&#xff1a; 循环链表 循环单链表 ​编辑 循环双链表 双向链表 不同于单链表&…...

framebuffer帧缓存

framebuffer:帧缓冲&#xff0c;帧缓存 Linux内核为显示提供的一套应用程序接口。&#xff08;驱动内核支持&#xff09; framebuffer本质上是一块显示缓存&#xff0c;往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。framebuffer驱动程序控制LCD显示设备&#xff0…...

24_竞赛中的高效并查集

菜鸟&#xff1a;老鸟&#xff0c;我最近在做一个与社交网络相关的项目&#xff0c;需要频繁地检查两个用户是否属于同一个群组。但我发现每次检查都很耗时&#xff0c;性能很差。你有什么建议吗&#xff1f; 老鸟&#xff1a;你可以试试使用并查集&#xff08;Union-Find&…...

新手c语言讲解及题目分享(十七)--运算符与表达式专项练习

本文主要讲解c语言的基础部分&#xff0c;运算符与表达式的学习&#xff0c;在这一部分中&#xff0c;往往有许多细节的东西需要去记住。当各种运算符一起用时&#xff0c;就会存在优先级的关系&#xff0c;本文末尾有各种运算符的优先级顺序表。 参考书目和推荐学习书目&#…...

香帅的金融学讲义:深入剖析与解读

香帅的金融学讲义&#xff1a;深入剖析与解读 金融学&#xff0c;这个看似高深复杂的学科&#xff0c;实则与我们的生活息息相关。从个人理财到国家宏观经济政策&#xff0c;金融学无处不在。那么&#xff0c;如何更好地理解金融学呢&#xff1f;今天&#xff0c;我们就来借助…...