参考帖子:https://blog.csdn.net/freedompoi/article/details/122350866
目前想要实现STM32F4自带的DMA双缓冲区,尝试过一版,结果不能预期,就使用了RxHalfCplt和RxCplt去实现DMA双缓冲区的效果。
现在有时间了,又重新实现STM32F4自带的DMA双缓冲区,作为参考。
MCU:STM32F429ZIT6
开发环境:STM32CubeMX+MDK5
此时,双击完后会关闭此界面,然后打开一个新界面。
然后,我们开始基本配置。
现在我们选择一个LED作为系统LED,该步骤可以忽略,只是本人喜欢这样子。以硬件原理图的LD3为例子。
基本配置除了时钟树外,基本上已经配置好了。
现在配置时钟树
基本配置已经配置完,现在开始配置实验使用的内容。
配置USART1,打开USART中断。并打开DMA。
配置FreeRTOS
配置完成,完善工程,生成工程。
到此,STM32CubeMX工具的使用结束!可以发现在桌面已经生成了DMA_DoubleBuf工程。
使用MDK5打开SDCard_rw工程打开。点击魔法棒,勾选微库。选择对应的下载器,勾选下载完复位允许。
在usart.h文件中,加入内容。
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include "cmsis_os.h"
#include <semphr.h>
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
#define UART_BUFF_SIZE 30
#pragma pack(4)
typedef struct
{
uint16_t len;
uint8_t data[UART_BUFF_SIZE];
}usart_multibuffer_data;
#pragma pack()
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
void UART_DMA_MultiBuffer(void);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
在usart.c文件中,加入内容。
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
QueueHandle_t queue_mes;
usart_multibuffer_data uart_buf[2];
//DMA 缓存0 传输结束回调函数
void DMA_M0_RC_Callback(DMA_HandleTypeDef *hdma)
{
BaseType_t xHigherPriorityTaskWoken;
uart_buf[0].len = hdma->Instance->NDTR;
xQueueSendFromISR(queue_mes,&uart_buf[0],&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
//DMA 缓存1 传输结束回调函数
void DMA_M1_RC_Callback(DMA_HandleTypeDef *hdma)
{
BaseType_t xHigherPriorityTaskWoken;
uart_buf[1].len = hdma->Instance->NDTR;
xQueueSendFromISR(queue_mes,&uart_buf[1],&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
//DMA 传输错误回调函数
void DMA_Error_Callback(DMA_HandleTypeDef *hdma)
{
//里面做一些异常处理
}
/* 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 = 115200;
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 */
/* 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_MEDIUM;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_usart1_rx.XferCpltCallback = DMA_M0_RC_Callback;
hdma_usart1_rx.XferM1CpltCallback = DMA_M1_RC_Callback;
hdma_usart1_rx.XferErrorCallback = DMA_Error_Callback;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 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 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
//使能DMA
void UART_DMA_MultiBuffer(void)
{
uint32_t u32wk0;
SET_BIT(huart1.Instance->CR3,USART_CR3_DMAR);
HAL_DMAEx_MultiBufferStart_IT(&hdma_usart1_rx,
(uint32_t)(&huart1.Instance->DR),
(uint32_t)&uart_buf[0].data[0],
(uint32_t)&uart_buf[1].data[0],
UART_BUFF_SIZE);
//这里是解决DMA在启动时,如果接收到大量数据会出现死机的问题
u32wk0 = huart1.Instance->SR;
u32wk0 = huart1.Instance->DR;
UNUSED(u32wk0);
}
/* USER CODE END 1 */
在main函数中,加入内容。
/**
* @brief The application entry point.
* @retval int
*/
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 */
queue_mes = xQueueCreate(10, sizeof(usart_multibuffer_data));
UART_DMA_MultiBuffer();
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
在freertos.c文件中
extern usart_multibuffer_data uart_buf[2];
extern QueueHandle_t queue_mes;
usart_multibuffer_data queue_data;
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
BaseType_t ret = pdFALSE;
/* Infinite loop */
for(;;)
{
ret = xQueueReceive(queue_mes,&queue_data,portMAX_DELAY);
if(ret == pdTRUE)
{
HAL_UART_Transmit(&huart1,queue_data.data,queue_data.len,100);
}
}
/* USER CODE END StartDefaultTask */
}
实验效果
时代越来越好,开发效率越来越高,希望能帮助到你!!!
还有就是,开源万岁。
评论(0)
您还未登录,请登录后发表或查看评论