采用HAL_UART_Receive_DMA接口使能DMA的接收,真正起到作用的是接口内部的HAL_DMA_Start_IT这个接口,如果想采用双缓冲模式,需要采用HAL_DMAEx_MultiBufferStart_IT这个接口才可以,这个接口的参数中需要提供两个缓冲区的地址,为了保证对外接口的一致性,我暂采用的是将第一个缓冲区首地址偏移缓冲区的长度作为第二个缓冲区的首地址。当然也可以直接改写HAL_UART_Receive_DMA,让使用者提供两个缓冲区的首地址,或者单独写一个接口都OK。
当第一个缓冲区数据满后会产生完成中断,回调HAL_UART_TxCpltCallback这个函数,当第二个缓冲区满后,也会回调一个函数,但这个函数需要我们事先注册一下,在串口初始化的时候添加第二个缓冲区满后回调的函数:
int8_t MW_UART_Init(int8_t id,UART_HandleTypeDef *handle)
{
MX_UART_ATTR *pUartAttr = &sUartAttr;
pUartAttr->id = id;
pUartAttr->handle = handle;
pUartAttr->DamOffset = 0;
pUartAttr->TransFlag = MW_TRANS_IDLE;
pUartAttr->DmaSize = MW_UART_DMA_LEN / 2;
pUartAttr->pReadDma = Uart1RxDma;
pUartAttr->pWriteDma = Uart1TxDma;
CFIFO_Init(&pUartAttr->ReadCFifo, Uart1RxBuff, MW_UART_BUFFER_LEN);
CFIFO_Init(&pUartAttr->WriteCFifo, Uart1TxBuff, MW_UART_BUFFER_LEN);
/*注册DMA的第二个缓冲区接收完成时回调的函数*/
HAL_DMA_RegisterCallback(pUartAttr->handle->hdmarx,HAL_DMA_XFER_M1CPLT_CB_ID,UART_DMAReceiveMem1Cplt);
/*使能串口空闲中断*/
__HAL_UART_ENABLE_IT(handle, UART_IT_IDLE);
/*使能DMA工作*/
if(HAL_OK != HAL_UART_Receive_DMA(pUartAttr->handle, pUartAttr->pReadDma, pUartAttr->DmaSize))
{
return MW_FAIL;
}
return MW_SUCCESS;
}
|