SBUS协议介绍和标准例程

这篇具有很好参考价值的文章主要介绍了SBUS协议介绍和标准例程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. SBUS信号简介

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

1.硬件标准

  • TTL电平即3.3V。 使用负逻辑,即低电平为“1”,高电平为“0”。
  • 波特率:100000(100k)
  • 负逻辑必须加硬件反相器

硬件反相器电路如下:

sbus协议,机器人or飞控通用,单片机,stm32,嵌入式硬件,开源协议

2.软件标准

1.串口配置:

100k波特率,8位数据位(stm32-选择9位),2位停止位,偶校验(EVEN),无控流,25个字节。

2.协议格式:

接收器和遥控器支持多少个通道就有多少个

[startbyte] [data1] [data2] [data10] [flags] [endbyte]
0xf0(起始字节) Flags 0x00

每个通道数据占 11bit (低位在前一字节、高位在后一字节)

3.数据范围

航模遥控器输出的PWM值是1000~2000,中值为1500,sbus输出的会不一样,每个遥控器厂家各有不同。

注意Sbus 速率比较快,且满速传输。容易产生串口ORE错误,例程中有解决方法

参考这篇文章:STM32常见错误-持续更新

4、间隔问题

它分两种模式(高速模式和普通模式)
高速模式:每隔7ms一帧数据,因为两帧的间隔只有超过3ms,才会被接受;而根据波特率计算一下,发送25字节需要的时间+3~4ms=7ms
普通模式:每隔14ms一帧数

据;

2. STM32F4_Sbus (DMA+串口 )

(1) 串口配置

void uart4_sbus_init(void)//串口2初始化
{
    NVIC_InitTypeDef NVIC_InitStructure ;//定义中断结构体
    GPIO_InitTypeDef GPIO_InitStructure;//定义IO初始化结构体
    USART_InitTypeDef USART_InitStructure;//定义串口结构体

    //设置IO口和串口4时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);//打开串口对应的外设时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

    GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4); //GPIOC10复用为UART4
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_UART4); //GPIOC10复用为UART4

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //管脚指定
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	 //管脚模式:输出口
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	    //类型:推挽模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	 //上拉下拉设置
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
    // 1 初始化串口及参数指定
    USART_InitStructure.USART_WordLength = USART_WordLength_9b;//9位数据位
    USART_InitStructure.USART_StopBits = USART_StopBits_2;//两位停止位
    USART_InitStructure.USART_Parity = USART_Parity_Even;//偶校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无控流
    USART_InitStructure.USART_Mode = USART_Mode_Rx;
    USART_InitStructure.USART_BaudRate = 100000;
    USART_Init(UART4, &USART_InitStructure);
    // 2 配置中断优先级并使能
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;               //通道设置为串口中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;       //中断占先等级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;              //中断响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断
    NVIC_Init(&NVIC_InitStructure);


    // 3 配置进入中断方式
    USART_ITConfig(UART4, USART_IT_IDLE, ENABLE); //接收到一帧数据就进入中断
    USART_ITConfig(UART4, USART_IT_ERR, ENABLE);

    // 4 使能串口的DMA接收
    USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);

    // 5 开启串口
    USART_Cmd(UART4, ENABLE);
}

(2) 串口中断接收

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

void UART4_IRQHandler(void) //串口2中断服务函数
{
    if (USART_GetFlagStatus(UART4, USART_FLAG_FE) != RESET) 
	{
        watch_usart4_fe_cnt++;
        
		USART_ReceiveData(UART4); 
		USART_ClearFlag(UART4, USART_FLAG_FE);
	}
	if(USART_GetFlagStatus(UART4, USART_FLAG_PE) != RESET)         
	{
        watch_usart4_pe_cnt++;
        
		USART_ReceiveData(UART4);  
		USART_ClearFlag(UART4, USART_FLAG_PE);  			  
	}	
	UART4_IRQHandler_cnt++;
	// USART_FLAG_ORE
	
	if(USART_GetFlagStatus(UART4, USART_FLAG_ORE) != RESET)
    {
        watch_usart4_ore_cnt++;
        USART_ReceiveData(UART4);
    }
	
    int i = 0;
    if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)  //接收中断,若为1则表示已经接收到数据
    {
        //先读SR,再读DR,清除IDLE中断标志
        i = UART4->SR;                                                        //读SR寄存器
        i = UART4->DR;
        DMA_Cmd(DMA1_Stream2, DISABLE);
        rx_len = sbus_data_len - DMA_GetCurrDataCounter(DMA1_Stream2);
        if(rx_len != 0 && rec_sbus_data[0] == 0x0f) //判断数据长度并丢掉无用数据
        {
            for(i = 0; i < rx_len; i++)
            {
                sbus_data[i] = 0;
            }
            for(i = 0; i < rx_len; i++)
            {
                get_sbus_data(rec_sbus_data);//保存接收到的数据
            }
            for(i = 0; i < rx_len; i++)                                          //将数据缓存区清零
            {
                rec_sbus_data[i] = 0; //清空缓存
            }
        }
        DMA_ClearFlag(DMA1_Stream2, DMA_FLAG_TCIF2 );
        DMA_SetCurrDataCounter(DMA1_Stream2, sbus_data_len);                       //设置DMA接收单元的长度
        DMA_Cmd(DMA1_Stream2, ENABLE);                                         //打开DMA
    }
}

(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;
    }
}


上面定义了一个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;

(4) DMA初始化


