LPC1769 unexpected value returns from ADC

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

LPC1769 unexpected value returns from ADC

1,523 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Kat on Mon Oct 21 00:35:23 MST 2013
Hi,
I'm using the one analog CH of LPC1769 ADC by ADC CLOCK 1MHz Polling read.
If Read of the ADC is carried out continuously Inaccurate data sometimes like 0xfff is acquired.
If Read may be carried out 50x500 times and there may be no inaccurate data
Inaccurate data may be acquired by 50x10 times of Read(s).
Of course, AD input is not changed.
Would you teach the evasion method, if the direction which experienced such a situation and was avoided comes?
The test code used for reference is attached.

Test code
---------------------------------------------------------------------
    // AD initialize  (AD0.0 1MHz polling read)
    LPC_SC->PCONP |= (1 << 12);
    LPC_PINCON->PINSEL1 &= ~0x0000C000;// P0.23 A0.0 function 01
    LPC_PINCON->PINSEL1 |=  0x00004000;
    LPC_PINCON->PINMODE1 &= ~0x0000C000;// No pull-up no pull-down (function 10)
    LPC_PINCON->PINMODE1 |=  0x00008000;
    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 ) | ( ( pclk  / ADC_Clk - 1 ) << 8 ) | 
( 0 << 16 ) | ( 0 << 17 ) | ( 1 << 21 ) | ( 0 << 24 ) | ( 0 << 27 );

    for(;;){
        for(i=0, j=0; i<50; i++) {
            LPC_ADC->ADCR &= 0xFFFFFF00;
            LPC_ADC->ADCR |= (1 << 24) | (1 << 0);// start adc
            for(;;){
regVal = DR[0];         // read result of A/D conversion
                if ( regVal & ADC_DONE )
    break;
            }
            LPC_ADC->ADCR &= 0xF8FFFFFF;// stop ADC now
            if ( regVal & ADC_OVERRUN ) {
                adspl = 0x1000;
continue;
            }
            adspl = ( regVal >> 4 ) & 0xFFF;
        }
    }


Labels (1)
0 Kudos
Reply
8 Replies

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by araki on Thu Mar 06 23:58:13 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

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by araki on Tue Feb 18 03:37:48 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

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Mon Nov 11 10:39:17 MST 2013
Thank you for the feedback. I think this question probably needs to be answered by the NXP support team.
0 Kudos
Reply

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Mon Nov 11 03:42:37 MST 2013
Your code snippet isn't faulty. (BTW: You don't need to stop ADC conversion after ADC_DONE).

Not sure which compiler & hardware you are using, but in LPCXpresso with LPCXpresso1769 Board your code is working

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

#include "LPC17xx.h"

#include <cr_section_macros.h>

#define ADC_OVERRUN     0x40000000
#define ADC_DONE        0x80000000
#define ADC_Clk1000000/* set to 1Mhz */

volatile uint16_t adspl[50];

int main(void)
{
 volatile static int i = 0;
 volatile uint32_t regVal;
 volatile uint32_t pclkdiv,pclk;
 // AD initialize (AD0.0 1MHz polling read)
 LPC_SC->PCONP |= (1 << 12);
 LPC_PINCON->PINSEL1 &= ~0x0000C000; // P0.23 A0.0 function 01
 LPC_PINCON->PINSEL1 |= 0x00004000;
 LPC_PINCON->PINMODE1 &= ~0x0000C000; // No pull-up no pull-down (function 10)
 LPC_PINCON->PINMODE1 |= 0x00008000;
 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 ) | ( ( pclk / ADC_Clk - 1 ) << 8 ) |
 ( 0 << 16 ) | ( 0 << 17 ) | ( 1 << 21 ) | ( 0 << 24 ) | ( 0 << 27 );

// for(i=0; i<50; i++)          //simple ADC reading
// {
//  LPC_ADC->ADCR |= (1 << 24); // start adc
//  do
//  {
//   regVal = LPC_ADC->ADDR0; //check done bit
//  }while(!(regVal & ADC_DONE));//wait until Done is set
//  if ( regVal & ADC_OVERRUN ){adspl = 0x1000;}//overrun
//  else{adspl = ( regVal >> 4 ) & 0xFFF;}
// }


 for(i=0 ; i<50; i++) {
 LPC_ADC->ADCR &= 0xFFFFFF00;
 LPC_ADC->ADCR |= (1 << 24) | (1 << 0); // start adc
 for(;;){
 regVal = LPC_ADC->ADDR0; // read result of A/D conversion
 if ( regVal & ADC_DONE )
 break;
 }
 //LPC_ADC->ADCR &= 0xF8FFFFFF; // stop ADC now
 if ( regVal & ADC_OVERRUN ) {
 adspl = 0x1000;
 continue;
 }
 adspl = ( regVal >> 4 ) & 0xFFF;
 }


 while(1)
 {
  i++ ;
 }
 return 0 ;
}


So your problem is either your hardware or the rest of your code / project setup.
0 Kudos
Reply

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Kat on Mon Nov 11 02:45:40 MST 2013
Hi, Pacman

Thank you for your advice.

The result of having tried your advice is as follows.
After checking ADC_DONE flag,
If DR [n] is read again, only the value from which ADC_DONE fell can be read.
AD value did not have change as a result.

Regards,
0 Kudos
Reply

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Tue Nov 05 11:56:33 MST 2013
I just learned something about the ADC, and remembered that you had this problem.

Have you tried reading the DR[n] register after you get the ADC_DONE flag ?

I would expect the results might be slightly improved.
Please let me know if it changes anything.
0 Kudos
Reply

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Kat on Mon Oct 21 22:45:19 MST 2013
Hi, MarcVonWindscooting.

Thank you for the comment.
However, the situation has not improved.
AD input does not exceed VDDA on a circuit.
Moreover, 0xfff may be able to be read even if AD input is 0v.
If dummy weight is put in, frequency will fall, but reading 0xfff is not lost.

Regards,
0 Kudos
Reply

1,451 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MarcVonWindscooting on Mon Oct 21 08:16:50 MST 2013
Hi,

without looking at your code, let me tell you I once had false readings from that exact processor by having other ADC lines catching some noise. The manual says: the voltage on ADC lines must not exceed VREF otherwise ADC readings (meaning: maybe ALL ADC readings, even of other channels) may be incorrect. I enabled pull-down on the ADC input lines and all problems were gone!
0 Kudos
Reply