LPCXpresso-LPC1769 ADC work not correctly!

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

LPCXpresso-LPC1769 ADC work not correctly!

1,381 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by zad on Thu Dec 12 07:00:14 MST 2013
Hello,

I'm using the LPCXpresso target LPC1769-Board.
My goal is to read 3 inputs voltage via  ADC0.0, ADC0.1 and ADC0.2 Channels in software controlled mode.
When I run the program, It  seems to work well but there are some results that I was not expected.
For example, when the input voltage is 0V.  The adc_count is 0, but some times it is 0xFFF or 0x8EF or another value.
Also  I treid to use Burst mode, but the result was the same result.

My program code is as follows:

(ADC_CLK is 1MHz)

uint32_t ADCInit( uint32_t ADC_Clk )
{
  uint32_t pclkdiv, pclk;

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

  /* all the related pins are set to ADC inputs, AD0.0~2 */

  LPC_PINCON->PINSEL1 &= ~0x000FC000;// P0.23~25, ADC0.0~ADC0.2 function 01
  LPC_PINCON->PINSEL1 |= 0x00054000;

  LPC_PINCON->PINMODE1 &=~(3<<14);
  LPC_PINCON->PINMODE1 |= (2<<14);        // P0.23 has neither pull up nor pull down
  LPC_PINCON->PINMODE1 &=~(3<<16);
  LPC_PINCON->PINMODE1 |= (2<<16);        // P0.24 has neither pull up nor pull down
  LPC_PINCON->PINMODE1 &=~(3<<18);
  LPC_PINCON->PINMODE1 |= (2<<18);        // P0.25 has neither pull up nor pull down

   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->ADCR = ( 0x01 << 0 ) | /* SEL=1,select channel 0 on ADC0 */
( ( (pclk  / ADC_Clk) - 1 ) << 8 ) |  /* CLKDIV = Fpclk / ADC_Clk - 1 */
( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */
( 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) */

   return (TRUE);
}

uint32_t ADC0Read( uint8_t channelNum )
{

  uint32_t regVal, ADC_Data;


  /* channel number is 0 through 7 */
  if ( channelNum >= ADC_NUM )
  {
channelNum = 0;/* reset channel number to 0 */
  }
  LPC_ADC->ADCR &= 0xFFFFFF00;

  LPC_ADC->ADCR |= (1 << channelNum);
  LPC_ADC->ADCR |= (1 << 24) ;

/* switch channel,start A/D convert */

  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->ADCR &= 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 */

}

Is there anybody who had the same problem?
Thanks!
0 Kudos
Reply
9 Replies

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by xjx on Sat Nov 28 14:06:50 MST 2015
Hello, same glitch or spikes problem here. See image for DC values conversion.

Any solutions?
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by araki on Thu Mar 06 23:56:51 MST 2014
I am sorry.
External VREFP removes only the noise of the LPCXpresso board. (pulse noise of the lower 5 bits)
Even if improve the VREFP, abnormal values that are discussed here seems to occur.
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by YES_IKEDA on Sat Feb 22 23:39:52 MST 2014
Thank you.
However, the result was the same.
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by araki on Tue Feb 18 03:37:17 MST 2014
I also had the same problem.
However, it could be solved by supplying externally VDDA and VREFP.
Remove the FB1(chip beads) and supply the 3.3V from the outside.
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by YES_IKEDA on Thu Feb 06 20:08:21 MST 2014
The contents of errata,
Conversion is started by an external input of P1.27 or external input of P2.10, there is something you let someone get away depending on the frequency of setting.
So, you can substitute that to Start Conversion MATxx match interrupt routine or CAPxx input interrupt routine.
I am aware of the contents of the above.

It was decided to install an A / D chip to the outside.
Thank you.
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by YES_IKEDA on Tue Feb 04 20:44:28 MST 2014
Thank you.
Yes, I've read of course.
I ran in the source code below.

1. Variables are global variables.
2. Analog pin is fixed to GND.
3. ADCRead (x); such as is polling the original method.
   (There is no external trigger.It is not a burst mode.)
4. Value indicated by this should indicate a zero value around almost.
5. However, I will show a large value sometimes more than 100.
6. CLKDIV of AD0CR is the same even if it is set to 1MHz, and even if it is set to 4MHz.
7. The SystemCoreClock has set to 100MHz.

I was able to see the big value 100 or more than zero.
I think whether Well Well that's the value of from 0 to less than 50.

Why not?

I have the same problem the question advertisers.
Thank you.

Is the source code....

/*
===============================================================================
Name        : main.c
Author      : $(author)
Version     :
Copyright   : $(copyright)
Description : main definition
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>

#include <stdio.h>
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "type.h"
#include "math.h"


#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "ssp.h"
#include "timer.h"
#include "uart.h"


#include "main.h"
#include "ExtValue.h"

//-----------------------------------------//
// main loop
// Variables are global variables.
// uiToString(xx),Device_Init(),InitValue()
// is Function of self-made
//-----------------------------------------//
int main(void)
{

SystemCoreClockUpdate();

Device_Init();

// Variable initialization
InitValue();

    while(1){

    switch(iMainTaskSwitch){
    case0:
    // Average value
    iAD_0 = ADCRead(0);
    iAD_1 = ADCRead(1);
    iAD_2 = ADCRead(2);
    iAD_3 = ADCRead(3);
    iAD_4 = ADCRead(4);
    iAD_5 = ADCRead(5);
    iAD_Total = iAD_0 + iAD_1 + iAD_2 + iAD_3 + iAD_4 + iAD_5;
    iAD_Avrage = iAD_Total / 6;

    iMainTaskSwitch = 10;

    break;

    case10:
iAD_0 = ADCRead(0);
iAD_1 = ADCRead(1);
iAD_2 = ADCRead(2);
iAD_3 = ADCRead(3);
iAD_4 = ADCRead(4);
iAD_5 = ADCRead(5);

    iMainTaskSwitch = 10;

    iDiff = abs(iAD_Avrage - iAD_0);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    iDiff = abs(iAD_Avrage - iAD_1);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    iDiff = abs(iAD_Avrage - iAD_2);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    iDiff = abs(iAD_Avrage - iAD_3);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    iDiff = abs(iAD_Avrage - iAD_4);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    iDiff = abs(iAD_Avrage - iAD_5);
    if(iDiff > 100){
    iMainTaskSwitch = 20;
    }

    break;

    case20:
    // Ready to Send

    LPC_GPIO2->FIOSET = 1 << 6;// LED ON

    iSendIndex = 0;
    for(iSendIndex = 0; iSendIndex < 64; iSendIndex++){
    chSendBuffer[iSendIndex] = ' ';
    }
    chSendBuffer[4] = ',';
    chSendBuffer[9] = ',';
    chSendBuffer[14] = ',';
    chSendBuffer[19] = ',';
    chSendBuffer[24] = ',';
    chSendBuffer[29] = ',';
    chSendBuffer[34] = 0x0d;
    chSendBuffer[35] = 0x0a;

    //Average value (places case 0:)
    uiToString(4,iAD_Avrage,&chSendBuffer[0],1);
    // CH0 <-> CH5
    uiToString(4,iAD_0,&chSendBuffer[5],1);
    uiToString(4,iAD_1,&chSendBuffer[10],1);
    uiToString(4,iAD_2,&chSendBuffer[15],1);
    uiToString(4,iAD_3,&chSendBuffer[20],1);
    uiToString(4,iAD_4,&chSendBuffer[25],1);
    uiToString(4,iAD_5,&chSendBuffer[30],1);

    iSendIndex = 0;
    iMainTaskSwitch = 25;

    break;

    case25:
    // Transmission
    LSRValue = LPC_UART0->LSR;
    if (LSRValue & LSR_TEMT){
    // both UnTHR and UnTSR are empty

    chSend_Data = chSendBuffer[iSendIndex];
    LPC_UART0->THR = chSend_Data;

    iSendIndex++;
    if(chSend_Data == 0x0a){
    // Transmission completion
    iMainTaskSwitch = 10;

    LPC_GPIO2->FIOCLR = 1 << 6;// LED OFF


    }

    }

    break;

    default:
    break;
    }


    }
    return 0 ;
}
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by serge on Tue Feb 04 01:50:40 MST 2014
Have you read the errata sheet?
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by YES_IKEDA on Mon Feb 03 07:17:52 MST 2014
Also in the manner described above, it was useless.
Again, it may return from time to time, a large value.
Will you become the internal organs that A / D can not be used.
I'm sorry. Sorry.
0 Kudos
Reply

964 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by YES_IKEDA on Sun Feb 02 23:36:36 MST 2014
AN10974 - LPC176x ADC Demo board - Reference Design Rev B.zip
AN10974 - LPC176x_ADC_Board - Software.zip
AN10974.pdf


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
case 6:
  LPC_PINCON->PINSEL0 |= (2U<<6);
break;
case 7:
  LPC_PINCON->PINSEL0 |= (2U<<4);
break;
}
/* After configuring PINSEL, ADC needs a delay before starting sampling (Otherwise, higher values will be read)  */
for (i = 0; i < 5000000; i++);

/* Read value of peripheral clock divider and then use this value
   to calculate clock frequency to ADC */
  u32PCLKDIV = (LPC_SC->PCLKSEL0 >> 24) & 0x03;
 
switch ( u32PCLKDIV )

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 Kudos
Reply