void DMA1_SBUS_Init(void)
{
    DMA_InitTypeDef DMA_InitStructure;//定义DMA结构体
    //启动DMA时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);//DMA通道配置
    //DMA通道配置
    DMA_DeInit(DMA1_Stream2);
    while (DMA_GetCmdStatus(DMA1_Stream2) != DISABLE);
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&UART4->DR);//外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rec_sbus_data;//内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//dma传输方向
    DMA_InitStructure.DMA_BufferSize = sbus_data_len;//设置DMA在传输时缓冲区的长度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA的外设一个外设
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//设置DMA的内存递增模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存数据字长
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//设置DMA的传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;//设置DMA的优先级别
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
    //配置DMA2的通道
    DMA_Init(DMA1_Stream2, &DMA_InitStructure);
    //使能DMA通道
    DMA_Cmd(DMA1_Stream2, ENABLE);
}

参考:振华OPPO文章来源地址https://www.toymoban.com/news/detail-516886.html

到了这里,关于SBUS协议介绍和标准例程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OPCUA 行业配套标准:机器人

             OPC UA 定义了对象,对象类型,结构化组织能力和定义对象之间关系的能力,利用这些基础和衍生类型及对象,用户还可以搭建出更复杂的类型,关系和对象。 如果不同的厂商或者用户定义的信息模型不同,将会影响系统的互操作性,对于设备而言,如果采用统一

    2024年02月05日
    浏览(42)
  • STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

    能够点进这篇文章的小伙伴肯定是对STM32串口DMA空闲中断接收数据感兴趣的啦,今天用这一功能实现串口解析航模遥控器sbus信号时,查阅了很多网友发布的文章(勤劳的搬运工~),包括自己之前写过一篇博客 STM32_HAL库_CubeMx串口DMA通信(DMA发送+DMA空闲接收不定长数据)。本文

    2024年02月09日
    浏览(64)
  • ROS的机器人协议:实现机器人之间的有效通信

    作者:禅与计算机程序设计艺术 ROS(Robot Operating System)是一个开源的机器人操作系统,其功能主要包括以下几个方面: 消息传递:ROS通过消息传递的方式进行通信,各个节点之间可以通过发布、订阅等方式互相通讯。 资源管理:ROS可以对进程、线程、资源进行管理,使得不

    2024年02月06日
    浏览(43)
  • 机器人修正DH参数(MDH)和标准DH(SDH)参数

    1.1.1 连杆坐标系定义 (a) 运动链中间位置连杆坐标系{ i {i} i }的定义 固连在连杆i上的固连坐标系称为坐标系{ i i i } O i O_i O i ​ 原点:关节轴i和i+1的交点或关节轴i和i+1公垂线与关节轴i的交点 Z ^ i hat{Z}_i Z ^ i ​ 轴:关节轴 i i i X ^ i hat{X}_i X ^ i ​ 轴:沿 Z ^ i hat{Z}_i Z ^ i ​

    2024年03月14日
    浏览(52)
  • 青少年机器人技术一级核心知识点、水平要求和考试标准

    青少年机器人技术的发展已成为当今世界科技领域中备受瞩目的一项技术。机器人技术的应用范围越来越广泛,不仅在工业制造、医疗、教育等领域中得到广泛应用,同时也成为了青少年学习STEM(科学、技术、工程、数学)的重要内容。 为了推动青少年机器人技术的发展,

    2024年02月12日
    浏览(46)
  • 【对话机器人】开源机器人项目介绍

    目录 1. 闲聊机器人介绍 2. 青云客平台 3. 思知项目 闲聊机器人是一种基于人工智能和自然语言处理技术的智能对话系统,旨在模拟人类的语言交流能力,与用户进行自然、连贯的对话。闲聊机器人能够理解用户的问题或指令,通过分析和处理文本,生成符合语法和语义规则的

    2024年02月11日
    浏览(53)
  • 如何保障医疗机器人的功能与安全?这几条编码标准你一定要了解

    在医疗物联网(IoMT)、机器学习(ML)和人工智能(AI)的推动下,医疗机器人和医疗技术正在飞速进步,随之而来的是侵入性更少的手术、更准确的诊断和更个性化的治疗选择,为患者带来了更多的可能性。 但是,这些所有的创新都离不开软件,而软件带来了更多的安全防

    2024年02月08日
    浏览(46)
  • 一文详解机器人标准D-H参数与改进型D-H参数

    关节角:绕轴,旋转到的角度; 偏置距离:沿轴,移动到的距离; 连杆长度:从轴,移动到的距离; 连杆扭角:绕轴,旋转到的角度;  1、坐标系的建立 对于连杆i - 1,首先将连杆i - 1的远端轴线(即关节轴i)作为轴,关节轴i - 1与i轴的公垂线作为轴,右手定则确定轴。

    2024年02月01日
    浏览(32)
  • 云深处绝影四足机器人协议学习解析

    本学习文档介绍了云深处 绝影X20 四足机器人的通信协议,并对相关的通信机制和命令格式进行了简单的解析。该协议在机器人系统和上位机(例如外部板卡或系统)之间进行TCP通信时使用。 在此协议中, 机器人本体 作为 TCP服务端 , 上位机 作为 TCP客户端 。协议的TCP服务

    2024年02月13日
    浏览(39)
  • 【机器人状态估计】粒子滤波算法介绍

    问题分类:位姿追踪、局部定位、全局定位;静态、动态环境定位;单一机器人定位、多机器人定位。 贝叶斯滤波框架: 定位置信度与运动模型卷积,两次独立估计值的整合比单一估计值使系统状态确定性更高。 基本思路 随机产生M个粒子(如M=1000),每个粒子表示状态变

    2024年02月22日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包