Skip to content

3.2 DMA 和遥控器控制

本章采用 DMA 和串口通信接收 DT7&DR16 遥控器信号。

代码配置

stm32f4xx_it.c 文件下 找到 void USART1_IRQHandler(void) 回调函数,写入如下代码

C
/**
 * @brief This function handles USART1 global interrupt.
 */
void USART1_IRQHandler(void) {
    /* USER CODE BEGIN USART1_IRQn 0 */

    /* USER CODE END USART1_IRQn 0 */
    HAL_UART_IRQHandler(&huart1);
    /* USER CODE BEGIN USART1_IRQn 1 */

    if (huart1.Instance == USART1) {
        if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) !=
            RESET) {                            // 判断处于空闲中断
            __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除标志位
            HAL_UART_DMAStop(&huart1);          // 停止DMA接收
            memcpy(Data_Handle, RxData, 18); // 将接收到的数据复制至Data_Handle
                                             // 方便后续解算遥控器信号
            Decode_DBUS(Data_Handle); // 解算遥控器信号
            HAL_UART_Receive_DMA(&huart1, RxData, 18); // 开启DMA接收
        }
    }

    /* USER CODE END USART1_IRQn 1 */
}

controller.c

查资料可以发现,接收机的 DBUS 协议如下,根据协议解算即可

通道 0通道 1通道 2通道 3S1S2
偏移01122334446
长度 (bit)1111111122
符号位
范围最大值 1684
中间值 1024
最小值 364
最大值 1684
中间值 1024
最小值 364
最大值 1684
中间值 1024
最小值 364
最大值 1684
中间值 1024
最小值 364
最大值 3
最小值 1
最大值 3
最小值 1
功能无符号类型
遥控器通道 0
无符号类型
遥控器通道 1
无符号类型
遥控器通道 2
无符号类型
遥控器通道 3
遥控器发射机
S1 开关位置
遥控器发射机
S2 开关位置
鼠标 X 轴鼠标 Y 轴鼠标 Z 轴鼠标左键鼠标右键按键
偏移48648096104112
长度1616168816
符号位
C
#include "stdint.h"
#define set0 0x7ff
typedef struct controller_info {
    uint16_t ch1;
    uint16_t ch2;
    uint16_t ch3;
    uint16_t ch4;
    uint16_t s1;
    uint16_t s2;

    struct {
        uint16_t x;
        uint16_t y;
        uint16_t z;

        uint8_t left;
        uint8_t right;
    } mouse;

    uint16_t key;
} Controller_Info;

void Decode_DBUS(uint8_t *Rx) { // 根据手册解算信号
    Ctrl_Data.ch1 = (((uint16_t)Rx[0]) | ((uint16_t)Rx[1] << 8)) & set0;
    Ctrl_Data.ch2 =
        (((uint16_t)Rx[1] >> 3) | ((uint16_t)Rx[2] << 5)) & set0;
    Ctrl_Data.ch3 = (((uint16_t)Rx[2] >> 6) | ((uint16_t)Rx[3] << 2) |
                     ((uint16_t)Rx[4] << 10)) &
                    set0;
    Ctrl_Data.ch4 =
        (((uint16_t)Rx[4] >> 1) | ((uint16_t)Rx[5] << 7)) & set0;

    Ctrl_Data.mouse.x = ((uint16_t)Rx[6]) | ((uint16_t)Rx[7] << 8);
    Ctrl_Data.mouse.y = ((uint16_t)Rx[8]) | ((uint16_t)Rx[9] << 8);
    Ctrl_Data.mouse.z = ((uint16_t)Rx[10]) | ((uint16_t)Rx[11] << 8);

    Ctrl_Data.mouse.left = Rx[12];
    Ctrl_Data.mouse.right = Rx[13];

    Ctrl_Data.key = ((uint16_t)Rx[14]);
}