Mise en oeuvre d'un DMA » History » Version 3

« Previous - Version 3/4 (diff) - Next » - Current version
Clement Jacob, 11/26/2010 08:44 AM


Mise en oeuvre d'un DMA

Présentation du DMA RX62N

L'utilisation d'un DMA lors d'un projet de développement sur microcontroleur est parfois fastidieuse et longue. Cependant, ce périphérique permet d'exploiter toute la puissance du microcontroleur. Dans le cas précis du RX62N, un DMA Controller est disponible, possédant lui même 4 canaux.

Exemple de démonstration proposé

Il est proposé ici de développer un code de démarrage simple, utilisant le DMA en mode répétition, sur source de déclenchement de type interruption. Concrètement, il s'agit d'effectuer l'acquisition de données analogique, via le convertisseur analogique/numérique, à cadence fixée par un timer. Un transfert est effectué automatiquement vers une zone de données en RAM, contenant 640 points. Cela illustre l'utilisation faite dans l'oscilloscope.

Code source associé

void main()
{
  Config_ADC();
  Config_TMR();
  Config_DMA();

  while (true);
}

void Config_ADC()
{
  SYSTEM.MSTPCRA.BIT.MSTPA22 = 0;        // Enable AD1 module
  AD1.ADCSR.BIT.ADIE = 0;             // No interrupts
  AD1.ADCSR.BIT.CH = 0;             // AN4 in continuous scan mode 
  AD1.ADCR.BIT.MODE = 2;             // Continuous scan mode
  AD1.ADCR.BIT.CKS = 3;             // Clock Select PCLK
  AD1.ADCR.BIT.TRGS = 0;            // Conversion starts by software
  AD1.ADDPR.BIT.DPSEL = 0;            // LSB padding
  AD1.ADCSR.BIT.ADST = 1;             // Start AD1    
}

void Config_TMR()
{
  MSTP(CMT2) = 0;
  CMT2.CMCOR = 18750/2; // Sampling frequency : 640Hz 
  CMT2.CMCR.BIT.CKS = 0; // Divide PCLK by 8 - 6MHz
  CMT.CMSTR1.BIT.STR2 = 1;
}

void Config_DMA()
{
  // Power on DMA module
  MSTP(DMACA) = 0;

  // Timer CMT2 will enable a transfert    
  ICU.DMRSR0 = 30;

  // Transfert from ADC - AN4    
  DMAC0.DMSAR = (void*)&AD1.ADDRA;

  // Transfert to RAM data - an array
  DMAC0.DMDAR = (void*)dma_data;

  // Transfert 640 x 16bits    
  DMAC0.DMCRA = (640<<16) + 640;

  DMAC0.DMCRB = 0;

  DMAC0.DMTMD.BIT.MD = 1; //Repeat mode
  DMAC0.DMTMD.BIT.DTS = 0; //Destination is the repeat area
  DMAC0.DMTMD.BIT.SZ = 1; //16 bits transfert
  DMAC0.DMTMD.BIT.DCTG = 1; //Interrupts are the transfert clock

  DMAC0.DMAMD.BIT.SM = 0; //Source is fixed - AN4
  DMAC0.DMAMD.BIT.SARA = 0;
  DMAC0.DMAMD.BIT.DM = 2; //Destination is incremented
  DMAC0.DMAMD.BIT.DARA = 0;

  DMAC0.DMCSL.BIT.DISEL = 0;

  DMAC0.DMINT.BIT.RPTIE = 1; // Repeat end interrupt enabled
  DMAC0.DMINT.BIT.ESIE = 1; // Repeat end interrupt enabled
  _IEN(_DMACA_DMAC0I) = 1; // Enable interrupt
  _IPR( _DMACA_DMAC0I ) = 6; // Priority

  DMAC.DMAST.BIT.DMST = 1; //DMA Module Enabled    
  DMAC0.DMCNT.BIT.DTE = 1; //Enable channel

  // Enable TMR interrupt
  CMT2.CMCR.BIT.CMIE = 1;    
  _IEN( _CMT2_CMI2 ) = 1; // Enable interrupt    
}