DT7遥控DBUS协议解析

news2024/11/24 4:06:21

文章目录

    • 运行环境:
    • 1.1 DBUS协议解析
      • 1)DT7遥控
      • 2)配置串口引脚
      • 3)配置串口接收DMA
    • 2.1例程代码移植
      • 1)例程移动到 Inc 和 Src
      • 2)makefile添加.c文件
    • 3.1核心代码解释
    • 4.1代码修改
      • 1)bsp_rc.c 和 remote_control.c
      • 2)调用代码
    • 5.1调试
      • 1)硬件接线
      • 2)串口工具监视拨杆数据

运行环境:

ubuntu18.04.melodic
宏基暗影骑士笔记本
stm32f427IIH6
stlink
9-24v可调电源
usb转串口
杜邦线转4pin
DBUS遥控
接收机

1.1 DBUS协议解析

1)DT7遥控

DT7遥控示意图:每个通道由11位数据控制
在这里插入图片描述

2)配置串口引脚

详情见:USART串口发送

UASRT6
发送TX_PG14
接收RX_PG9
在这里插入图片描述
在这里插入图片描述

3)配置串口接收DMA

串口接收DMA:接收由遥控发送过来的数据

DBUS 的传输速率为 100k bit/s,数据长度为 8 位,奇偶校验位为偶校验,结束位 1 位。
在这里插入图片描述

串口6接收DMA
环形储存器

在这里插入图片描述

打开串口全局中断

在这里插入图片描述

2.1例程代码移植

1)例程移动到 Inc 和 Src

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2)makefile添加.c文件

在这里插入图片描述

3.1核心代码解释

在这里插入图片描述

每个通道由11位数据控制

在这里插入图片描述

rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff;
sbus_buf[1] << 8是将pData[1]左移8位到高8位,然后和sbus_buf[0]的pData[0]进行与运算, 拼接成左下图的16位
然后和0x07ff(0x07ff二进制是1111111111)进行或运算,取出后11位。

rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff
同理,sbus_buf[1] >> 3是将pData[1]右移3位,舍弃3位,保留低5位。
sbus_buf[2] << 5是将pData[2]左移5位,然后拼接如右下图,取后11位。

在这里插入图片描述

4.1代码修改

1)bsp_rc.c 和 remote_control.c

bsp_rc.c 文件是串口3的初始化, 我们用的是串口6,需要修改代码。
remote_control.c是对数据进行处理和解析,我们用的是串口6,需要修改代码。

void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num)
{
    //enable the DMA transfer for the receiver request
    SET_BIT(huart6.Instance->CR3, USART_CR3_DMAR);

    //enalbe idle interrupt
    __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);

    //disable DMA
    __HAL_DMA_DISABLE(&hdma_usart6_rx);
    while(hdma_usart6_rx.Instance->CR & DMA_SxCR_EN)
    {
        __HAL_DMA_DISABLE(&hdma_usart6_rx);
    }

    hdma_usart6_rx.Instance->PAR = (uint32_t) & (USART6->DR);
  
    //memory buffer 1
    hdma_usart6_rx.Instance->M0AR = (uint32_t)(rx1_buf);
  
    //memory buffer 2
    hdma_usart6_rx.Instance->M1AR = (uint32_t)(rx2_buf);
  
    //data length
    hdma_usart6_rx.Instance->NDTR = dma_buf_num;
  
    //enable double memory buffer
    SET_BIT(hdma_usart6_rx.Instance->CR, DMA_SxCR_DBM);

    //enable DMA
    __HAL_DMA_ENABLE(&hdma_usart6_rx);

}
extern UART_HandleTypeDef huart6;
extern DMA_HandleTypeDef hdma_USART6_rx;

/**
  * @brief          remote control protocol resolution
  * @param[in]      sbus_buf: raw data point
  * @param[out]     rc_ctrl: remote control data struct point
  * @retval         none
  */
/**
  * @brief          ң����Э�����
  * @param[in]      sbus_buf: ԭ������ָ��
  * @param[out]     rc_ctrl: ң��������ָ
  * @retval         none
  */
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl);

