lpcware

LPC11C24 converting ADC value to voltage

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by One33Seven on Sat Oct 04 01:33:21 MST 2014
I'm using the examples from the CMSIS package as a driver for the onchip ADC.

In my main function I call ADCInit( ADC_CLK ); to initialize the ADC and later on in a timer I use ADCValue = ADCRead(0); to read the ADC.

Every works fine except the converted value doesn't match the voltage on the pin. The voltage on the PIN is 2.5v and the value the ADC is giving me is 590 (uint).

So this is how I'm calculating to real value, the range of the ADC is 3.3v and it's in 10bit mode so 1024. 3.3/1024 = 0.0032v LSB.

590*0.0032 = 1.9v which is not 2.5v.

What am I doing wrong?


#ifndef __ADC_H
#define __ADC_H

#define ADC_INTERRUPT_FLAG    0/* 1 is interrupt driven, 0 is polling */
#define BURST_MODE            0 /* Burst mode works in interrupt driven mode only. */
#define SINGLE_BURST_MODE     0 /* Single burst mode works in interrupt driven mode only. */
#define ADGINTEN              0/* global DONE flag generate interrupt */
#define INTERNAL_VOLT         1/* If this flag is on, it measures interval voltage,
                                   core voltage, internal Vref, and temperature. */
#define ADC_DEBUG             0
#define ADC_DEBUG_CLEAR_CNT   (100) /* Number of samples until statistics are cleared */
#define ADC_DEBUG_UPDATE_CNT  (5000) /* Number of samples until statistics are cleared */

#define ADC_OFFSET            0x10
#define ADC_INDEX             4

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

#define ADC_NUM               8/* for LPC11xx */
#define ADC_CLK               4400000/* set to 4.4Mhz */


extern void ADC_IRQHandler( void );
extern void ADCInit( uint32_t ADC_Clk );
extern uint32_t ADCRead( uint8_t channelNum );
extern void ADCBurstRead( void );
#endif /* end __ADC_H */
/*****************************************************************************
**                            End Of File
******************************************************************************/


#include "LPC11xx.h"/* LPC11xx Peripheral Registers */
#include "adc.h"

volatile uint32_t ADCValue[ADC_NUM];
volatile uint32_t ADCIntDone = 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, 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 & (0x1 << i) )
  {
regVal = LPC_ADC->DR;
  }
}
LPC_ADC->CR &= 0xF8FFFFFF;/* stop ADC now */
ADCIntDone = 1;
return;
  }

  if ( regVal & ADC_ADINT )
  {
for ( i = 0; i < ADC_NUM; i++ )
{
  if ( (regVal&0xFF) & (0x1 << i) )
  {
ADCValue = ( LPC_ADC->DR >> 6 ) & 0x3FF;
  }
}

#if BURST_MODE
channel_flag |= (regVal & 0xFF);
if ( (channel_flag & 0xFF) == 0xFF )
{
  /* All the bits in have been set, it indicates all the ADC
  channels have been converted. */
  LPC_ADC->CR &= 0xF8FFFFFF;/* stop ADC now */
  channel_flag = 0;
  ADCIntDone = 1;
}
#else
LPC_ADC->CR &= 0xF8FFFFFF;/* 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;

  /* Disable Power down bit to the ADC block. */
  LPC_SYSCON->PDRUNCFG &= ~(0x1<<4);

  /* Enable AHB clock to the ADC. */
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13);

  for ( i = 0; i < ADC_NUM; i++ )
  {
ADCValue = 0x0;
  }
  /* Unlike some other pings, for ADC test, all the pins need
  to set to analog mode. Bit 7 needs to be cleared according
  to design team. */
  LPC_IOCON->R_PIO0_11 &= ~0x8F; /*  ADC I/O config */
  LPC_IOCON->R_PIO0_11 |= 0x02;  /* ADC IN0 */
  //LPC_IOCON->R_PIO1_0  &= ~0x8F;
  //LPC_IOCON->R_PIO1_0  |= 0x02;  /* ADC IN1 */
  //LPC_IOCON->R_PIO1_1  &= ~0x8F;
  //LPC_IOCON->R_PIO1_1  |= 0x02;  /* ADC IN2 */
  //LPC_IOCON->R_PIO1_2 &= ~0x8F;
  //LPC_IOCON->R_PIO1_2 |= 0x02; /* ADC IN3 */

/* AD4 disabled to retain SWD. Un-comment if needed */
// LPC_IOCON->SWDIO_PIO1_3   &= ~0x8F;
  // LPC_IOCON->SWDIO_PIO1_3   |= 0x02;  /* ADC IN4 */
  /*--------------------------------------------*/

//LPC_IOCON->PIO1_4    &= ~0x8F; /* Clear bit7, change to analog mode. */
  //LPC_IOCON->PIO1_4    |= 0x01;  /* ADC IN5 */
  //LPC_IOCON->PIO1_10   &= ~0x8F; /* Clear bit7, change to analog mode. */
  //LPC_IOCON->PIO1_10   |= 0x01;  /* ADC IN6 */
  //LPC_IOCON->PIO1_11   &= ~0x8F; /* Clear bit7, change to analog mode. */
  //LPC_IOCON->PIO1_11   |= 0x01;  /* ADC IN7 */

  LPC_ADC->CR = ( 0x01 << 0 ) |  /* select AD0 on PIO0_11. SEL=1,select channel 0~7 on ADC0 */
( ( SystemCoreClock / ADC_Clk - 1 ) << 8 ) |  /* CLKDIV = Fpclk / 1000000 - 1 */
( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */
( 0 << 17 ) |  /* CLKS = 0, 11 clocks/10 bits */
( 1 << 21 ) |  /* PDN = 1, normal operation */
( 0 << 22 ) |  /* TEST1:0 = 00 */
( 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 = 0xFF;/* Enable all interrupts */
#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 = *(volatile unsigned long *)(LPC_ADC_BASE
+ ADC_OFFSET + ADC_INDEX * 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 >> 6 ) & 0x3FF;
  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 )
{
  if ( LPC_ADC->CR & (0x7<<24) )
  {
LPC_ADC->CR &= ~(0x7<<24);
  }
  /* Read all channels, 0 through 7. Be careful that if the ADCx pins is shared
  with SWD CLK or SWD IO. */
  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
*********************************************************************************/

Outcomes