【问题标题】:STM32 Use DMA to generate bit pattern on GPIO PINSTM32 使用 DMA 在 GPIO PIN 上生成位模式
【发布时间】:2021-09-29 05:25:30
【问题描述】:

我正在尝试在 GPIO 引脚上生成位模式。我已经设置了 DMA 引擎以从 GPIO 引脚状态数组传输到 GPIO BSRR 寄存器

这是我用来配置 DMA 的代码

hdma_tim16_ch1_up.Instance = DMA1_Channel3;
hdma_tim16_ch1_up.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_tim16_ch1_up.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim16_ch1_up.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim16_ch1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tim16_ch1_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_tim16_ch1_up.Init.Mode = DMA_NORMAL;
hdma_tim16_ch1_up.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_tim16_ch1_up) != HAL_OK)
{
  Error_Handler();
}

/* Several peripheral DMA handle pointers point to the same DMA handle.
 Be aware that there is only one channel to perform all the requested DMAs. */
__HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_CC1],hdma_tim16_ch1_up);
__HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim16_ch1_up);

这是我用来设置传输的代码:

  uint32_t outputbuffer[] = {
  0x0000100,0x01000000,
  0x0000100,0x01000000,
  0x0000100,0x01000000,
  0x0000100,0x01000000,
  0x0000100,0x01000000,
  0x0000100,0x01000000,
  0x0000100,0x01000000
  /* ... */
  };

  if (HAL_DMA_Start_IT(htim16.hdma[TIM_DMA_ID_UPDATE], (uint32_t)outputbuffer,  (uint32_t)&GPIOG->BSRR, 14) != HAL_OK)
  {
    /* Return error status */
    return HAL_ERROR;
  }
  __HAL_TIM_ENABLE_DMA(&htim16,TIM_DMA_UPDATE);
  HAL_TIM_Base_Start_IT(&htim16);

我希望看到每次计数器溢出时,DMA 从数组传输 32 位并递增到下一个数组位置,直到 DMA CNDTR 寄存器读取 0。

我设置了一个 GPIO 引脚以在每次定时器溢出时进行切换,并在数组中设置了一个交替位模式。我希望这两个 GPIO 引脚的输出形状相似,但我在连接到 DMA 的线路上得到一个更长的脉冲。任何提示将不胜感激

【问题讨论】:

    标签: stm32 dma


    【解决方案1】:
    1. 将TIM2配置为输入捕捉直接模式(TIM2_CH1)

    2. 配置TIM2 DMA方向“内存到外设”

    3. 配置TIM2数据宽度半字/半字

    4. 将 GPIO 引脚配置为 GPIO_OUTPUT,例如 16 个引脚 GPIOD0..GPIOD15

    5. 从 HAL 库中复制并粘贴 HAL_TIM_IC_Start_DMA() 函数并为其命名 MY_TIM_IC_Start_DMA()

    6. 在 MY_TIM_IC_Start_DMA() 中找到 HAL_DMA_Start_IT() 函数调用

    7. 将 (uint32_t)&htim->Instance->CCR1 替换为 (uint32_t)&GPIOD->ODR

      如果 (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&GPIOD->ODR, (uint32_t)pData, Length) != HAL_OK)

    现在您可以通过调用来启动 DMA 到 GPIO 的传输 MY_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_1,(uint32_t*)gpioBuffer,GPIO_BUFFER_SIZE); 实际传输必须通过在 TIM2_CH1 输入引脚上提供脉冲来触发(例如,通过使用来自其他定时器通道的输出比较引脚)。这些脉冲最初用于将 Timer2 CCR1 寄存器值保存到 DMA 缓冲区。调整了代码以将 DMA 缓冲区值传输到 GPIOD ODR 寄存器。

    对于 GPIO 到内存的传输,将 TIM2 DMA 方向更改为“外设到内存”,将 GPIO 引脚配置为 GPIO_INPUT 并使用 GPIOD->IDR 代替修改后的 MY_TIM_IC_Start_DMA() 函数中的 HAL_DMA_Start_IT 参数中的 ODR

    【讨论】:

      猜你喜欢
      • 2020-06-17
      • 2017-09-04
      • 2017-04-14
      • 2021-08-17
      • 2019-10-25
      • 2019-03-17
      • 2014-06-27
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多