1、HAL库UART 中断|DMA 自动回显接收数据

1、实现代码:

stm32f4xx_hal_conf.h文件开启UART宏定义

#define HAL_UART_MODULE_ENABLED

添加stm32f4xx_hal_uart.c和stm32f4xx_hal_dma.c到自己工程;
编写好的代码:usart_Driver.c

/**********************************************************************
*file:串口驱动
*author:残梦
*date:2023.2.13
*note:
**********************************************************************/
#include "usart_Driver.h"

#define UART1_BAUDRATE 2000000 //波特率
#define UART1_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART1_RX_GPIO_PORT              GPIOA
#define UART1_RX_GPIO_PIN               GPIO_PIN_10
#define UART1_RX_AF                     GPIO_AF7_USART1

#define UART1_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART1_TX_GPIO_PORT              GPIOA
#define UART1_TX_GPIO_PIN               GPIO_PIN_9
#define UART1_TX_AF                     GPIO_AF7_USART1

UART_HandleTypeDef huart1;

#ifndef _UART1_RX_MODE
    DMA_HandleTypeDef hdma_usart1_rx;
#endif
uint8_t huart1_RxData[50] = {0};
/****************************************************
@function:串口1初始化
@param:void
@return:void
@date:2023.2.13
@note:
****************************************************/
void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = UART1_BAUDRATE;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    if(HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}

    #ifdef _UART1_RX_MODE
        HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));
    #else
        HAL_UART_Receive_DMA(&huart1,huart1_RxData,sizeof(huart1_RxData));
    #endif
}

/****************************************************
@function:串口1
@param:void
@return:void
@date:2023.2.13
@note:
****************************************************/
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_USART1_CLK_ENABLE();
    UART1_RX_GPIO_CLK_ENABLE();
    UART1_TX_GPIO_CLK_ENABLE();

    //外设引脚初始化
    GPIO_InitStruct.Pin = UART1_RX_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = UART1_RX_AF;
    HAL_GPIO_Init(UART1_RX_GPIO_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = UART1_TX_GPIO_PIN;
    GPIO_InitStruct.Alternate = UART1_TX_AF;
    HAL_GPIO_Init(UART1_TX_GPIO_PORT, &GPIO_InitStruct);

    #ifdef _UART1_RX_MODE
        HAL_NVIC_SetPriority(USART1_IRQn,1,0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
    #else
        __HAL_RCC_DMA2_CLK_ENABLE();
        hdma_usart1_rx.Instance = DMA2_Stream2;
        hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
        hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
        hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
        hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
        hdma_usart1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
        hdma_usart1_rx.Init.MemBurst = DMA_MBURST_SINGLE;
        hdma_usart1_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
        if(HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK){Error_Handler();}

        __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);//关联DMA句柄
        HAL_NVIC_SetPriority(DMA2_Stream2_IRQn,0,0);
        HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
    #endif
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发

    #ifdef _UART1_RX_MODE
        HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));//中断方式接收则需开启,否则会导致接收完指定数据个数后自动关闭
    #endif
}

usart_Driver.h

#ifndef _usart_Driver_H_
#define _usart_Driver_H_
#include "Common_Driver.h"
//#define _UART1_RX_MODE //未定义--DMA方式接收,定义--中断接收方式

extern UART_HandleTypeDef huart1;
extern void MX_USART1_UART_Init(void);

#endif

在stm32f4xx_it.c文件中添加中断处理函数:

