lpc1768 adc at sampling rate of 200KHz

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

lpc1768 adc at sampling rate of 200KHz

1,923 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dipali on Thu Jun 02 05:10:06 MST 2016
For one of my application i want to use lpc1768's adc at full speed i.e 200 KHz. I have enabled burst mode and read data for 5000 samples but it is reading data at 30 KHz.
I have tried by changing crystal to 20 MHz which was earlier 12 MHz
I dont know whether I m making any mistake in clock configuration or some other prblm is there
my clock system_lpc17xx.c file code
#define CLOCK_SETUP           1
#define SCS_Val               0x00000020
#define CLKSRCSEL_Val         0x00000001
#define PLL0_SETUP            1
#define PLL0CFG_Val           0x0000000B//0x00050063
#define PLL1_SETUP            1
#define PLL1CFG_Val           0x00000023
#define CCLKCFG_Val           0x00000003
#define USBCLKCFG_Val         0x00000000
#define PCLKSEL0_Val          0x00000000
#define PCLKSEL1_Val          0x00000000
#define PCONP_Val             0x042887DE
#define CLKOUTCFG_Val         0x00000000

/*----------------------------------------------------------------------------
  Define clocks
 *----------------------------------------------------------------------------*/
#define XTAL        (20000000UL)        /* Oscillator frequency               */
#define OSC_CLK     (      XTAL)        /* Main oscillator frequency          */
#define RTC_CLK     (   32768UL)        /* RTC oscillator frequency           */
#define IRC_OSC     ( 4000000UL)        /* Internal RC oscillator frequency   */


/* F_cco0 = (2 * M * F_in) / N  */
#define __M               (((PLL0CFG_Val      ) & 0x7FFF) + 1)//0x64
#define __N               (((PLL0CFG_Val >> 16) & 0x00FF) + 1) //0x06
#define __FCCO(__F_IN)    ((2 * __M * __F_IN) / __N)
#define __CCLK_DIV        (((CCLKCFG_Val      ) & 0x00FF) + 1)//4

/* Determine core clock frequency according to settings */
 #if (PLL0_SETUP) //true
    #if   ((CLKSRCSEL_Val & 0x03) == 1)
        #define __CORE_CLK (__FCCO(OSC_CLK) / __CCLK_DIV) //100 MHz
    #elif ((CLKSRCSEL_Val & 0x03) == 2)
        #define __CORE_CLK (__FCCO(RTC_CLK) / __CCLK_DIV)
    #else
        #define __CORE_CLK (__FCCO(IRC_OSC) / __CCLK_DIV)
    #endif
 #else
    #if   ((CLKSRCSEL_Val & 0x03) == 1)
        #define __CORE_CLK (OSC_CLK         / __CCLK_DIV)
    #elif ((CLKSRCSEL_Val & 0x03) == 2)
        #define __CORE_CLK (RTC_CLK         / __CCLK_DIV)
    #else
        #define __CORE_CLK (IRC_OSC         / __CCLK_DIV)
    #endif
 #endif