//remote control data 
//ң�������Ʊ���
RC_ctrl_t rc_ctrl;

//receive data, 18 bytes one frame, but set 36 bytes 
//����ԭʼ���ݣ�Ϊ18���ֽڣ�����36���ֽڳ��ȣ���ֹDMA����Խ��
static uint8_t sbus_rx_buf[2][SBUS_RX_BUF_NUM];

/**
  * @brief          remote control init
  * @param[in]      none
  * @retval         none
  */
/**
  * @brief          ң������ʼ��
  * @param[in]      none
  * @retval         none
  */
void remote_control_init(void)
{
    RC_init(sbus_rx_buf[0], sbus_rx_buf[1], SBUS_RX_BUF_NUM);
}
/**
  * @brief          get remote control data point
  * @param[in]      none
  * @retval         remote control data point
  */
/**
  * @brief          ��ȡң��������ָ��
  * @param[in]      none
  * @retval         ң��������ָ��
  */
const RC_ctrl_t *get_remote_control_point(void)
{
    return &rc_ctrl;
}


//�����ж�
void USART6_IRQHandler(void)
{
    if(huart6.Instance->SR & UART_FLAG_RXNE)//���յ�����
    {
        __HAL_UART_CLEAR_PEFLAG(&huart6);
    }
    else if(USART6->SR & UART_FLAG_IDLE)
    {
        static uint16_t this_time_rx_len = 0;

        __HAL_UART_CLEAR_PEFLAG(&huart6);

        if ((hdma_USART6_rx.Instance->CR & DMA_SxCR_CT) == RESET)
        {
            /* Current memory buffer used is Memory 0 */
    
            //disable DMA
            //ʧЧDMA
            __HAL_DMA_DISABLE(&hdma_USART6_rx);

            //get receive data length, length = set_data_length - remain_length
            //��ȡ�������ݳ���,���� = �趨���� - ʣ�೤��
            this_time_rx_len = SBUS_RX_BUF_NUM - hdma_USART6_rx.Instance->NDTR;

            //reset set_data_lenght
            //�����趨���ݳ���
            hdma_USART6_rx.Instance->NDTR = SBUS_RX_BUF_NUM;

            //set memory buffer 1
            //�趨������1
            hdma_USART6_rx.Instance->CR |= DMA_SxCR_CT;
            
            //enable DMA
            //ʹ��DMA
            __HAL_DMA_ENABLE(&hdma_USART6_rx);

            if(this_time_rx_len == RC_FRAME_LENGTH)
            {
                sbus_to_rc(sbus_rx_buf[0], &rc_ctrl);
            }
        }
        else
        {
            /* Current memory buffer used is Memory 1 */
            //disable DMA
            //ʧЧDMA
            __HAL_DMA_DISABLE(&hdma_USART6_rx);

            //get receive data length, length = set_data_length - remain_length
            //��ȡ�������ݳ���,���� = �趨���� - ʣ�೤��
            this_time_rx_len = SBUS_RX_BUF_NUM - hdma_USART6_rx.Instance->NDTR;

            //reset set_data_lenght
            //�����趨���ݳ���
            hdma_USART6_rx.Instance->NDTR = SBUS_RX_BUF_NUM;

            //set memory buffer 0
            //�趨������0
            DMA1_Stream1->CR &= ~(DMA_SxCR_CT);
            
            //enable DMA
            //ʹ��DMA
            __HAL_DMA_ENABLE(&hdma_USART6_rx);

            if(this_time_rx_len == RC_FRAME_LENGTH)
            {
                //����ң��������
                sbus_to_rc(sbus_rx_buf[1], &rc_ctrl);
            }
        }
    }
}


/**
  * @brief          remote control protocol resolution
  * @param[in]      sbus_buf: raw data point
  * @param[out]     rc_ctrl: remote control data struct point
  * @retval         none
  */
