This commit is contained in:
Robofish 2026-03-14 17:24:48 +08:00
parent a3b4381f7e
commit 511b9809c9

View File

@ -41,12 +41,26 @@
static osThreadId_t thread_alert;
static bool inited = false;
static DR16_t *dr16_instance = NULL; /* 用于空闲中断回调中访问实例 */
static uint8_t sync_buf[32]; /* 帧同步时的丢弃缓冲区 */
/* Private function -------------------------------------------------------- */
static void DR16_RxCpltCallback(void) {
osThreadFlagsSet(thread_alert, SIGNAL_DR16_RAW_REDY);
}
/**
* @brief -
* 线DMA接收
* StartDmaRecv
*/
static void DR16_IdleCallback(void) {
/* 停止当前DMA接收无论收了多少字节 */
HAL_UART_AbortReceive(BSP_UART_GetHandle(BSP_UART_DR16));
/* 通知任务:可以启动下一次对齐的接收了 */
osThreadFlagsSet(thread_alert, SIGNAL_DR16_RAW_REDY);
}
static bool DR16_DataCorrupted(const DR16_t *dr16) {
if (dr16 == NULL) return DEVICE_ERR_NULL;
@ -79,16 +93,49 @@ int8_t DR16_Init(DR16_t *dr16) {
if (inited) return DEVICE_ERR_INITED;
if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL;
dr16_instance = dr16;
/* 注册 DMA 接收完成回调 */
BSP_UART_RegisterCallback(BSP_UART_DR16, BSP_UART_RX_CPLT_CB,
DR16_RxCpltCallback);
/* 注册空闲中断回调并使能空闲中断,用于帧同步 */
BSP_UART_RegisterCallback(BSP_UART_DR16, BSP_UART_IDLE_LINE_CB,
DR16_IdleCallback);
__HAL_UART_ENABLE_IT(BSP_UART_GetHandle(BSP_UART_DR16), UART_IT_IDLE);
/*
* DMA接收
* DMA会从帧中间开始收
* IdleCallback Abort StartDmaRecv
*
*/
HAL_UART_Receive_DMA(BSP_UART_GetHandle(BSP_UART_DR16),
sync_buf, sizeof(sync_buf));
/* 等待空闲中断完成首次同步最多50ms足够等一帧 */
osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, 50);
inited = true;
return DEVICE_OK;
}
int8_t DR16_Restart(void) {
__HAL_UART_DISABLE(BSP_UART_GetHandle(BSP_UART_DR16));
__HAL_UART_ENABLE(BSP_UART_GetHandle(BSP_UART_DR16));
UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_DR16);
/* 先终止当前DMA接收 */
HAL_UART_AbortReceive(huart);
/* 重置串口 */
__HAL_UART_DISABLE(huart);
__HAL_UART_ENABLE(huart);
/* 重新使能空闲中断 */
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
/* 重新做帧同步:丢弃式接收,等空闲中断对齐 */
HAL_UART_Receive_DMA(huart, sync_buf, sizeof(sync_buf));
osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, 50);
return DEVICE_OK;
}
@ -109,6 +156,8 @@ int8_t DR16_ParseData(DR16_t *dr16){
if (dr16 == NULL) return DEVICE_ERR_NULL;
if (DR16_DataCorrupted(dr16)) {
/* 数据损坏说明帧错位了,重启串口并重新同步 */
DR16_Restart();
return DEVICE_ERR;
}