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


目录

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


优质博文,求个赞不过分吧。

cubemx 串口 双工_stm32

单片只因图镇贴!

cubemx 串口 双工_stm32_02

1.图形化操作

1.1.配置串口基本参数

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

cubemx 串口 双工_嵌入式硬件_03

1.2.增加发送和接收DMA

点击ADD

cubemx 串口 双工_数据_04

1.3.开启中断

NVIC中勾选使能中断

cubemx 串口 双工_stm32_05

1.4.配置时钟树

g0支持64m。

cubemx 串口 双工_stm32_06

1.5.生成代码

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

cubemx 串口 双工_stm32_07

点击生成代码

cubemx 串口 双工_数据_08

2.用户代码

2.1.usart修改

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

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

cubemx 串口 双工_单片机_09

代码:

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函数的末尾,写入如下代码。

cubemx 串口 双工_数据_10

代码:

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

usart.h 修改如下

cubemx 串口 双工_stm32_11

代码如下:

包括头文件

#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函数修改如下:

cubemx 串口 双工_cubemx 串口 双工_12

代码:

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重定向

cubemx 串口 双工_单片机_13

代码:

#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 */
  }

烧录程序:

cubemx 串口 双工_嵌入式硬件_14

4.实验结果

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

发送hi,显示如下

cubemx 串口 双工_单片机_15

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

如果没有数据,请检查串口连接及串口重定向。

用爱发电,真的很详细了。

cubemx 串口 双工_stm32_16