【STM32 HAL 详解】CubeIDE实现DMA接收不定长数据和串口重定向

基于STM32G0,使用DMA方式,实现串口接收不定长的数据

目录

  • 基于STM32G0,使用DMA方式,实现串口接收不定长的数据
  • 1.图形化操作
  • 1.1.配置串口基本参数
  • 1.2.增加发送和接收DMA
  • 1.3.开启中断
  • 1.4.配置时钟树
  • 1.5.生成代码
  • 2.用户代码
  • 2.1.usart修改
  • 2.2.修改串口中断函数
  • 3.结果测试
  • 4.实验结果
  • 优质博文,求个赞不过分吧。

    单片只因图镇贴!

    1.图形化操作

    1.1.配置串口基本参数

    使能串口,异步模式,参数:115200,8,None,1。io为默认引脚。

    1.2.增加发送和接收DMA

    点击ADD

    1.3.开启中断

    NVIC中勾选使能中断

    1.4.配置时钟树

    g0支持64m。

    1.5.生成代码

    勾选生成独立的.c和h文件

    点击生成代码

    2.用户代码

    2.1.usart修改

    注意: 用户一定要放置在CUBE IDE生成的代码,指定注释的下面。如:/* USER CODE END 0 */

    usart.c如下位置定义变量。

    代码:

    volatile uint8_t USART1_RX_LEN = 0;              // 接收一帧数据的长度
    volatile uint8_t USART1_RECV_CPLT_FLAG = 0;      // 一帧数据接收完成标志
    uint8_t USART1_RX_BUF[USART1_RX_BUF_SIZE]={0};   // 接收数据缓冲区
    

    在MX_USART1_UART_Init函数的末尾,写入如下代码。

    代码:

    /* 使能空闲中断 */
      __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
      HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);
    

    usart.h 修改如下

    代码如下:

    包括头文件

    #include "stdio.h"
    

    声明

    #define USART1_RX_BUF_SIZE 512
    extern volatile uint8_t USART1_RX_LEN;              // 接收一帧数据的长度
    extern volatile uint8_t USART1_RECV_CPLT_FLAG;      // 一帧数据接收完成标志
    extern uint8_t USART1_RX_BUF[USART1_RX_BUF_SIZE];   // 接收数据缓冲区
    

    2.2.修改串口中断函数

    stm32g0xx_it.c文件中先添加头文件

    #include "usart.h"
    

    然后,USART1_IRQHandler函数修改如下:

    代码:

    void USART1_IRQHandler(void)
    {
      /* USER CODE BEGIN USART1_IRQn 0 */
    	uint32_t tmp_flag = 0;
    	uint32_t temp;
    
      /* USER CODE END USART1_IRQn 0dr&huart1);
      /* USER CODE BEGIN USART1_IRQn 1 */
      if(USART1 == huart1.Instance)
      {
          tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
    
          if((tmp_flag != RESET))//idle标志被置位
          {
              __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
              HAL_UART_DMAStop(&huart1);
              temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数
              USART1_RX_LEN =  USART1_RX_BUF_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
    
              USART1_RECV_CPLT_FLAG = USART1_RX_LEN?1:0;  // 如果接收到数据,设置完成标志
              HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);//重新打开DMA接收
          }
      }
      /* USER CODE END USART1_IRQn 1 */
    }
    

    3.结果测试

    main.c包括头文件:

    #include <string.h>
    

    main.c串口printf重定向

    代码:

    #ifdef __GNUC__
    /* With GCC, small printf (option LD Linker->Libraries->Small printf
       set to 'Yes') calls __io_putchar() */
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif /* __GNUC__ */
    
    /**
      * @brief  Retargets the C library printf function to the USART.
      * @param  None
      * @retval None
      */
    PUTCHAR_PROTOTYPE
    {
      /* Place your implementation of fputc here */
      /* e.g. write a character to the USART3 and Loop until the end of transmission */
      HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
    
      return ch;
    }
    

    main函数的while(1)测试代码如下:

    /* USER CODE BEGIN WHILE */
      printf("hello world\r\n");
      while (1)
      {
    	if(USART1_RECV_CPLT_FLAG ==1)
    	{
    		printf("rx_len=%d\r\n",USART1_RX_LEN);//打印接收长度
    		HAL_UART_Transmit(&huart1,USART1_RX_BUF, USART1_RX_LEN,200);//接收数据打印出来
    
    		// 清除数据
    		memset(USART1_RX_BUF,0,USART1_RX_BUF_SIZE);
    		USART1_RX_LEN=0;//清除计数
    		USART1_RECV_CPLT_FLAG=0;//清除接收结束标志位
    	}
    	HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);//重新打开DMA接收
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
    

    烧录程序:

    4.实验结果

    打开串口工具。单片机复位上电后,先打印hello world

    发送hi,显示如下

    因为勾选了发送新行所以,len会加上回车换行这俩个字符。
    到此实验结束。

    如果没有数据,请检查串口连接及串口重定向。
    用爱发电,真的很详细了。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【STM32 HAL 详解】CubeIDE实现DMA接收不定长数据和串口重定向

    发表评论