/**
  * @brief          ң����Э�����
  * @param[in]      sbus_buf: ԭ������ָ��
  * @param[out]     rc_ctrl: ң��������ָ
  * @retval         none
  */
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
{
    if (sbus_buf == NULL || rc_ctrl == NULL)
    {
        return;
    }

    rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff;        //!< Channel 0
    rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff; //!< Channel 1
    rc_ctrl->rc.ch[2] = ((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) |          //!< Channel 2
                         (sbus_buf[4] << 10)) &0x07ff;
    rc_ctrl->rc.ch[3] = ((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff; //!< Channel 3
    rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003);                  //!< Switch left
    rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2;                       //!< Switch right
    rc_ctrl->mouse.x = sbus_buf[6] | (sbus_buf[7] << 8);                    //!< Mouse X axis
    rc_ctrl->mouse.y = sbus_buf[8] | (sbus_buf[9] << 8);                    //!< Mouse Y axis
    rc_ctrl->mouse.z = sbus_buf[10] | (sbus_buf[11] << 8);                  //!< Mouse Z axis
    rc_ctrl->mouse.press_l = sbus_buf[12];                                  //!< Mouse Left Is Press ?
    rc_ctrl->mouse.press_r = sbus_buf[13];                                  //!< Mouse Right Is Press ?
    rc_ctrl->key.v = sbus_buf[14] | (sbus_buf[15] << 8);                    //!< KeyBoard value
    rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8);                 //NULL

    rc_ctrl->rc.ch[0] -= RC_CH_VALUE_OFFSET;
    rc_ctrl->rc.ch[1] -= RC_CH_VALUE_OFFSET;
    rc_ctrl->rc.ch[2] -= RC_CH_VALUE_OFFSET;
    rc_ctrl->rc.ch[3] -= RC_CH_VALUE_OFFSET;
    rc_ctrl->rc.ch[4] -= RC_CH_VALUE_OFFSET;
}

2)调用代码

main.c中包含头文件

#include "bsp_rc.h"
#include "remote_control.h"

定义一个变量储存区(结构体指针)

const RC_ctrl_t *local_rc_ctrl;

初始化串口
初始化储存区

remote_control_init();
local_rc_ctrl = get_remote_control_point();

添加串口输出代码到while循环中

       usart_printf(
"**********\r\n\
ch0:%d\r\n\
ch1:%d\r\n\
ch2:%d\r\n\
ch3:%d\r\n\
ch4:%d\r\n\
s1:%d\r\n\
s2:%d\r\n\
mouse_x:%d\r\n\
mouse_y:%d\r\n\
press_l:%d\r\n\
press_r:%d\r\n\
key:%d\r\n\
**********\r\n",
            local_rc_ctrl->rc.ch[0], local_rc_ctrl->rc.ch[1], local_rc_ctrl->rc.ch[2], local_rc_ctrl->rc.ch[3], local_rc_ctrl->rc.ch[4],
            local_rc_ctrl->rc.s[0], local_rc_ctrl->rc.s[1],
            local_rc_ctrl->mouse.x, local_rc_ctrl->mouse.y,local_rc_ctrl->mouse.z, local_rc_ctrl->mouse.press_l, local_rc_ctrl->mouse.press_r,
            local_rc_ctrl->key.v);

        HAL_Delay(200);

在这里插入图片描述

添加void usart_printf()函数定义

void usart_printf(const char *fmt,...)
{
    static uint8_t tx_buf[256] = {0};
    static va_list ap;
    static uint16_t len;
    va_start(ap, fmt);

    //return length of string 
    //�����ַ�������
    len = vsprintf((char *)tx_buf, fmt, ap);

    va_end(ap);

    // usart1_tx_dma_enable(tx_buf, len);

}

修改bsp_rc.h和remote_control.h

在这里插入图片描述
在这里插入图片描述

注释stm32f4xx_it.c中重复定义的串口6中断服务函数(remote_control.c中已经定义过了)

在这里插入图片描述

5.1调试

1)硬件接线

接收机插A板的dbus接口
对频: 按住接收机的孔,然后打开遥控器

2)串口工具监视拨杆数据

sudo cutecom
make
F5调试运行


⭐⭐⭐ 嘟嘟崽 ⭐⭐⭐
⭐⭐⭐ 祝你成功 ⭐⭐⭐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C进阶】-- 字符串函数(1)

