This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC21xx ADC Problem

I have just started writing a simple application for the LPC2129. I have a problem with polling the DONE bit of the ADC.

The ADC clock is 3.68 MHz. I set the ADC to be 10 bits, single shot. I start the ADC and then poll the done bit like this:-
while( !(ADDR & 0x80000000) );
The code is compiled using the Keil ARM tools (demo version). When I run the code on the simulator it works correctly, when I run it on the target it returns incorrect values.

The returned value does track the input voltage but is quantised to 0x0000, 0x6000, 0x8000 or 0xE000 (Only 4 discrete values).

If I single step or place a delay function before polling the DONE bit then the code runs correctly.

Am I doing something wrong or is there a problem with polling this bit?

  • Is ADDR define with proper 'volatile' qualification?

  • The ADC registers are defined like this:-

    /* A/D Converter */
    #define ADCR (*((volatile unsigned long *) 0xE0034000))
    #define ADDR (*((volatile unsigned long *) 0xE0034004))

    I think that's correct.
    I did notice a problem when single-stepping with the ULINK in that the test for the DONE bit gets stuck because in single step mode the bit is cleared before it is tested. I have to overwrite the CPU register that is used for the comparison in order to force it out of the loop. Once I've done that the result is always correct in single-step mode.

    Paul

  • "The ADC registers are defined like this ...

    I think that's correct."


    I do too, so a few more things:

    • There is ADC errata on this device. It wouldn't seem to apply to your situation, but without seeing how you are controlling the ADC, it's impossible say.
    • Double-check the ADC configuration and control used to initiate conversion.
    • Examine the assembly code to be certain there's nothing fishy going on.

  • The UM is ambiguous about the state of the
    sample value when DONE=0. Since I prefer not
    to depend on anything that isn't explicitly
    stated in the manual, I use the alternative
    coding

    do { r = ADDR; } while (!(r & DONEMASK));

    [This message brought to you by your
    Department of Magic and Superstition.]

  • Thanks for your help guys.

    I looked through the assembly and couldn't see anything amiss (though I'm no expert in ARM assembly). One thing I did realise was that I am starting a conversion like this:-

    ADCR |= 0x01000000; // Set start condition to 'Now'

    but never reseting the start condition. I tried adding 'ADCR &= 0x00FFFFFF;' after finding the DONE bit set. This resets the start condition to 'none'. This fixes the problem. So I now read the result like this:-

    do { r = ADDR; } while (!(r & 0x80000000));
    ADCR &= 0x00FFFFFF; // Clear start condition
    return( r & 0x0000FFFF);

    (incorporating the change that Bruce sugested because I take your point about not doing anything not explicitly defined in the manual).

    It's now working a treat. Thank you both for pointing me in the right direction.

    Paul