STM32的存储结构

(图由哔哩哔哩大佬的视频里截的图,如有侵权请联系我)

STM32的DMA(Direct Memory Access,直接存储器访问)

是一种硬件机制,允许在微控制器的外设和存储器之间进行高效的数据传输,而不需要CPU的干预。这种机制可以显著提高数据传输的效率,减轻CPU的负担,从而提高系统的整体性能。

STM32微控制器中的DMA控制器具有以下特点:

  1. 通道数量:STM32的DMA控制器通常有多个通道(例如STM32F4系列有7个通道),每个通道可以独立配置,用于不同外设的数据传输。

  2. 数据传输类型:DMA支持多种数据传输类型,包括字节(8位)、半字(16位)和字(32位)。

  3. 传输模式:DMA支持单次传输模式和循环传输模式。在循环传输模式下,DMA会在完成一次传输后自动重新开始,这对于连续的数据流传输非常有用。

  4. 增量模式:DMA可以配置为增量模式,其中源地址和/或目标地址在每次传输后自动增加,也可以配置为非增量模式,地址保持不变。

  5. 优先级:DMA通道可以配置不同的优先级,以控制通道之间的访问顺序。

  6. 中断和事件:DMA传输可以配置为在传输完成、半传输完成、传输错误等情况时产生中断,以便于软件进行相应的处理。

  7. 数据流控制:DMA可以与各种外设接口,如ADC、DAC、SPI、I2C、UART等,以及内部Flash和SRAM进行数据传输。

在使用STM32的DMA时,通常需要进行以下步骤:

  • 配置DMA通道:设置传输的数据宽度、增量模式、传输模式、优先级等。
  • 设置源地址和目标地址:指定数据传输的起始地址。
  • 设置数据传输量:指定要传输的数据量。
  • 启动DMA传输:配置完成后,启动DMA传输。
  • 处理中断:如果启用了中断,需要在中断服务函数中处理传输完成等事件。
  • 重点

    (uint32_t)&变量     可以得出变量的地址         //

    变量存储在SRAM中

    常量存储在闪存中     //c中  在变量前面加(const)括号内的单词即为常量不可改变的量

    STM32cude 设置

    关于STM32_DMA_的函数

    1. HAL_DMA_Init: 初始化DMA句柄,配置DMA通道的参数,如方向、增量模式、数据对齐方式、传输模式和优先级等

    2. HAL_DMA_DeInit: 反初始化DMA句柄,将DMA通道的配置恢复到默认状态。

    3. HAL_DMA_Start: 启动DMA传输。

    4. HAL_DMA_Start_IT: 启动DMA传输,并启用中断。当DMA传输完成或发生错误时,会产生中断。

    5. HAL_DMA_Stop: 停止DMA传输。

    6. HAL_DMA_Abort: 中止DMA传输。

    7. HAL_DMA_PollForTransfer: 轮询DMA传输完成状态。

    8. HAL_DMA_GetState: 获取DMA传输的状态。

    9. HAL_DMA_GetError: 获取DMA传输的错误码。

    10. HAL_DMA_IRQHandler: DMA中断处理函数。在这个函数中,你需要根据DMA中断状态来处理传输完成、半传输完成、传输错误等情况。

    11. HAL_DMA_RegisterCallback: 注册DMA回调函数,以便在DMA传输完成或发生错误时调用。

    12. 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 */
    

    作者:快秃头的码农

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32_HAL_DMA

    发表回复