一、核心实现原理
-
DMA接收机制
DMA以循环模式从串口DR寄存器自动搬运数据到内存缓冲区,无需CPU干预。当DMA缓冲区半满或全满时触发中断,实现双缓冲机制。 -
超时检测策略
使用定时器监控数据包间隔。若超过设定时间(如3.5字符周期)无新数据到达,触发超时中断,标志数据帧接收完成。 -
错误处理机制
通过清除ORE(Overrun Error)标志防止数据溢出,在DMA重新初始化前校验错误状态。
二、硬件配置步骤
1. 串口DMA初始化(以USART1为例)
// DMA接收配置
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)uart1_buffer; // 双缓冲数组
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = 256; // 缓冲区大小
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 循环模式
DMA_Init(DMA1_Channel5, &DMA_InitStruct);
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
2. 超时定时器配置(TIM2)
// 定时器参数设置(1字符时间=10bits/波特率)
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_InitStruct.TIM_Period = 35; // 3.5字符周期
TIM_InitStruct.TIM_Prescaler = SystemCoreClock/1000000 -1; // 1us计数
TIM_TimeBaseInit(TIM2, &TIM_InitStruct);
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single); // 单次触发模式
三、中断协同处理
1. DMA传输中断(双缓冲管理)
void DMA1_Channel5_IRQHandler(void) {
if(DMA_GetITStatus(DMA1_IT_HT5)) { // 半满中断
TIM_SetCounter(TIM2, 0); // 重置超时计数器
TIM_Cmd(TIM2, ENABLE);
}
if(DMA_GetITStatus(DMA1_IT_TC5)) { // 全满中断
process_data(uart1_buffer, 256); // 处理前半数据
}
DMA_ClearITPendingBit(DMA1_IT_GL5);
}
2. 定时器超时中断
void TIM2_IRQHandler(void) {
if(TIM_GetITStatus(TIM2, TIM_IT_Update)) {
uint16_t data_len = 256 - DMA_GetCurrDataCounter(DMA1_Channel5);
process_data(uart1_buffer + data_pos, data_len); // 处理当前数据段
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
3. 串口错误中断(防止数据丢失)
void USART1_IRQHandler(void) {
if(USART_GetITStatus(USART1, USART_IT_ORE)) { // 上溢错误处理
USART_ClearITPendingBit(USART1, USART_IT_ORE);
USART_ReceiveData(USART1); // 清空DR寄存器
}
}