# PIC16F1936 Multiple ADC channel readings

I am programming a PIC16F1934 and using it's two ADC channels namely AN0 and AN1.

I take the maximum out of a bunch of few readings for the AN0 reading and then just one sample for AN1.

Here is my code:

    ADCON0 = 0b00000001;                // Source: AN0, Enable ADC
for (uint8_t i = 0; i < 46; i++) {

ADCON0bits.GO_nDONE = 1; // start conversion
while (!ADCON0bits.GO_nDONE); // wait for result

rawADCResult = *((uint16_t*) & ADRESL);

ADCResult = ((uint32_t) rawADCResult * 500ul) >> 10; // Scale it to 100x volts

if (maxADCResult < ADCResult) // Check if value has changed
maxADCResult = ADCResult; // and update last value

__delay_us(50);

}

ADCON0 = 0b00000100;                // Source: AN1, Disable ADC
__delay_ms(500);
ADCON0 = 0b00000101;                // Enable ADC
__delay_ms(500);

ADCON0bits.GO_nDONE = 1; // start conversion
while (!ADCON0bits.GO_nDONE); // wait for result

rawADCResult = *((uint16_t*) & ADRESL);

ADCPORTA1 = ((uint32_t) rawADCResult * 500ul) >> 10; // Scale it to 100x volts


The maxADCResult from channel AN0 is fine. But the value of ADCPORTA1 is always matching the value of channel AN1.

I am printing these values on the LCD and have made sure that I am not copying the same variable twice:

lcdSetCursor(1, 1);
sprintf(msg, "AN0: %d  ", ADCResult);
lcdWriteString(msg);
lcdSetCursor(2, 1);
sprintf(msg, "AN1: %d  ", ADCPORTA1);
lcdWriteString(msg);


One more thing, if I change the order of the channel reading (AN1 first, then AN0). The situation is reversed. Now the result of AN1 gets copied over to AN0.

I tried these things, but it's no use:

1. Disabling enabling the ADC in b/w each channel change.
2. Introducing huge delays to allow the MUX to change the channel or the ADC to power up.
3. Writing whole registers in each command to make sure all bits are according to need.
4. Completely changing the names the variables used with AN0 and AN1.

Can someone help me with an insight to this issue?

• Possessive 'its' does not have an apostrophe. – Spehro Pefhany Jan 9 '18 at 18:17

## 1 Answer

You have the sense wrong in your adc code: "while (!ADCON0bits.GO_nDONE);" should be "while (ADCON0bits.GO_nDONE);". You want to be stuck in the while loop while ADCON0bits.GO_nDONE is "1". When it is "0" the ADC has completed the measurement and you can then get out of the while loop and read the result. Otherwise, you read the ADC register immediately after starting the conversion. The result is then from the previous conversion.

• Painful experience. – John Birckhead Jan 9 '18 at 18:52