Device: TM4C123GH6PM
I have an ADC measuring my li-ion 3.7V battery voltage (through a voltage divider, two 180k resistors.) I also have a light sensor on my board (simple non-RoHS CdS cell due to having a few left over.)
This works, but when the light sensor intensity (resistance) changes, and hence voltage on the AIN0 channel changes, the reading on the AIN2 channel is affected. A full scale range from 0~3.3V on AIN0 affects AIN2 by about 20%. Note I'm not even sampling the channel in question. Only sampling channels AIN2 and AIN3. I haven't checked if it works the other way around or on other channels.
At all times, my analog inputs are within operational limits (0~3.3V.) VDDA is powered from 3.3V and GNDA is connected - though no particular precaution has been taken in ensuring the grounds are separated or analog 3.3V is isolated from the digital 3.3V, I would only anticipate a noise floor increase....
I'm enclosing my code. I check readings of each channel alternately. I don't require oversampling or high performance - I only check each input about 10 times a second.
I'm unsure if this is a PCB/layout problem, a misunderstanding of device capability, or a software problem, or some combination of all three.
/*
* Initialise and start the ADC.
*/
void init_adc()
{
// Start ADC peripheral clock and start GPIOE (if not already started)
// for PE0, PE1, PE2 and PE3, the analog GPIOs.
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// Set analog mode on the appropriate pins.
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
// Use sequence 3 type sampling. According to the ADC module datasheet, and
// some example code, this will sample on the processor's signal.
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
ADCReferenceSet(ADC0_BASE, ADC_REF_INT);
ADCIntEnable(ADC0_BASE, 3);
}
/*
* Get a sample on an ADC port (AIN0~AIN3). 12-bit result returned.
*/
unsigned int adc_get_sample(int ain)
{
uint32_t sample[1];
uint32_t adcins[] = {ADC_CTL_CH0, ADC_CTL_CH1, ADC_CTL_CH2, ADC_CTL_CH3};
// Wait for ADC to be free.
// Configure and start the sequence of conversions - containing a single conversion.
ADCSequenceDisable(ADC0_BASE, 3);
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_IE | ADC_CTL_END | adcins[ain]);
ADCSequenceEnable(ADC0_BASE, 3);
ADCIntClear(ADC0_BASE, 3);
ADCProcessorTrigger(ADC0_BASE, 3);
// Wait for the result to be acquired, then return it.
while(!ADCIntStatus(ADC0_BASE, 3, false)) ;
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, sample);
return (unsigned int)sample[0];
}
/*
* Get an averaged (128x) ADC sample.
* TODO: use ADC pipelining to improve speed.
*/
unsigned int adc_get_sample_avg(int ain)
{
int numsamp = 128, sampctr = 0;
unsigned int acq = 0;
while(sampctr < numsamp) {
acq += adc_get_sample(ain);
sampctr++;
}
return acq / numsamp;
}
/*
* Get current temperature in degrees C, using the board
* temperature sensor. Used for speed of sound compensation.
*
* Note: this does not read the TIVA's temperature sensor.
*/
int adc_read_temperature()
{
return (adc_get_sample(3) * CALFAC_ADC3_TEMP_SNS_SCALE) + CALFAC_ADC3_TEMP_SNS_OFFSET;
}
/**
* Return in millivolts current battery voltage.
*/
unsigned int adc_read_vbat()
{
return (adc_get_sample_avg(2) * CALFAC_ADC0_VBAT_SCALE) + CALFAC_ADC0_VBAT_OFFSET;
}
Any advice appreciated.

