hero-dm02/User/device/dr16.c
2026-01-04 00:53:51 +08:00

222 lines
6.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
DR16接收机
Example
DR16_Init(&dr16);
while (1) {
DR16_StartDmaRecv(&dr16);
if (DR16_WaitDmaCplt(20)) {
DR16_ParseData(&dr16);
} else {
DR16_Offline(&dr16);
}
}
*/
/* Includes ----------------------------------------------------------------- */
#include "dr16.h"
#include "bsp/uart.h"
#include "bsp/time.h"
#include "device.h"
#include <string.h>
#include <stdbool.h>
/* USER INCLUDE BEGIN */
/* USER INCLUDE END */
/* Private define ----------------------------------------------------------- */
#define DR16_CH_VALUE_MIN (364u)
#define DR16_CH_VALUE_MID (1024u)
#define DR16_CH_VALUE_MAX (1684u)
//#define DR16_FRAME_SIZE (18u) // DR16数据帧固定18字节
/* USER DEFINE BEGIN */
/* USER DEFINE END */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static osThreadId_t thread_alert;
static bool inited = false;
/* Private function -------------------------------------------------------- */
static void DR16_RxCpltCallback(void) {
osThreadFlagsSet(thread_alert, SIGNAL_DR16_RAW_REDY);
}
//static void DR16_ErrorCallback(void) {
// UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_RC);
//
// // 清除所有错误标志包括FIFO错误
// __HAL_UART_CLEAR_OREFLAG(huart);
// __HAL_UART_CLEAR_NEFLAG(huart);
// __HAL_UART_CLEAR_FEFLAG(huart);
// __HAL_UART_CLEAR_PEFLAG(huart);
//
// // 清除FIFO超时标志STM32H7特有
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF)) {
// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
// }
//
// // 中止并清除当前DMA传输
// HAL_UART_AbortReceive(huart);
//}
static bool DR16_DataCorrupted(const DR16_t *dr16) {
if (dr16 == NULL) return DEVICE_ERR_NULL;
if ((dr16->raw_data.ch_r_x < DR16_CH_VALUE_MIN) ||
(dr16->raw_data.ch_r_x > DR16_CH_VALUE_MAX))
return DEVICE_ERR;
if ((dr16->raw_data.ch_r_y < DR16_CH_VALUE_MIN) ||
(dr16->raw_data.ch_r_y > DR16_CH_VALUE_MAX))
return DEVICE_ERR;
if ((dr16->raw_data.ch_l_x < DR16_CH_VALUE_MIN) ||
(dr16->raw_data.ch_l_x > DR16_CH_VALUE_MAX))
return DEVICE_ERR;
if ((dr16->raw_data.ch_l_y < DR16_CH_VALUE_MIN) ||
(dr16->raw_data.ch_l_y > DR16_CH_VALUE_MAX))
return DEVICE_ERR;
if (dr16->raw_data.sw_l == 0) return DEVICE_ERR;
if (dr16->raw_data.sw_r == 0) return DEVICE_ERR;
return DEVICE_OK;
}
/* Exported functions ------------------------------------------------------- */
int8_t DR16_Init(DR16_t *dr16) {
if (dr16 == NULL) return DEVICE_ERR_NULL;
if (inited) return DEVICE_ERR_INITED;
if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL;
// // 清零结构体
// memset(dr16, 0, sizeof(DR16_t));
BSP_UART_RegisterCallback(BSP_UART_RC, BSP_UART_RX_CPLT_CB,
DR16_RxCpltCallback);
// BSP_UART_RegisterCallback(BSP_UART_RC, BSP_UART_ERROR_CB,
// DR16_ErrorCallback);
inited = true;
return DEVICE_OK;
}
int8_t DR16_Restart(void) {
__HAL_UART_DISABLE(BSP_UART_GetHandle(BSP_UART_RC));
__HAL_UART_ENABLE(BSP_UART_GetHandle(BSP_UART_RC));
return DEVICE_OK;
}
int8_t DR16_StartDmaRecv(DR16_t *dr16) {
UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_RC);
// // 确保之前的DMA接收已停止
// if (huart->RxState != HAL_UART_STATE_READY) {
// HAL_UART_AbortReceive(huart);
// }
//
// // 清除所有可能的错误标志和IDLE标志
// __HAL_UART_CLEAR_OREFLAG(huart);
// __HAL_UART_CLEAR_NEFLAG(huart);
// __HAL_UART_CLEAR_FEFLAG(huart);
// __HAL_UART_CLEAR_PEFLAG(huart);
// __HAL_UART_CLEAR_IDLEFLAG(huart);
//
// // 清除FIFO超时标志
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF)) {
// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
// }
if (HAL_UART_Receive_DMA(huart, (uint8_t *)&(dr16->raw_data),
sizeof(dr16->raw_data)) == HAL_OK)
return DEVICE_OK;
return DEVICE_ERR;
}
bool DR16_WaitDmaCplt(uint32_t timeout) {
return (osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, timeout) ==
SIGNAL_DR16_RAW_REDY);
}
int8_t DR16_ParseData(DR16_t *dr16){
if (dr16 == NULL) return DEVICE_ERR_NULL;
// // STM32H7 D-Cache一致性处理使DMA接收的数据对CPU可见
// // D-Cache按32字节对齐需要对齐处理
// uint32_t addr = (uint32_t)&(dr16->raw_data);
// uint32_t size = sizeof(dr16->raw_data);
// // 向下对齐到32字节边界
// uint32_t aligned_addr = addr & ~0x1FU;
// // 计算对齐后的大小
// uint32_t aligned_size = ((size + (addr - aligned_addr) + 31) & ~0x1FU);
// SCB_InvalidateDCache_by_Addr((uint32_t *)aligned_addr, aligned_size);
if (DR16_DataCorrupted(dr16)) {
return DEVICE_ERR;
}
dr16->header.online = true;
dr16->header.last_online_time = BSP_TIME_Get_us();
memset(&(dr16->data), 0, sizeof(dr16->data));
float full_range = (float)(DR16_CH_VALUE_MAX - DR16_CH_VALUE_MIN);
// 解析摇杆数据
dr16->data.ch_r_x = 2.0f * ((float)dr16->raw_data.ch_r_x - DR16_CH_VALUE_MID) / full_range;
dr16->data.ch_r_y = 2.0f * ((float)dr16->raw_data.ch_r_y - DR16_CH_VALUE_MID) / full_range;
dr16->data.ch_l_x = 2.0f * ((float)dr16->raw_data.ch_l_x - DR16_CH_VALUE_MID) / full_range;
dr16->data.ch_l_y = 2.0f * ((float)dr16->raw_data.ch_l_y - DR16_CH_VALUE_MID) / full_range;
// 解析拨杆位置
dr16->data.sw_l = (DR16_SwitchPos_t)dr16->raw_data.sw_l;
dr16->data.sw_r = (DR16_SwitchPos_t)dr16->raw_data.sw_r;
// 解析鼠标数据
dr16->data.mouse.x = dr16->raw_data.x;
dr16->data.mouse.y = dr16->raw_data.y;
dr16->data.mouse.z = dr16->raw_data.z;
dr16->data.mouse.l_click = dr16->raw_data.press_l;
dr16->data.mouse.r_click = dr16->raw_data.press_r;
// 解析键盘按键 - 使用union简化代码
uint16_t key_value = dr16->raw_data.key;
// 解析键盘位映射W-B键位0-15
for (int i = DR16_KEY_W; i <= DR16_KEY_B; i++) {
dr16->data.keyboard.key[i] = (key_value & (1 << i)) != 0;
}
// 解析鼠标点击
dr16->data.keyboard.key[DR16_L_CLICK] = dr16->data.mouse.l_click;
dr16->data.keyboard.key[DR16_R_CLICK] = dr16->data.mouse.r_click;
// 解析第五通道
dr16->data.ch_res = 2.0f * ((float)dr16->raw_data.res - DR16_CH_VALUE_MID) / full_range;
return DEVICE_OK;
}
int8_t DR16_Offline(DR16_t *dr16){
if (dr16 == NULL) return DEVICE_ERR_NULL;
dr16->header.online = false;
memset(&(dr16->data), 0, sizeof(dr16->data));
return DEVICE_OK;
}
/* USER FUNCTION BEGIN */
/* USER FUNCTION END */