当前位置 博文首页 > 振华OPPO的博客世界:不清楚SBUS,这份SBUS协议详解请收藏

    振华OPPO的博客世界:不清楚SBUS,这份SBUS协议详解请收藏

    作者:[db:作者] 时间:2021-08-15 16:27

    1、简介

    SBUS,全称Serial Bus,即串行通信总线。本质上是一种串口通信协议,采用100K的波特率,8位数据位,2位停止位,偶效验,即8E2的串口通信。

    2、串口配置

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

    3、协议格式

    [startbyte] [data1][data2]…[data22][flags][endbyte]

    startbyte=0x0f;
    endbyte=0x00;

    flags标志位是用来检测控制器与px4是否断开的标志位:
    flags=1:控制器与接收器保持连接;
    flags=0:控制器与接收器断开(失控),px4会控制电机停转。

    data1…data22:对应16个通道(ch1-ch16),每个通道11bit(22X8=16X11=176)
    数据范围在0-2047之间,基本上是282~1722,中值为1002;

    ch1的11位=data2的低3位+data1的8位;
    例如:data1=00110110,data2=11001111;
    这时ch1=111 00110110=1846;通道1 的值就为1846;
    ch2=data3的低6位+data2的高5位;
    ch3=data5的低1位+data4的8位+data3的高2位;
    ch4=4 7;
    ch5=7 4;
    ch6=2 8 1;
    ch7=5 6;
    ch8=8 3;
    ch9=1 8;
    ch10=4 7;
    ch11=7 4;
    ch12=2 8 1;
    ch13=5 6;
    ch14=8 3;
    ch15=3 8;
    ch16=8 5;

    4、取反问题

    用stm32中给px4发时,需要取反,并且是硬件取反,软件取反是无效的;硬件取反的电路图如下。
    在这里插入图片描述

    5、间隔问题

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

    6、数据解析与合并

    #include "Sbus.h"
    #include "bsp_usart1.h"
    #include "string.h"
    
    uint16_t values[16]={0};
    
    void sbus_out(uint16_t num_values)
    {
    	int i=0;
    	uint16_t value=0;
    	uint8_t byteindex = 1;
    	uint8_t offset = 0;
    	uint8_t oframe[25] = { 0 };
    	memset(oframe,0,25);
    	oframe[0]=0x0f;
    	oframe[24]=0x00;
    
    	for (i = 0; (i < num_values) && (i < 16); ++i)
    	{
    		value = (unsigned short)(((values[i] - SBUS_SCALE_OFFSET) / SBUS_SCALE_FACTOR) + .5f);
    		if (value > 0x07ff)
    		{
    			value = 0x07ff;
    		}
    
    		while (offset >= 8)
    		{
    			++byteindex;
    			offset -= 8;
    		}
    		
    		oframe[byteindex] |= (value << (offset)) & 0xff;
    		oframe[byteindex + 1] |= (value >> (8 - offset)) & 0xff;
    		oframe[byteindex + 2] |= (value >> (16 - offset)) & 0xff;
    		offset += 11;
    	}
    	
    	for (i=0;i<25;i++)
    	{
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
    		USART_SendData(USART1, (uint16_t)oframe[i]);     
    	}
    }
    
    
    void sbus_decode(unsigned char *frame)
    {
    	unsigned int pick=0,channel=0,value1=0,piece=0;
    	const struct sbus_bit_pick *decode;
    	for (channel = 0; channel < 16; channel++) 
    	{
    		value1 = 0;
    
    		for (pick = 0; pick < 3; pick++) 
    		{
    			decode = &sbus_decoder[channel][pick];
    
    			if (decode->mask != 0) 
    			{
    				piece = frame[1 + decode->byte];
    				piece >>= decode->rshift;
    				piece &= decode->mask;
    				piece <<= decode->lshift;
    
    				piece &= 0x07ff;
    
    				value1 |= piece;
    			}
    		}
    		values[channel] = (uint16_t)(value1 * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
    		if(channel==1)
    		{
    			values[channel]=3029-values[channel];
    		}
    	}
    }
    

    合成函数:
    void sbus_out(uint16_t num_values);
    //参数为通道数;
    values[16]就是对应的16个通道;
    解析函数:
    void sbus_decode(unsigned char *frame);
    //frame为25个u8位数据;


    参考大佬的文章链接:
    https://blog.csdn.net/uunubt/article/details/101712492?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242

    https://blog.csdn.net/uunubt/article/details/101712492?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242

    安装nvidia驱动只能显示扩展屏,卸载nvidia驱动只能显示主屏幕,二者不可得兼,两小时在安装驱动解决显示问题。有时候不完整就不完整吧,不是所有东西都能顺利解决,既然解决不了为何不调整心态做其他事情。

    cs