提供一个已经实际使用的DMA串口空闲驱动代码
串口及DMA初始化代码就不提供了,自行调通。
接收DMA设置为单次,不要用循环模式。
这个是串口空闲中断接收的回调函数
/*************************************
*函数名称:UART_DMARx_IDLECallback
*函数说明:串口DMA空闲中断数据处理函数
*入口参数:无
*
*返回参数:无
*************************************/
void UART_DMARx_IDLECallback(void)
{
#if RX_Enable
//串口DMA空闲中断数据处理
uint32_t temp;
DMA_ChannelEnable(DMA1_Channel4, DISABLE); //DMA通道禁止
temp = DMA_GetCurrDataCounter(DMA1_Channel4); //获取DMA剩余字节数
Rxbuffer_index = RX_Buffer_Size - temp; //计算接收到的数据数量
USART_Rx_OK = 1; //接收完成标志置位
#endif
}
在串口中断里的调用
void USART1_IRQHandler(void)
{
uint8_t clearTag;
if(USART_GetITStatus(USART1, USART_INT_IDLEF) != RESET)
{
// USART_ClearITPendingBit(USART1, USART_INT_IDLEF); //清除中断标志位
clearTag += USART1->DT; //读一次数据寄存器,作用是清除中断标志位
UART_DMARx_IDLECallback(); //串口DMA空闲中断回调函数
}
}
接收到的数据在用户程序里进行处理,处理完毕记得调用串口DMA接收恢复函数,恢复DMA接收
代码如下:
/*************************************
*函数名称:UART_DMARx_IDLEResume
*函数说明:串口DMA空闲中断数据处理完成
*后的DMA状态恢复函数
*入口参数:无
*
*返回参数:无
*************************************/
void UART_DMARx_IDLEResume(void)
{
memset(Rxbuffer, 0, RX_Buffer_Size); //清空接收缓冲区
Rxbuffer_index = 0; //接收缓冲区索引清零
USART_Rx_OK = 0; //接收完成标志清零
DMA_ChannelEnable(DMA1_Channel4, DISABLE); //DMA通道禁止
DMA_SetCurrDataCounter(DMA1_Channel4, RX_Buffer_Size); //重新设置DMA数据计数器参数
DMA_ChannelEnable(DMA1_Channel4, ENABLE); //DMA通道使能,开始空闲中断DMA传输
}
就这么多代码,就可以实现串口DMA空闲中断的数据接收,比较适合一帧一帧的数据传输。
|