#define ADC_BATT_CH11 #define ADC_BATT_PINSWM_FIXED_ADC11 #define REF_MV2500 uint32_t getBatteryMV(void) { uint32_t adc = getADC(ADC_BATT_CH); return (adc * REF_MV) >> 11;// Return battery voltage (voltage divider factor included) } uint32_t getADC(uint8_t ad) { // Start ADC conversion Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX, ADC_SEQ_CTRL_CHANSEL(ad) | ADC_SEQ_CTRL_MODE_EOS | ADC_SEQ_CTRL_HWTRIG_POLPOS); Chip_ADC_EnableSequencer(LPC_ADC, ADC_SEQA_IDX); uint32_t i = 0; uint32_t gdat = 0; while((gdat & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) == 0) { // Retrieve sampled data gdat = Chip_ADC_GetDataReg(LPC_ADC, ad); } return ADC_DR_RESULT(gdat); } void ADC_Init(void) { // Configure pins Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM); Chip_SWM_EnableFixedPin(ADC_BATT_PIN); Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM); // Enable ADC clock Chip_ADC_Init(LPC_ADC, 0); // Start Calibration Chip_ADC_StartCalibration(LPC_ADC); while(!Chip_ADC_IsCalibrationDone(LPC_ADC)); // Configure clock Chip_ADC_SetClockRate(LPC_ADC, 1000); // Clock 1kHz } void ADC_DeInit(void) { Chip_ADC_DeInit(LPC_ADC); // Power down ADC } |
I also encountered this problem a few years ago (strong pullup of ADC input to Vdd) and gave up on finding the cause. (I used an opamp which was strong enough to overcome the effect). For some reason the now obvious cause didn't occur to me then. Only by chance yesterday I was reading the LPC845 datasheet and saw a little note reminding users to disable any internal pullup/pulldown via the IOCON register when using the ADC. Indeed the pullup is enabled by default and needs to be disabled (remember to enable clock to IOCON too before making changes).
I think what threw me was that I had assumed the internal pullup/pull down was part of the digital IO hardware which the datasheet says is disabled if using the ADC. I just tried this modification to the firmware on my hardware prototype where I experienced the problem and indeed a floating ADC input now goes from hard Vdd to something like 0.7V when the pullup is disabled.
Another thing to watch out for is the acquisition time. There is a time constant of 2.5kΩ with the 0.32pF of Cia and the unspecified Cdac. (which is 10pF on a Microchip microcontroller) For the ADC to settle within 1 bit takes EIGHT time constants. (about 200ns) The impedance of your source adds to the 2.5kΩ, so if you are reading a 10kΩ pot (which has a maximum output impedance of 2.5kΩ) the acquisition time is doubled (400ns), but if your source has an output of 100kΩ then it will take 4µs.
The general advice given is to run the ADC at the fastest speed it can go, but if you find that your values are being strangely influenced by the voltage on the adjacent pin you have an acquisition time problem. My advice would be to run the ADC at the SLOWEST speed which will get the job done in the time available. (Each channel takes 25 clock cycles to read). The only occasion when I wouldn't recommend this is if you are sampling two waveforms and trying to determine the phase difference between them, in which case make sure that they are on adjacent pins so that the ADC reads one immediately after the other.