STM32 HAL库串口+DMA接收不定长数据

        在串口通信中,很多时候我们需要的是接收一帧不确定长度的数据,而不是单个字节或者固定长度,这时我们就需要利用STM32的空闲中断(IDLE)来实现不定长数据的接收,首先我们打开STM32Cumebx建立一个工程,配置管脚图:

这里我们采用三线SWD下载方式,加一个LED灯交替闪烁,串口中断+DMA来接收不定长数据,串口采用默认配置,打开串口中断,采用DMA方式进行发送和接收:

然后保存工程生成代码。

生成代码后先定义以下变量:


uint8_t  rx_buffer[100];                             
char     BUFFER_SIZE=100;   

然后在主函数中加入串口接收回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_DMAStop(&huart1);  
	uint8_t data_length  = BUFFER_SIZE - hdma_usart1_rx.Instance->CNDTR; 
	HAL_UART_Transmit(&huart1,rx_buffer,data_length,200);
	data_length = 0;
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
}

我用的Firmware Package 版本是STM32Cube FW_L4 V1.13.0,需要在库函数stm32l4xx_hal_uart.c中的第2366行加入如下代码段


	if(((isrflags & USART_ISR_IDLE)!= RESET) &&((cr1its & USART_CR1_IDLEIE)!=RESET))
	{ 
		//clear IDLE flag
			__HAL_UART_CLEAR_IDLEFLAG(huart);
		
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    huart->RxCpltCallback(huart);
#else
    HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
		return;
	}

这段代码的位置如下图所示:

主函数中我们自己添加的代码:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        //这是我们自己添加的代码,让LED灯循环闪烁。
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
		HAL_Delay(200);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
		HAL_Delay(200);
		
  }
  /* USER CODE END 3 */
}

当然我们的主函数没有意义,实际功能是在串口回调函数中实现的,目的就是把接收到的数据重新返回给串口助手,效果图如下:

可以看到   当我们给单片机发送一帧数据时,单片机会把同样的数据返回给我们。

注意:在串口初始化程序中我们一定要添加以下两行代码:

  /* USER CODE BEGIN USART1_Init 2 */
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
  /* USER CODE END USART1_Init 2 */

并且在串口回调函数中,接收完一帧数据后,需要重新打开串口的DMA接收。

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值