目录 0. 前言 1. 函数介绍 1.1 strlen 1.1.1主动改变\0的位置 ✅"strlen函数的返回类型是size_t - 无符号整型"✅ 当使用strlen函数但不引用头文件时&#xff0c;执行结果超出预料: 求字符串长度的方法&#x1f4a5; 1.计数器 2.递归 3.指针 - 指针 1.2 st…

HBase安装下载与集群(高可用)

一、准备 1.1 安装zookeeper zookeeper 安装下载与集群 1.2 安装HADOOP hadoop搭建集群搭建 1.3下载HBase https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/ 二、正常部署 2.1 检查是否正常启动 2.2解压 tar -zvxf hbase-2.4.11-bin.tar.gz2.3配置环境变量 vim /…

高效的工作团队都在使用什么工具?

、 移动互联网时代&#xff0c;企业需要开源节流&#xff0c;需要提高员工整体工作效率。尤其对于互联网公司来说&#xff0c;要快速发展业务&#xff0c;更需要让团队工作简单、方便、高效。然而大多公司都面临以下低效阻碍&#xff1a;跨公司、跨部门沟通合作困难。不同部门和…

2、Flutter布局和状态管理

一、Flutter布局之Row&Column 1.1 Container的center属性: 让子控件在父控件的中间显示 Container(color: Colors.yellow,//1.Center让子部件在父控件中间child: Center(child: Text(Layout Center)),); 1.2 alignment让子控件相对父控件位置,取值范围在-1&#xff5e;1…

Mysql索引(1):索引概述

1 介绍 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c; 这样就可以在这些数据结构上…

【半监督学习】Match系列.1

半监督学习(SSL) 半监督学习(SSL). 让学习器不依赖外界交互、自动地利用未标记样本来提升学习性能. 即在少量样本标签的引导下, 能够充分利用大量无标签样本提高学习性能, 避免了数据资源的浪费, 同时解决了有标签样本较少时监督学习方法泛化能力不强和缺少样本标签引导时无监…

YoloV8涨点神器:CFPNet-ECVBlock的小目标检测,即插即用,助力检测涨点

1.Centralized Feature Pyramid for Object Detection 论文地址: https://arxiv.org/abs/2210.02093 1.摘要: CFPNet简介 CFPNet即插即用,助力检测涨点,YOLOX/YOLOv5/YOLOV7均有效 1.3 Centralized Feature Pyramid (CFP) 如图2所示,CFP主要由以下部分组成:输入图像、…

<IBM AIX><ERRPT><No.001>《出现E86653C3、49183216、8003764C告警的处理 20230506》

《出现E86653C3、49183216、8003764C告警的处理 20230506》 1 现象2 分析3 结论4 引申 1 现象 服务器出现errpt告警&#xff0c;告警为E86653C3、49183216、8003764C。 2 分析 1、hdisk1对应的VG&#xff0c;为rootvg。 lspv |grep hdisk12、查看VG状态 lsvg rootvg说明…

聊聊压电材料高温介电温谱仪所知道的那些事(GWJDN-600A)

GWJDN-600A型压电材料高温介电温谱仪 关键词&#xff1a;单通道&#xff0c;双通道&#xff0c;四通道&#xff0c;高低温 GWJDN-600A压电材料高温介电温谱仪本高频介电温谱系统主要用于绝缘材料在不同温度不同频率下的电学性能测试&#xff0c;系统包含高温炉膛&#xff0c;阻…

【云原生】k8s集群部署Rook+Ceph云原生存储

文章目录 一、Rook介绍二、Ceph介绍三、部署Rook和Ceph3.1 前置准备3.2 部署Rook3.3 部署Ceph集群3.4 部署ceph dashboard 四、部署Rook工具箱五、部署RBD StorageClass 一、Rook介绍 Rook 官网地址&#xff1a;https://rook.io 是一个自管理的分布式存储编排系统&#xff0c;…

c++基础学习Num04

目录 基于for循环 一维数组 二维数组理解 c语言的null和c的null 基于for循环 for(ELEMTYPE val:array){}ELEMTYPE:是范围变量的类型。通常使用auto自动转换范围变量类型 val:范围变量的名称。通过迭代依次接收数组中的元素值 array:容器&#xff0c;注意这里的array必须是…

ctfshow 每周大挑战 RCE极限挑战 2

目录 题目解题步骤1.跑一下正则2.变量自增3.最终解题payload 一点多余的思考 题目 解题步骤 1.跑一下正则 本着能懒就懒的原则&#xff0c;就不写Python了&#xff08;提一下这个主要是我一开始想的是写Python呜呜呜&#xff09;&#xff0c;直接写php&#xff0c;还能复制粘…

C生万物 | 指针入门到进阶就看这篇了【十万字吐血整理,收藏学习】

文章篇幅较长&#xff0c;可前往电脑端进行学习&#x1f4bb; 之前很多粉丝私信我说C语言指针怎么这么难&#xff0c;看了很多视频都学不懂&#xff0c;于是我写了一篇有关指针从入门到进阶的教学&#xff0c;帮助那些对指针很困扰的同学有一个好的学习途径&#xff0c;下面是本…

基于JavaWeb实现的学生宿舍管理系统

【简介】 本系统是基于Java实现的学生宿舍管理系统&#xff0c;前端&#xff1a;Vue&#xff1b;后端&#xff1a;SpringBoot Mybatis Redis Mysql&#xff1b;系统环境&#xff1a;jdk1.8 | mysql | redis | nodejs14。有包含登录在内的十大功能模块&#xff0c;三个访问角…

详解事务模式和 Lua 脚本,带你吃透 Redis 事务

先说结论&#xff1a; Redis 的事务模式具备如下特点&#xff1a; 保证隔离性&#xff1b;无法保证持久性&#xff1b;具备了一定的原子性&#xff0c;但不支持回滚&#xff1b;一致性的概念有分歧&#xff0c;假设在一致性的核心是约束的语意下&#xff0c;Redis 的事务可以…

Vuex从了解到实际运用(一)彻底搞懂什么是Vuex

vuex从了解到实际运用——彻底搞懂什么是vuex 知识回调&#xff08;不懂就看这儿&#xff01;&#xff09;场景复现核心干货什么是vuex全局状态管理使用状态管理工具后的好处vuex的实现原理vuex的组件通信1.多级组件通信2.同级组件通信使用vuex进行组件通信 关于vuex的小结 知识…

总结842

学习目标&#xff1a; 5月&#xff08;张宇强化18讲&#xff0c;背诵25篇短文&#xff0c;熟词僻义300词基础词&#xff09; 每日必复习&#xff08;5分钟&#xff09; 学习内容&#xff1a; 暴力英语:背200个基础词阅读理解前两段语法 高等数学&#xff1a;强化课第一讲 小…

Baumer工业相机堡盟工业相机如何联合BGAPISDK和Halcon实现图像的Pow伽马变换算法增强(C#)

Baumer工业相机堡盟工业相机如何联合BGAPISDK和Halcon实现图像的Pow伽马变换算法增强&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机使用图像算法增加图像的技术背景Baumer工业相机通过BGAPI SDK联合Halcon使用Pow伽马变换增强算法1.引用合适的类文件2.BGAPI SDK在图…

gtest之断言

目录 普通断言EXPECT_THAT 布尔条件断言EXPECT_TRUEEXPECT_FALSE 二进制断言EXPECT_EQEXPECT_NEEXPECT_LTEXPECT_LEEXPECT_GTEXPECT_GE 字符串比较EXPECT_STREQEXPECT_STRNEEXPECT_STRCASEEQEXPECT_STRCASENE 浮点型比较EXPECT_FLOAT_EQEXPECT_DOUBLE_EQEXPECT_NEAR 显式成功与…

k8s基础4——deployment控制器、应用部署、升级、回滚、水平扩容缩容

文章目录 一、基本介绍二、应用程序生命周期2.1 部署应用2.2 应用升级2.2.1 修改YAML文件升级&#xff08;交互式&#xff09;2.2.2 命令指定镜像版本升级&#xff08;免交互式&#xff09;2.2.3 调用vim升级 2.3 滚动升级2.3.1 升级流程 2.4 应用回滚2.4.1 查看历史发布版本2.…