您现在的位置是:首页 >技术杂谈 >DT7遥控DBUS协议解析网站首页技术杂谈

DT7遥控DBUS协议解析

圆嘟嘟2019 2024-06-17 10:14:45
简介DT7遥控DBUS协议解析

运行环境:

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(
"**********

ch0:%d

ch1:%d

ch2:%d

ch3:%d

ch4:%d

s1:%d

s2:%d

mouse_x:%d

mouse_y:%d

press_l:%d

press_r:%d

key:%d

**********
",
            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调试运行


⭐⭐⭐ 嘟嘟崽 ⭐⭐⭐
⭐⭐⭐ 祝你成功 ⭐⭐⭐
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。