lpcware

lpc1768 adc at sampling rate of 200KHz

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 18, 2016 by lpcware
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 */

Outcomes