/* USER CODE BEGIN 1 */
#include "usart_driver.h"
#ifdef _UART1_RX_MODE
void USART1_IRQHandler(void)
{
  extern UART_HandleTypeDef huart1;
  HAL_UART_IRQHandler(&huart1);
}
#else
void DMA2_Stream2_IRQHandler(void)
{
  extern DMA_HandleTypeDef hdma_usart1_rx;
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
#endif
/* USER CODE END 1 */
```c
/****************************************************
@function:串口重定义
@param:void
@return:void
@date:2023.2.14
@note:使用printf时需要此函数,并在Keil魔术棒中勾选User MicroLIB库
****************************************************/
int fputc(int ch,FILE *f)
{
    uint8_t data = ch;
	HAL_UART_Transmit(&huart1,&data,1,1);
	return(ch);
}

主函数调用MX_USART1_UART_Init();即可实现自收自发
在这里插入图片描述

2、电路推荐:CH340N

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、初始化处理框架 MX_USART1_UART_Init()

void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = UART1_BAUDRATE;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    if(HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}

    #ifdef _UART1_RX_MODE
        HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));
    #else
        HAL_UART_Receive_DMA(&huart1,huart1_RxData,sizeof(huart1_RxData));
    #endif
}

OverSampling :过采样
8倍过采样速度更快,最高速度可达fPCLK/8,fPCLK为USART时钟;
16倍过采样速度虽然没有8倍过采样那么快,但得到的数据更加精准,其最大速度为fPCLK/16;

那么HAL_UART_Init()里面做了什么呢?

移除参数检查,提取主要后

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
{
  if (huart->gState == HAL_UART_STATE_RESET)
  {
    /* Allocate lock resource and initialize it */
    huart->Lock = HAL_UNLOCKED;
    /* Init the low level hardware : GPIO, CLOCK */
    HAL_UART_MspInit(huart);
  }

  huart->gState = HAL_UART_STATE_BUSY;

  /* Disable the peripheral */
  __HAL_UART_DISABLE(huart);

  /* Set the UART Communication parameters */
  UART_SetConfig(huart);

  /* In asynchronous mode, the following bits must be kept cleared:
     - LINEN and CLKEN bits in the USART_CR2 register,
     - SCEN, HDSEL and IREN  bits in the USART_CR3 register.*/
  CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
  CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));

  /* Enable the peripheral */
  __HAL_UART_ENABLE(huart);

  /* Initialize the UART state */
  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->gState = HAL_UART_STATE_READY;
  huart->RxState = HAL_UART_STATE_READY;

  return HAL_OK;
}

所以这个函数顺序则先通过函数HAL_UART_MspInit()初始化底层硬件:GPIO, CLOCK
再调用UART_SetConfig()设置时串口通信参数
__HAL_UART_ENABLE()启用外围设备

那么HAL_UART_MspInit()里面做了什么呢?

该函数主要是初始化底层硬件:GPIO、CLOCK、DMA、中断
开启DMA时需要关联句柄

__HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);//关联DMA句柄

为什么使用的是DMA2_Stream2 且通道4呢
在这里插入图片描述
可以看到USART1挂载在APB2上
在这里插入图片描述
在这里插入图片描述
由此知晓DMA使用的流和通道

启动中断|DMA去接收数据

中断接收函数:HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef huart, uint8_t pData, uint16_t Size)
1、使用此函数值得注意的是此函数
Size参数代表接收的数据个数,在接收完该个数后会自动关闭中断,导致后续数据不去接收了**
所以在接收到数据回调函数中需要再次调用此函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发

    #ifdef _UART1_RX_MODE
        HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));//中断方式接收则需开启,否则会导致接收完指定数据个数后自动关闭
    #endif
}

2、使用前需开启串口中断

    HAL_NVIC_SetPriority(USART1_IRQn,1,0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

**DMA中断接收函数:HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef huart, uint8_t pData, uint16_t Size)
1、使用前需要开启DMA中断并关联DMA句柄

    __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);//关联DMA句柄
    HAL_NVIC_SetPriority(DMA2_Stream2_IRQn,0,0);
    HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);

中断函数调用HAL库处理函数中的处理

在stm32f4xx_it.c文件中添加中断处理函数:HAL_外设名_IRQHandler();
如HAL_UART_IRQHandler()或者HAL_DMA_IRQHandler();
注意:在HAL_UART_IRQHandler()函数中会调用函数:
函数中会在接收完指定数据个数后会执行的关闭中断(在使用函数HAL_UART_Receive_IT()时)

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
 ......省略
    if (--huart->RxXferCount == 0U)//此处就是在接收完指定数据个数后会执行的关闭中断
    {
      /* Disable the UART Data Register not empty Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      /* Disable the UART Parity Error Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;

      /* Check current reception Mode :
         If Reception till IDLE event has been selected : */
      if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
      {
      	......
      }
      else
      {
        /*Call legacy weak Rx complete callback*/
        HAL_UART_RxCpltCallback(huart);
      }
    }
 ......省略
}

HAL_DMA_IRQHandler()函数可是不会去关闭的哈

4、CubeMx UART 中断接收回显数据

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
生成代码即可
在这里插入图片描述
1、main.h中包含stdio.h文件

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

2、usart.c中
定义接收数据区变量

/* USER CODE BEGIN 0 */
uint8_t huart1_RxData[50] = {0};
/* USER CODE END 0 */

MX_USART1_UART_Init()函数中添加数据中断接收函数:

  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));
  /* USER CODE END USART1_Init 2 */

添加回调函数并发送接收到的数据

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发
  HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));//中断方式接收则需开启,否则会导致接收完指定数据个数后自动关闭
}

编写串口重定义函数,方便使用printf()

/****************************************************
@function:串口重定义
@param:void
@return:void
@date:2023.2.14
@note:使用printf时需要此函数,并在Keil魔术棒中勾选User MicroLIB库
****************************************************/
int fputc(int ch,FILE *f)
{
    uint8_t data = ch;
	HAL_UART_Transmit(&huart1,&data,1,1);
	return(ch);
}

在这里插入图片描述
usart.c

/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */
uint8_t huart1_RxData[50] = {0};
/* USER CODE END 0 */

UART_HandleTypeDef huart1;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 2000000;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));
  /* USER CODE END USART1_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
/****************************************************
@function:串口重定义
@param:void
@return:void
@date:2023.2.14
@note:使用printf时需要此函数,并在Keil魔术棒中勾选User MicroLIB库
****************************************************/
int fputc(int ch,FILE *f)
{
    uint8_t data = ch;
	HAL_UART_Transmit(&huart1,&data,1,1);
	return(ch);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发
  HAL_UART_Receive_IT(&huart1, huart1_RxData, sizeof(huart1_RxData));//中断方式接收则需开启,否则会导致接收完指定数据个数后自动关闭
}

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

UART 中断接收完整工程:
链接:https://pan.baidu.com/s/1p34JFrjOUl2_IsnvZBSn0w
提取码:au2o

## 5、CubeMx UART DMA中断接收回显数据

注意:除了USART1外其他配置和CubeMx UART 中断接收回显数据一样
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
产生工程代码
1、usart.c中
定义接收数据区变量

/* USER CODE BEGIN 0 */
uint8_t huart1_RxData[50] = {0};
/* USER CODE END 0 */

MX_USART1_UART_Init()函数中添加数据DMA中断接收函数:

  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_DMA(&huart1,huart1_RxData,sizeof(huart1_RxData));
  /* USER CODE END USART1_Init 2 */

添加回调函数并发送接收到的数据

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发
}

在这里插入图片描述
usart.c

/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */
uint8_t huart1_RxData[50] = {0};
/* USER CODE END 0 */

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 2000000;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_DMA(&huart1,huart1_RxData,sizeof(huart1_RxData));
  /* USER CODE END USART1_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA2_Stream2;
    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmarx);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart1,huart1_RxData,sizeof(huart1_RxData),10);//自收自发
}
/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

UART DMA接收完整工程:
链接:https://pan.baidu.com/s/15aVMAqIVg8DrLjlPVGY5ag
提取码:3nmu

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是HAL库中使用UART2和DMA中断配置代码示例: ``` // 定义DMAUART2的句柄 DMA_HandleTypeDef hdma_usart2_rx; UART_HandleTypeDef huart2; // 配置UART2和DMA接收 void MX_USART2_UART_Init(void) { // ... UART2的基本配置 ... // 配置DMA句柄 hdma_usart2_rx.Instance = DMA1_Stream5; hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4; hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart2_rx.Init.Mode = DMA_NORMAL; hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_usart2_rx); // 关联DMAUART2 __HAL_LINKDMA(&huart2, hdmarx, hdma_usart2_rx); // 使能UART2 IDLE中断 SET_BIT(huart2.Instance->CR1, USART_CR1_IDLEIE); // 使能DMA传输完成中断 __HAL_DMA_ENABLE_IT(&hdma_usart2_rx, DMA_IT_TC); } // UART2中断回调函数 void HAL_UART_IDLE_Callback(UART_HandleTypeDef *huart) { // 如果是UART2触发的中断 if (huart == &huart2) { // 关闭DMA传输 HAL_UART_DMAStop(&huart2); // 处理接收到的数据 // ... // 重新开启DMA传输 HAL_UART_Receive_DMA(&huart2, rx_buf, RX_BUF_SIZE); } } // DMA传输完成中断回调函数 void HAL_DMA_TC_Callback(DMA_HandleTypeDef *hdma) { // 如果是UART2触发的中断 if (hdma == &hdma_usart2_rx) { // 关闭DMA传输 HAL_UART_DMAStop(&huart2); // 处理接收到的数据 // ... // 重新开启DMA传输 HAL_UART_Receive_DMA(&huart2, rx_buf, RX_BUF_SIZE); } } // 启动UART2接收 void start_uart2_receive(void) { HAL_UART_Receive_DMA(&huart2, rx_buf, RX_BUF_SIZE); } ``` 以上代码中,我们定义了一个DMAUART2的句柄,然后在初始化函数中进行了DMAUART2的配置,包括了DMA数据传输方向、传输模式、优先级等参数的设置。接着我们使用了`__HAL_LINKDMA()`函数将DMAUART2关联起来,并使能了UART2的IDLE中断DMA的传输完成中断。最后我们在中断回调函数中处理接收到的数据,重新开启DMA传输。在程序中我们可以通过调用`start_uart2_receive()`函数启动UART2的接收。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值