void SystemCoreClockUpdate (void)            /* Get Core Clock Frequency      */
{
  /* Determine clock frequency according to clock register values             */
  if (((LPC_SC->PLL0STAT >> 24) & 3) == 3) { /* If PLL0 enabled and connected */
    switch (LPC_SC->CLKSRCSEL & 0x03) {
      case 0:                                /* Int. RC oscillator => PLL0    */
      case 3:                                /* Reserved, default to Int. RC  */
        SystemCoreClock = (IRC_OSC *
                          ((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1)))  /
                          (((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)    /
                          ((LPC_SC->CCLKCFG & 0xFF)+ 1));
        break;
      case 1:                                /* Main oscillator => PLL0       */
        SystemCoreClock = (OSC_CLK *
                          ((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1)))  /
                          (((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)    /
                          ((LPC_SC->CCLKCFG & 0xFF)+ 1));
        break;
      case 2:                                /* RTC oscillator => PLL0        */
        SystemCoreClock = (RTC_CLK *
                          ((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1)))  /
                          (((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)    /
                          ((LPC_SC->CCLKCFG & 0xFF)+ 1));
        break;
    }
  } else {
    switch (LPC_SC->CLKSRCSEL & 0x03) {
      case 0:                                /* Int. RC oscillator => PLL0    */
      case 3:                                /* Reserved, default to Int. RC  */
        SystemCoreClock = IRC_OSC / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
        break;
      case 1:                                /* Main oscillator => PLL0       */
        SystemCoreClock = OSC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
        break;
      case 2:                                /* RTC oscillator => PLL0        */
        SystemCoreClock = RTC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
        break;
    }
  }

}

/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System.
 */
void SystemInit (void)
{
  const uint32_t PLL0_CONNECT_FLG = (1<<25) | (1<<24);
  const uint32_t PLL1_CONNECT_FLG = (1<<8) | (1<<9);
  
#if (CLOCK_SETUP)                       /* Clock Setup                        */
  LPC_SC->SCS       = SCS_Val;
  if (LPC_SC->SCS & (1 << 5)) {             /* If Main Oscillator is enabled  */
    while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready    */
  }

  LPC_SC->CCLKCFG   = CCLKCFG_Val;      /* Setup Clock Divider                */
  /* Periphral clock must be selected before PLL0 enabling and connecting
   * - according errata.lpc1768-16.March.2010 -
   */
  LPC_SC->PCLKSEL0  = PCLKSEL0_Val;     /* Peripheral Clock Selection         */
  LPC_SC->PCLKSEL1  = PCLKSEL1_Val;

#if (PLL0_SETUP)
  LPC_SC->CLKSRCSEL = CLKSRCSEL_Val;    /* Select Clock Source for PLL0       */

  LPC_SC->PLL0CFG   = PLL0CFG_Val;      /* configure PLL0                     */
  LPC_SC->PLL0FEED  = 0xAA;
  LPC_SC->PLL0FEED  = 0x55;

  LPC_SC->PLL0CON   = 0x01;             /* PLL0 Enable                        */
  LPC_SC->PLL0FEED  = 0xAA;
  LPC_SC->PLL0FEED  = 0x55;
  while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0                    */

  LPC_SC->PLL0CON   = 0x03;             /* PLL0 Enable & Connect              */
  LPC_SC->PLL0FEED  = 0xAA;
  LPC_SC->PLL0FEED  = 0x55;
  while ((LPC_SC->PLL0STAT & PLL0_CONNECT_FLG) != PLL0_CONNECT_FLG);/* Wait for PLLC0_STAT & PLLE0_STAT */
#endif

#if (PLL1_SETUP)
  LPC_SC->PLL1CFG   = PLL1CFG_Val;
  LPC_SC->PLL1FEED  = 0xAA;
  LPC_SC->PLL1FEED  = 0x55;

  LPC_SC->PLL1CON   = 0x01;             /* PLL1 Enable                        */
  LPC_SC->PLL1FEED  = 0xAA;
  LPC_SC->PLL1FEED  = 0x55;
  while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1                    */

  LPC_SC->PLL1CON   = 0x03;             /* PLL1 Enable & Connect              */
  LPC_SC->PLL1FEED  = 0xAA;
  LPC_SC->PLL1FEED  = 0x55;
  while ((LPC_SC->PLL1STAT & PLL1_CONNECT_FLG) != PLL1_CONNECT_FLG);/* Wait for PLLC1_STAT & PLLE1_STAT */
#else
  LPC_SC->USBCLKCFG = USBCLKCFG_Val;    /* Setup USB Clock Divider            */
#endif
  LPC_SC->PCONP     = PCONP_Val;        /* Power Control for Peripherals      */

  LPC_SC->CLKOUTCFG = CLKOUTCFG_Val;    /* Clock Output Configuration         */
#endif

#if (FLASH_SETUP == 1)                  /* Flash Accelerator Setup            */
  LPC_SC->FLASHCFG  = FLASHCFG_Val;
#endif

//  Set Vector table offset value
#if (__RAM_MODE__==1)
  SCB->VTOR  = 0x10000000 & 0x3FFFFF80;
#else
  SCB->VTOR  = 0x00000000 & 0x3FFFFF80;
#endif
}



my adc code
/****************************************************************************
 *   $Id:: adc.c 6089 2011-01-06 04:38:09Z nxp12832                         $
 *   Project: NXP LPC17xx ADC example
 *
 *   Description:
 *     This file contains ADC code example which include ADC 
 *     initialization, ADC interrupt handler, and APIs for ADC
 *     reading.
 *
 ****************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
****************************************************************************/
#include "lpc17xx.h"
#include "type.h"
#include "adc.h"
#include "Variables.h"

#ifndef _BV
#define _BV(_x_) (1UL << (_x_))
#endif

//volatile uint32_t ADCValue[ADC_NUM];
//volatile uint32_t ADCIntDone = 0;
volatile uint32_t BurstCounter = 0;
volatile uint32_t OverRunCounter = 0;

#if BURST_MODE
volatile uint32_t channel_flag = 0; 
#endif

#if ADC_INTERRUPT_FLAG
/******************************************************************************
** Function name:ADC_IRQHandler
**
** Descriptions:ADC interrupt handler
**
** parameters:None
** Returned value:None
** 
******************************************************************************/
void ADC_IRQHandler (void) 
{
  uint32_t regVal;
  volatile uint32_t dummy;
  int i;
  
  regVal = LPC_ADC->STAT;/* Read ADC will clear the interrupt */
  if ( regVal & 0x0000FF00 )/* check OVERRUN error first */
  {
OverRunCounter++;
  for ( i = 0; i < ADC_NUM; i++ )
  {
    regVal = (regVal & 0x0000FF00) >> 0x08;
    /* if overrun, just read ADDR to clear */
    /* regVal variable has been reused. */
      if ( regVal & _BV(i) )
    {
        dummy = LPC_ADC->DR;
    }
  }
LPC_ADC->CR &= ~((0x7<<24)|(0x1<<16));/* stop ADC now, turn off BURST bit. */ 
//  ADCIntDone = 1;
  return;
  }

  for ( i = 0; i < ADC_NUM; i++ )
  {
    if ( regVal & _BV(i) )
{
  ADCValue = ( LPC_ADC->DR >> 4 ) & 0xFFF;
}
  }

#if BURST_MODE
  BurstCounter++;
  channel_flag |= (regVal & 0xFF);
  if ( (channel_flag & 0x20) == 0x20 )
  {
/* All the bits in have been set, it indicates all the ADC 
channels have been converted. */
LPC_ADC->CR &= ~(0x1<<16);/* Clear BURST mode, stop ADC now */ 
  channel_flag = 0; 
//ADCIntDone = 1;
adc_arr[adc_ptr] = ADCValue[5];
adc_ptr++;
if(adc_ptr >= 5000)
{
ADCIntDone = 1;
LPC_ADC->CR &= ~(0x1<<16);/* Clear BURST mode, stop ADC now */ 
}
else
ADCBurstRead();
  }
#else
  LPC_ADC->CR &= ~(0x7<<24);/* stop ADC now */ 
//  ADCIntDone = 1;
#endif
  return;
}
#endif

/*****************************************************************************
** Function name:ADCInit
**
** Descriptions:initialize ADC channel
**
** parameters:ADC clock rate
** Returned value:None
** 
*****************************************************************************/
void ADCInit( uint32_t ADC_Clk )
{
  uint32_t i, pclkdiv, pclk;

  /* Enable CLOCK into ADC controller */
  LPC_SC->PCONP |= (1 << 12);

  for ( i = 0; i < ADC_NUM; i++ )
  {
ADCValue = 0x0;
  }

#ifADC_BURST
LPC_PINCON->PINSEL3 |= 0xF0000000;// P1.30~31, A0.4~5, function 11
LPC_PINCON->PINMODE3 &= ~0xF0000000;
  LPC_PINCON->PINMODE3 |= 0xA0000000;
#endif
 /*  
  // all the related pins are set to ADC inputs, AD0.0~7 
  LPC_PINCON->PINSEL0 &= ~0x000000F0;// P0.2~3, A0.6~7, function 10 
  LPC_PINCON->PINSEL0 |= 0x000000A0;
  LPC_PINCON->PINSEL1 &= ~0x003FC000;// P0.23~26, A0.0~3, function 01
  LPC_PINCON->PINSEL1 |= 0x00154000;
  LPC_PINCON->PINSEL3 |= 0xF0000000;// P1.30~31, A0.4~5, function 11
  // No pull-up no pull-down (function 10) on these ADC pins.
  LPC_PINCON->PINMODE0 &= ~0x000000F0;
  LPC_PINCON->PINMODE0 |= 0x000000A0;
  LPC_PINCON->PINMODE1 &= ~0x003FC000;
  LPC_PINCON->PINMODE1 |= 0x002A8000;
  LPC_PINCON->PINMODE3 &= ~0xF0000000;
  LPC_PINCON->PINMODE3 |= 0xA0000000;
 */

// /* all the related pins are set to ADC inputs, AD0.0~2 */
//LPC_PINCON->PINSEL1 &= ~0x000FC000;/* P0.23~25, A0.0~3, function 01 */
//LPC_PINCON->PINSEL1 |= 0x00054000;
//  
///* No pull-up no pull-down (function 10) on these ADC pins. */
//LPC_PINCON->PINMODE1 &= ~0x000FC000;
//LPC_PINCON->PINMODE1 |= 0x000A8000;


  /* By default, the PCLKSELx value is zero, thus, the PCLK for
  all the peripherals is 1/4 of the SystemFrequency. */
  /* Bit 24~25 is for ADC */
  pclkdiv = (LPC_SC->PCLKSEL0 >> 24) & 0x03;
  switch ( pclkdiv )
  {
case 0x00:
default:
  pclk = SystemCoreClock/4;
break;
case 0x01:
  pclk = SystemCoreClock;
break; 
case 0x02:
  pclk = SystemCoreClock/2;
break; 
case 0x03:
  pclk = SystemCoreClock/8;
break;
  }

  LPC_ADC->CR = ( 0x01 << 0 ) |  /* SEL=1,select channel 0~7 on ADC0 */
//( ( pclk  / ADC_Clk - 1 ) << 8 ) |  /* CLKDIV = Fpclk / ADC_Clk - 1 */ 
( 1 << 8 ) |
( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */
( 0 << 17 ) |  /* CLKS = 0, 11 clocks/10 bits */
( 1 << 21 ) |  /* PDN = 1, normal operation */
( 0 << 24 ) |  /* START = 0 A/D conversion stops */
( 0 << 27 );/* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */ 

  /* If POLLING, no need to do the following */
#if ADC_INTERRUPT_FLAG
  NVIC_EnableIRQ(ADC_IRQn);
#if BURST_MODE
  LPC_ADC->INTEN = 0x20;/* Enable interrupts int 4 & 5 */
#else
  LPC_ADC->INTEN = 0x1FF;/* Enable all interrupts */
#endif
#endif
  return;
}

/*****************************************************************************
** Function name:ADCRead
**
** Descriptions:Read ADC channel
**
** parameters:Channel number
** Returned value:Value read, if interrupt driven, return channel #
** 
*****************************************************************************/
uint32_t ADCRead( uint8_t channelNum )
{
#if !ADC_INTERRUPT_FLAG
  uint32_t regVal, ADC_Data;
#endif

  /* channel number is 0 through 7 */
  if ( channelNum >= ADC_NUM )
  {
channelNum = 0;/* reset channel number to 0 */
  }
  LPC_ADC->CR &= 0xFFFFFF00;
  LPC_ADC->CR |= (1 << 24) | (1 << channelNum);
/* switch channel,start A/D convert */
#if !ADC_INTERRUPT_FLAG
  while ( 1 )/* wait until end of A/D convert */
  {
regVal = LPC_ADC->DR[channelNum];
/* read result of A/D conversion */
if ( regVal & ADC_DONE )
{
  break;
}
  }
        
  LPC_ADC->CR &= 0xF8FFFFFF;/* stop ADC now */    
//  if ( regVal & ADC_OVERRUN )/* save data when it's not overrun, otherwise, return zero */
//  {
//return ( 0 );
//  }
  ADC_Data = ( regVal >> 4 ) & 0xFFF;
  return ( ADC_Data );/* return A/D conversion value */
#else
  return ( channelNum );/* if it's interrupt driven, the ADC reading is 
done inside the handler. so, return channel number */
#endif
}

/*****************************************************************************
** Function name:ADC0BurstRead
**
** Descriptions:Use burst mode to convert multiple channels once.
**
** parameters:None
** Returned value:None
** 
*****************************************************************************/
void ADCBurstRead( void )
{
  /* Start bits need to be zero before BURST mode can be set. */
  if ( LPC_ADC->CR & (0x7<<24) )
  {
LPC_ADC->CR &= ~(0x7<<24);
  }
  LPC_ADC->CR &= ~0xFF;
  /* Read all channels, 0 through 7. */
  LPC_ADC->CR |= 0xFF;
  LPC_ADC->CR |= (0x1<<16);/* Set burst mode and start A/D convert */
  return;/* the ADC reading is done inside the 
handler, return 0. */
}

/*********************************************************************************
**                            End Of File
*********************************************************************************/



adc.h header file

#defineADC_BURST1

#ifADC_BURST
/* If Burst mode is enabled, make sure interrupt flag is set. */
#define ADC_INTERRUPT_FLAG1/* 1 is interrupt driven, 0 is polling */
#define BURST_MODE1   /* Burst mode works in interrupt driven mode only. */
#else
/* In DMA mode, BURST mode and ADC_INTERRUPT flag need to be set. */
/* In BURST mode, ADC_INTERRUPT need to be set. */
#define ADC_INTERRUPT_FLAG0/* 1 is interrupt driven, 0 is polling */
#define BURST_MODE0   /* Burst mode works in interrupt driven mode only. */
#endif

#define ADC_DEBUG1

#define ADC_OFFSET          0x10
#define ADC_INDEX           4

#define ADC_DONE            0x80000000
#define ADC_OVERRUN         0x40000000
#define ADC_ADINT           0x00010000

//#define ADC_NUM8/* for LPCxxxx */
#define ADC_CLK12000000/* set to 1Mhz */

Labels (1)
0 Kudos
2 Replies

659 Views
lpcware
NXP Employee
NXP Employee
bump
0 Kudos

659 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rocketdawg on Thu Jun 02 09:52:19 MST 2016
If you really need that kind of acquisition speed, then perhaps, you should look at DMA.
0 Kudos