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 | 通道 3 | S1 | S2 |
---|---|---|---|---|---|---|
偏移 | 0 | 11 | 22 | 33 | 44 | 46 |
长度 (bit) | 11 | 11 | 11 | 11 | 2 | 2 |
符号位 | 无 | 无 | 无 | 无 | 无 | 无 |
范围 | 最大值 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 轴 | 鼠标左键 | 鼠标右键 | 按键 |
---|---|---|---|---|---|---|
偏移 | 48 | 64 | 80 | 96 | 104 | 112 |
长度 | 16 | 16 | 16 | 8 | 8 | 16 |
符号位 | 有 | 有 | 有 | 无 | 无 | 无 |
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]);
}