lpcware

LPC1769 ADC hw triggered and DMA

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by salentu on Mon Mar 19 04:00:31 MST 2012
Hi everybody.
I'm using LPCXpresso LPC1769 to implement an  application that reads 2 ADC channels repeatedly (but limited) and  stores data into RAM memory by DMA. I need to sample 2 voltage ramps  (duration from 0.02 to 0.2 seconds, number of samples 1000 for each  channel). So I need repeated fast conversions. I thought that the best  way to develop this application is to try HW conversions triggered on  timer0 MR1 and DMA transfer to RAM memory; repeated conversions are made  by properly setting MR1 value.

As first step, I developed the  following simple code, considering LPCxpresso examples. I use only  channel AD0.0, CPU frequency 104MHz, ADC frequency 13MHz (in order to  have fast conversions -5micros for each channel?). DMA transfer size is  1, source is AD0.0, destination is RAM 0x2007C000 (incremented on every  transfer). Match event occours every second, for simplicity.

Debug  result (I stop it after few seconds) is that only one conversion is  made, so only one sample is stored in RAM. I expect one conversion on  every match event between TC and MR1, so one every second. Is this right  or wrong?
What I'm missing? Is my code correct?

Thanks a lot for the help.
Best regards


#define XTAL            (12000000UL)        /* Oscillator frequency               */
#define OSC_CLK         (      XTAL)        /* Main oscillator frequency       */
#define ADC_NUM           1                  
#define ADC_CLK            13000000            /* set to 13Mhz */ 
#define DMA_SRC0         (LPC_ADC_BASE+ADC_OFFSET)
#define DMA_SRC1         (DMA_SRC0+0x04)
#define DMA_DST0         LPC_AHBRAM0_BASE
#define DMA_DST1         LPC_AHBRAM1_BASE
#define DMA_DST           LPC_RAM_BASE
#define DMA_ADC          4
#define DMA_SIZE          1
#define ADC_OFFSET      0x10
#define ADC_INDEX       4
extern volatile uint32_t ADCValue[ADC_NUM];

int main (void)
{
  uint32_t i = 0;
  /* Clock Setup ----- SystemInit */
  LPC_SC->SCS         = 0x00000020;
  if (0x00000020 & (1 << 5))                  /* If Main Oscillator is enabled      */
  {
    while ((LPC_SC->SCS & (1<<6)) == 0);  
  }
  LPC_SC->CCLKCFG   = 0x00000003;          
  LPC_SC->PCLKSEL0  = 0x01000014;          
  LPC_SC->PCLKSEL1  = 0x00040000;
  LPC_SC->CLKSRCSEL = 0x00000001;         
  LPC_SC->PLL0CFG   = 0x00020033;    /* MSEL0 = 51 , NSEL0 = 2 */
  LPC_SC->PLL0CON   = 0x01;                
  LPC_SC->PLL0FEED  = 0xAA;                  
  LPC_SC->PLL0FEED  = 0x55;
  while (!(LPC_SC->PLL0STAT & (1<<26)));   
  LPC_SC->PLL0CON   = 0x03;                
  LPC_SC->PLL0FEED  = 0xAA;                   
  LPC_SC->PLL0FEED  = 0x55;
  LPC_SC->USBCLKCFG = 0x00000000;           
  LPC_SC->PCONP     = 0x00000000;           
  LPC_SC->CLKOUTCFG = 0x000000C0;           
  LPC_SC->FLASHCFG  = 0x0000503A;           
  /* SystemFrequency ----- 104 MHz */
  SystemFrequency = (OSC_CLK *
                      (((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
                      (((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1))   /
                      ((LPC_SC->CCLKCFG & 0xFF)+ 1));
    /* Initialize ADC  */
  /* Enable CLOCK into ADC controller */
  LPC_SC->PCONP |= (1 << 12);
  for ( i = 0; i < ADC_NUM; i++ )
  {
    ADCValue = 0x0;
  }
  LPC_PINCON->PINSEL1 &= ~0x0003C000;    /* P0.23~24, A0.0~1 */
  LPC_PINCON->PINSEL1 |= 0x00014000;
  LPC_PINCON->PINMODE1 &= ~0x0003C000;
  LPC_PINCON->PINMODE1 |= 0x00028000;
  LPC_ADC->CR = ( 0x1 << 0 ) |                 
        ( ( SystemFrequency  / ADC_CLK - 1 ) << 8 ) |    
        ( 0 << 16 ) |                            
        ( 1 << 21 ) |                             
        ( 4 << 24 ) |      /* START = 4 --- start HW conversion on match event */
        ( 0 << 27 );      /* EDGE = 0 MAT signal rising, trigger A/D  */
  LPC_ADC->INTEN = 0xFF;        /* 0xFF Enable all interrupts */
  /* ADC Interrupt is needed, but NVIC is not necessary for ADC DMA. */
  NVIC_DisableIRQ(ADC_IRQn);
  /* Initialize DMA  */
  LPC_SC->PCONP |= (1 << 29);           
  LPC_GPDMA->Sync = 0xFFFF;               
  LPC_SC->DMAREQSEL = 0x0000;
  LPC_GPDMA->IntTCClear = 0x03;
  LPC_GPDMA->IntErrClr = 0x03;
  LPC_GPDMA->Config = 0x01;               
  while ( !(LPC_GPDMA->Config & 0x01) );
  NVIC_EnableIRQ(DMA_IRQn);
  /* Initialize DMA Channel 0  */
  LPC_GPDMA->IntTCClear = 0x01<<0;
  LPC_GPDMA->IntErrClr = 0x01<<0;
  LPC_GPDMACH0->CControl = 0;
  LPC_GPDMACH0->CConfig = 0;
  LPC_GPDMACH0->CSrcAddr = DMA_SRC0;
  LPC_GPDMACH0->CDestAddr = DMA_DST0;
  LPC_GPDMACH0->CControl = (DMA_SIZE & 0xFFF)|(0x00<<12)
          |(0x00<<15)|(0x02<<18)|(0x02<<21)|(0<<26)|(1<<27)|0x80000000;
  LPC_GPDMACH0->CConfig = 0xC001|(DMA_ADC<<1)|(0x00<<6)|(0x02<<11);
  /* Initialize Timer 0 and enable  */
  LPC_SC->PCONP |= (0x01<<1);
  LPC_TIM0->IR = 0xF;    /* Clear MATx interrupt include DMA request */
  LPC_TIM0->CTCR  = 0x0;
  LPC_TIM0->PR  = 0x00000000;
  LPC_TIM0->MR1 = 100000000;   /* conversion every second */
  LPC_TIM0->EMR &= ~(0xFF<<4);
  LPC_TIM0->EMR |= (0x3<<6);
  LPC_TIM0->MCR = (0x3<<3);        /* Interrupt and Reset on MR1 */
  NVIC_EnableIRQ(TIMER0_IRQn);
  LPC_TIM0->TCR = 1;
  while ( 1 );                   
}

Outcomes