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

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

优质博文,求个赞不过分吧。
在这里插入图片描述

单片只因图镇贴!

在这里插入图片描述

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会加上回车换行这俩个字符。
到此实验结束。

如果没有数据,请检查串口连接及串口重定向。
用爱发电,真的很详细了。
在这里插入图片描述

  • 23
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
利用STM32 HAL实现串口DMA发送和不定数据接收的方法如下: 1. 串口DMA发送: 首先,需要初始化串口DMA相关的参数。通过HAL_UART_Init()函数初始化串口,设置波特率、数据位、停止位等参数。然后使用HAL_UART_Transmit_DMA()函数启动DMA发送,将发送数据缓冲区的指针和数据度传入该函数。 2. 不定数据接收: 在接收数据时,我们可以使用DMA模式配合中断来实现不定度的数据接收。首先,需要初始化串口DMA相关的参数,与串口DMA发送相同。然后,使用HAL_UART_Receive_DMA()函数启动DMA接收,将接收数据存放到接收缓冲区中。 在接收数据的过程中,可以通过中断方式来判断数据是否接收完成。在中断处理函数中,可以读取接收数据缓冲区的数据,并根据接收到的数据进行处理。在处理完数据之后,可以继续启动DMA接收,以进行下一次的数据接收。 需要注意的是,在中断处理函数中,需要判断DMA接收是否完成,可以通过检查DMA接收状态寄存器的标志位来判断。如果DMA接收完成,则可以执行相应的操作,比如解析接收到的数据。 总结: 利用STM32 HAL库,可以方便地实现串口DMA发送和不定数据接收。通过初始化相关参数,并启动串口DMA发送和接收,可以实现高效的数据传输。在中断处理函数中,可以对接收到的数据进行处理,并根据需要继续启动DMA接收。这种方法适用于需要在接收端实时处理不定度的数据的场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值