简单学习速记-STM32串口接收使用DMA+空闲中断

本文介绍了如何在STM32中利用DMA和空闲中断进行串口接收不定长数据,包括初始化、空闲中断回调、后台数据处理和CubeMX配置等步骤。
摘要由CSDN通过智能技术生成

这是一篇简单的学习笔记,记录使用STM32串口接收不定长数据,之前都是使用接收中断+缓冲区的方式,这篇笔记使用DMA+空闲中断的方式。

这是简单的速记:

使用串口空闲中断的基本思路是

  1. 串口接收初始化:在main函数初始化部分调用
    开启空闲中断__HAL_UART_ENABLE_IT()
    ②发起一个串口DMA接收HAL_UART_Receive_DMA(&huart2, uartRecv_buffer, uartRecv_buffer_len)。
    :接收的缓冲区uartRecv_buffer、长度我们通过宏以及全区数组来定义,这样串口会自动接收数据放入uartRecv_buffer。
  2. 空闲中断回调函数:这个函数会在串口中断处理函数USART2_IRQHandler(void)中调用。一开始需要判断空闲中断标志位是否被置1,如果被置1则执行下面操作。
    清除idle标志位,停止DMA传输
    ②计算DMA当前帧实际接收的数据长度 = 我们在1中设置要接收的长度 - DMA中剩余的空间长度;
    设置串口接收完成标志(这个标志是我们定义的全局变量,用于通知后台串口数据处理函数,接收完成,如果使用操作系统就可以通过“任务通知”等方式)。
    :空闲中断在HAL库中并没有提供预先定义的回调函数,这里我们自己定义一个就可以。
  3. 串口接收数据的后台处理函数:因为数据已经被DMA放到缓冲区uartRecv_buffer中,所以我们可以直接处理其中的数据,下面的示例代码只是在串口中回显出来。
    后台数据处理函数包含两个部分:
    处理数据的业务逻辑,示例代码实现串口数据回显。
    ②清除DMA当前帧实际接收的数据长度uartRecv_buffer_curframe_len,接收完成标志uartRecv_end_flag,再发起下一次的串口DMA接收HAL_UART_Receive_DMA。

在CubeMX中配置:

配置串口接收的DMA:

使能串口和DMA中断

编写上面1,2,3步骤的函数:

static uint8_t DebugUartRecvBuf[DEBUG_UART_RECVBUFLEN];
static int DebugUartRecvCnt = 0;
static int DebugUartRecvCompleteFlge = 0;
extern DMA_HandleTypeDef hdma_usart2_rx;

/* Debug_uart rx DMA idle*/
/* 初始化函数 */
void DebugUartRecvInit(void)
{
	/* 使能空闲中断 */
	__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
	/* 发起串口DMA接收 */
	HAL_UART_Receive_DMA(&huart2, DebugUartRecvBuf, DEBUG_UART_RECVBUFLEN);
}

/* 空闲中断回调函数 */
void DebugUartRecv_IdleCallback(void)
{
	/* 判断空闲中断发生 */
	if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) == SET)
	{
		/* 清除空闲中断标志位,暂停串口DMA传输 */
		__HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_IDLEF);
		HAL_UART_DMAStop(&huart2);
		/* 计算当前空闲帧接收到的数据长度 */
		DebugUartRecvCnt = DEBUG_UART_RECVBUFLEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
		/* 通知后台处理程序,接收完成 */
		DebugUartRecvCompleteFlge = 1;
	}
}

/* 
** 串口数据接收的数据处理后台函数
** ret: 0 - ok, -1 - 无数据
*/
int DebugUartRecv_DealData(char *recvData, int *len)
{
	if(DebugUartRecvCompleteFlge)
	{
		/* 数据处理 */
		strncpy(recvData, (char *)DebugUartRecvBuf, DebugUartRecvCnt);
		*len = DebugUartRecvCnt;
		
		/* 恢复标志位、当前空闲帧接收到的数据长度 */
		DebugUartRecvCompleteFlge = 0;
		DebugUartRecvCnt = 0;
		/* 再次发起下一次的串口DMA接收 */
		HAL_UART_Receive_DMA(&huart2, DebugUartRecvBuf, DEBUG_UART_RECVBUFLEN);
		return 0;
	}
	else
	{
		return -1;
	}
}

函数被调用的地方如下所示:

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值