代码之家  ›  专栏  ›  技术社区  ›  Batperson

STM32 DMA内存到内存传输仅触发一次

  •  2
  • Batperson  · 技术社区  · 7 年前

    我正在使用STM32F103,试图使用DMA从一个阵列复制到另一个阵列。传输第一次工作,在 DMA1_Channel1_IRQHandler 被击中,但随后呼叫 DMA_Cmd(DMA1_Channel1, ENABLE) DMA1_FLAG_TE1

    #include "stm32f10x.h"
    
    #define ARRAYSIZE 800
    volatile uint32_t status = 0;
    volatile uint32_t i;
    
    
    int main(void)
    {
        uint32_t source[ARRAYSIZE];
        uint32_t destination[ARRAYSIZE];
        for (i=0; i<ARRAYSIZE;i++)
            source[i]=i;
    
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
        DMA_InitTypeDef  DMA_InitStructure;
        DMA_DeInit(DMA1_Channel1);
    
        DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = ARRAYSIZE;
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)source;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)destination;
    
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
    
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    
        status = 1;
    
        while (1)
          {
            if(status == 1)
            {
               status = 0;
    
               DMA1_Channel1->CNDTR = ARRAYSIZE;
               DMA1_Channel1->CPAR = (uint32_t)source;
               DMA1_Channel1->CMAR = (uint32_t)destination;
               DMA_ClearFlag(DMA1_FLAG_GL1);
               DMA_ClearFlag(DMA1_FLAG_TC1);
    
               DMA_Cmd(DMA1_Channel1, DISABLE);
               DMA_Cmd(DMA1_Channel1, ENABLE);
            }
          }
    }
    
    void DMA1_Channel1_IRQHandler(void)
    {
      if(DMA_GetITStatus(DMA1_IT_TC1))
      {
        status=1;
        DMA_ClearITPendingBit(DMA1_IT_GL1);
      }
    }
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   rkrahl    7 年前

    在设置其寄存器之前禁用DMA,然后启用它。根据 RM0008 (第287页)DMA_CNDTRx只能在信道禁用时写入。DMA_CMARx也是如此。