STM32_HAL_DMA
STM32的存储结构
(图由哔哩哔哩大佬的视频里截的图,如有侵权请联系我)
STM32的DMA(Direct Memory Access,直接存储器访问)
是一种硬件机制,允许在微控制器的外设和存储器之间进行高效的数据传输,而不需要CPU的干预。这种机制可以显著提高数据传输的效率,减轻CPU的负担,从而提高系统的整体性能。
STM32微控制器中的DMA控制器具有以下特点:
-
通道数量:STM32的DMA控制器通常有多个通道(例如STM32F4系列有7个通道),每个通道可以独立配置,用于不同外设的数据传输。
-
数据传输类型:DMA支持多种数据传输类型,包括字节(8位)、半字(16位)和字(32位)。
-
传输模式:DMA支持单次传输模式和循环传输模式。在循环传输模式下,DMA会在完成一次传输后自动重新开始,这对于连续的数据流传输非常有用。
-
增量模式:DMA可以配置为增量模式,其中源地址和/或目标地址在每次传输后自动增加,也可以配置为非增量模式,地址保持不变。
-
优先级:DMA通道可以配置不同的优先级,以控制通道之间的访问顺序。
-
中断和事件:DMA传输可以配置为在传输完成、半传输完成、传输错误等情况时产生中断,以便于软件进行相应的处理。
-
数据流控制:DMA可以与各种外设接口,如ADC、DAC、SPI、I2C、UART等,以及内部Flash和SRAM进行数据传输。
在使用STM32的DMA时,通常需要进行以下步骤:
重点
(uint32_t)&变量 可以得出变量的地址 //
变量存储在SRAM中
常量存储在闪存中 //c中 在变量前面加(const)括号内的单词即为常量不可改变的量
STM32cude 设置
关于STM32_DMA_的函数
-
HAL_DMA_Init: 初始化DMA句柄,配置DMA通道的参数,如方向、增量模式、数据对齐方式、传输模式和优先级等。
-
HAL_DMA_DeInit: 反初始化DMA句柄,将DMA通道的配置恢复到默认状态。
-
HAL_DMA_Start: 启动DMA传输。
-
HAL_DMA_Start_IT: 启动DMA传输,并启用中断。当DMA传输完成或发生错误时,会产生中断。
-
HAL_DMA_Stop: 停止DMA传输。
-
HAL_DMA_Abort: 中止DMA传输。
-
HAL_DMA_PollForTransfer: 轮询DMA传输完成状态。
-
HAL_DMA_GetState: 获取DMA传输的状态。
-
HAL_DMA_GetError: 获取DMA传输的错误码。
-
HAL_DMA_IRQHandler: DMA中断处理函数。在这个函数中,你需要根据DMA中断状态来处理传输完成、半传输完成、传输错误等情况。
-
HAL_DMA_RegisterCallback: 注册DMA回调函数,以便在DMA传输完成或发生错误时调用。
-
HAL_DMA_UnRegisterCallback: 注销DMA回调函数。
main.h源码
将数组的值写到另一个数组中在打印
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @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 */
//定义数组
uint32_t srcArray[10]={1,2,3,4,5,6,7,8,9,10};//源数据
uint32_t decArray[10];//要写入的地方
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//开启DMA 1:DMA指针 2:源地址 3:写入的地址 4:长度
HAL_DMA_Start(&hdma_memtomem_dma1_channel1,(uint32_t)srcArray,(uint32_t)decArray,10);
//重点HAL_DMA_PollForTransfer不然数据会错 HAL_DMA_FULL_TRANSFER表示传输完成 HAL_MAX_DELAY无限时间
if (HAL_DMA_PollForTransfer(&hdma_memtomem_dma1_channel1, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY) == HAL_OK)
{
// 存储数据
char data_char[48];
// 转换类型
sprintf(data_char, "数据为: %d %d %d %d %d %d %d %d %d %d",
decArray[0], decArray[1], decArray[2], decArray[3], decArray[4], decArray[5], decArray[6], decArray[7], decArray[8], decArray[9]);
// 打印数据
HAL_UART_Transmit(&huart1, (uint8_t*)data_char, 47, 30);
}
for(int i=0;i<10;i++){
srcArray[i]=srcArray[i]+1;
}
HAL_Delay(3000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
作者:快秃头的码农