STM32H750 UART 空闲中断 +DMA传输

STM32H750 UART 空闲中断 +DMA传输


STM32H750在使用串口外设配合DMA,和其他不带高速数据缓冲区的MCU差别就是,在调用DMA收发函数时,如果开启了数据高速缓存区,需要对将要调用的数据存储区域进行缓存清空处理。因为DMA传输的数据不在高速缓冲区范围内。如果不是调用DMA相关收发函数,就不需要此操作。
在这里插入图片描述

  • 🌿开启缓冲区
  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();
  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();
  • 🌿清除指定缓冲区方法
SCB_CleanDCache_by_Addr((uint32_t *)UART_RX_STA, UART_RX_LEN);
SCB_CleanInvalidateDCache_by_Addr ((uint32_t *)UART_RX_STA, UART_RX_LEN);//或者
  • 🌿如果开启了MPU功能,需要注意所定义的变量存储位置在可读写范围内,不是定义在MPU内存保护区地址内,否则无法存储所接收的数据。

🔰串口接收事件中断回调(HAL_UARTEx_RxEventCallback )和接收完成中断回调(HAL_UART_RxCpltCallback )差异说明

HAL_UARTEx_RxEventCallbackHAL_UART_RxCpltCallback 是两个不同的回调函数,它们在STM32的HAL库中用于处理UART(通用异步收发传输器)的接收事件。

  1. HAL_UART_RxCpltCallback: 这个回调函数在UART接收完成时被调用。当UART接收到指定数量的数据(通常是一个字节或一个数据包)后,DMA(直接内存访问)传输完成,此时会触发这个回调函数。

◦ 它通常用于处理接收到的数据,例如将数据存储到缓冲区或进行进一步的处理。

  1. HAL_UARTEx_RxEventCallback: 这个回调函数在UART接收到数据时被调用,而不仅仅是在接收完成时。它可以在接收到每个字节或每个数据包时被触发,具体取决于UART的配置。与 HAL_UART_RxCpltCallback 不同,HAL_UARTEx_RxEventCallback 提供了更细粒度的控制,可以在数据接收的过程中进行实时处理。
    总结:
    HAL_UART_RxCpltCallback 在UART接收完成时调用,用于处理接收到的完整数据。
    HAL_UARTEx_RxEventCallback 在UART接收到数据时调用,可以在数据接收的过程中进行实时处理。

采用不同的接收回调函数,决定了中断处理内容的不同。具体使用哪种方式,可以根据具体的实际需求来设定中断回调。

🛠 STM32CubeMX工程配置

  • 🌿串口外设的基本配置:无特殊要求,默认参数即可
    在这里插入图片描述

  • 🌿串口DMA配置参数
    在这里插入图片描述
    在这里插入图片描述

  • 🌿使能串口全局中断
    在这里插入图片描述

📗业务代码完善

  • 🌿开启串口DMA接收
HAL_UART_Receive_DMA(&huart1,UART_RX_BUF,UART_RX_LEN);//开启DMA串口接收
  • 🌿开启空闲中断
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//空闲中断
  • 🌿串口中断处理函数
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)  // 空闲中断标记被置位
	{
	    __HAL_UART_CLEAR_IDLEFLAG(&huart1);  // 清除中断标记
	    HAL_UART_DMAStop(&huart1);           // 停止DMA接收
	    UART_RX_STA = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
	    UART_RX_BUF[UART_RX_STA] = 0;  // 添加结束符
	    UART_RX_STA |= 0X8000;         // 标记接收结束
	    HAL_UART_Receive_DMA(&huart1, UART_RX_BUF, UART_RX_LEN);  // 重新启动DMA接收
	}
  /* USER CODE END USART1_IRQn 1 */
}
  • 🌿串口接收完成,数据处理内容:
		if(UART_RX_STA & 0X8000)
{
					SCB_CleanDCache_by_Addr((uint32_t *)UART_RX_STA, UART_RX_LEN);
	//				SCB_CleanInvalidateDCache_by_Addr ((uint8_t *)UART_RX_STA, UART_RX_LEN);//或者
			HAL_UART_Transmit_DMA(&huart1,(uint8_t *)UART_RX_BUF, UART_RX_STA & 0X7FFF);//配合上面的函数一起使用
//	HAL_UART_Transmit(&huart1, UART_RX_BUF, UART_RX_STA & 0X7FFF, 100);    // 将接收到的数据发送回去
	UART_RX_STA = 0;  // 清除标记
}

📘接收事件回调实现方法

  • 🌿在中断处理函数中添加:
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

	HAL_UARTEx_ReceiveToIdle_DMA(&huart1,UART_RX_BUF,UART_RX_LEN);	//重新开启串口空闲中断和DMA接收,一定要放在这里
  /* USER CODE END USART1_IRQn 1 */
}
  • 🌿添加接收事件回调函数处理内容:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart->Instance == USART1)
	{

	    UART_RX_STA = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
		UART_RX_BUF[UART_RX_STA] = 0;  // 添加结束符
		UART_RX_STA |= 0X8000;         // 标记接收结束
		__HAL_UNLOCK(huart);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1,UART_RX_BUF,UART_RX_LEN) ;
		HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_12 ) ;
	}

}
  • 🌿main串口接收空闲中断初始化

在main外设初始化后,添加:

HAL_UARTEx_ReceiveToIdle_DMA(&huart1,UART_RX_BUF,UART_RX_LEN) ;
  • 🌿接收数据回调事件,数据处理内容:
		if(UART_RX_STA & 0X8000)
{
					SCB_CleanDCache_by_Addr((uint32_t *)UART_RX_STA, UART_RX_LEN);
			//		SCB_CleanInvalidateDCache_by_Addr ((uint32_t *)UART_RX_STA, UART_RX_LEN);//或者
			HAL_UART_Transmit_DMA(&huart1,(uint8_t *)UART_RX_BUF, UART_RX_STA & 0X7FFF);//配合上面的函数一起使用
//	HAL_UART_Transmit(&huart1, UART_RX_BUF, UART_RX_STA & 0X7FFF, 100);    // 将接收到的数据发送回去
	UART_RX_STA = 0;  // 清除标记
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值