2017-07-08 8 views
1

J'utilise un STM32F103, en essayant de copier d'un tableau à un autre en utilisant DMA. Le transfert fonctionne la première fois et un point d'arrêt dans DMA1_Channel1_IRQHandler est atteint, mais les appels suivants à DMA_Cmd(DMA1_Channel1, ENABLE) n'ont aucun effet et le point d'arrêt n'est pas atteint. Le drapeau d'erreur DMA1_FLAG_TE1 n'est pas défini. Y a-t-il quelque chose d'additionnel qui doit être réglé/réinitialisé pour que le transfert fonctionne une seconde fois?STM32 DMA La mémoire vers le transfert de mémoire ne se déclenche qu'une seule fois

#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); 
    } 
} 
+0

Vous définissez l'état à 0 dans si bloc, votre programme n'entrera pas la deuxième fois. Voulez-vous avoir un transfert continu et circulaire DMA ou le démarrer dans votre propre? – rkrahl

+0

Je n'ai pas remarqué de réglage de statut dans isr, la première partie du commentaire précédent n'est plus pertinente. – rkrahl

Répondre

1

Désactiver DMA avant de définir ses registres et l'activer par la suite. Selon RM0008 (page 287) DMA_CNDTRx ne peut être écrit que lorsque le canal est désactivé. La même chose vaut pour DMA_CMARx.

+1

Déplacement 'DMA_Cmd (DMA1_Channel1, DISABLE);' à la ligne avant de définir les registres a corrigé le problème, la transaction DMA s'exécute en continu comme prévu. – Batperson