这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » NUCLEO-U083RC学习历程21-使用DMA方式从FLASH传输到SRAM

共1条 1/1 1 跳转至

NUCLEO-U083RC学习历程21-使用DMA方式从FLASH传输到SRAM

助工
2025-01-15 19:49:01     打赏

之前和大家分享过串口使用DMA传输的例子,今天和大家分享一下,使用DMA把数据缓冲区从flash中传输到SRAM中。

一:程序编写流程:

1.1:程序开始运行时,调用 HAL_Init() 函数来重置所有外围设备,

1.2 初始化 Flash 接口和系统,

1.3 调用SystemClock_Config() 配置CPU主频为 48 MHz 运行。

1.4 初始化DMA的初始化

1.5 编写DMA发送的函数

二:首先在cube中开始DMA1的通道

01-15-3.png如上图所示,软件配置时候,只需要配置DMA1的通道1的发送功能,并开始DMA的中断功能。

DMA控制函数编写流程:

DMA1_Channel1 配置为将存储在 Flash 存储器中的 32 字数据缓冲区的内容传输到 RAM 中声明的接收缓冲区。

传输的开始由软件触发。DMA1_Channel1 已启用内存到内存传输。源地址和目标地址递增也已启用。通过设置 DMA1_Channel1 的 channel enable bit 来开始传输。在传输结束时,会生成一个 Transfer Complete 中断,因为它已启用,并且回调函数被调用。

三:软件代码编写:

3.1 代码DMA的初始化函数:

static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* Configure DMA request hdma_memtomem_dma1_channel1 on DMA1_Channel1 */
  hdma_memtomem_dma1_channel1.Instance = DMA1_Channel1;
  hdma_memtomem_dma1_channel1.Init.Request = DMA_REQUEST_MEM2MEM;
  hdma_memtomem_dma1_channel1.Init.Direction = DMA_MEMORY_TO_MEMORY;
  hdma_memtomem_dma1_channel1.Init.PeriphInc = DMA_PINC_ENABLE;
  hdma_memtomem_dma1_channel1.Init.MemInc = DMA_MINC_ENABLE;
  hdma_memtomem_dma1_channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma_memtomem_dma1_channel1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  hdma_memtomem_dma1_channel1.Init.Mode = DMA_NORMAL;
  hdma_memtomem_dma1_channel1.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_memtomem_dma1_channel1) != HAL_OK)
  {
    Error_Handler( );
  }
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}


3.2  需要DMA传输的字节如下所示:

static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
{
  0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
  0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
  0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
  0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
  0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
  0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
  0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
  0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
};

static uint32_t aDST_Buffer[BUFFER_SIZE];

传输代码如下:

  /* Select Callbacks functions called after Transfer complete and Transfer error */
  HAL_DMA_RegisterCallback(&hdma_memtomem_dma1_channel1, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);
  HAL_DMA_RegisterCallback(&hdma_memtomem_dma1_channel1, HAL_DMA_XFER_ERROR_CB_ID, TransferError);
  
  /* Configure the source, destination and buffer size DMA fields and Start DMA Channel/Stream transfer */
  /* Enable All the DMA interrupts */
  if (HAL_DMA_Start_IT(&hdma_memtomem_dma1_channel1, (uint32_t)&aSRC_Const_Buffer, (uint32_t)&aDST_Buffer, BUFFER_SIZE) != HAL_OK)
  {
    /* Transfer Error */
    Error_Handler();
  }

代码测试截图如下所示:

image.png

可以看到执行好上述代码后,DMA将数据缓冲区从flash中传输到SRAM中

避坑经验:

1:可以通过修改文件 main.h 中的 defines 值来为 DMA 传输示例选择不同的通道。

2:使用 HAL_Delay() 时必须小心,此函数根据 SysTick ISR 中递增的变量提供准确的延迟(以毫秒为单位)。这意味着,如果 HAL_Delay() 是从外围 ISR 进程调用的,则 SysTick 中断必须具有比外围中断更高的优先级(数值上更低)。否则,调用方 ISR 进程将被阻止。要更改 SysTick 中断优先级,您必须使用 HAL_NVIC_SetPriority() 函数。

3:应用程序需要确保 SysTick 时基始终设置为 1 毫秒,才能执行正确的 HAL 操作。







关键词: NUCLEO-U083RC     串口     DMA内存传输    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]