Analog-to-Digital Conversion (ADC)
Real-world signals — light, temperature, sound — are analog. An ADC is the peripheral that translates a continuous voltage into a number your code can actually use.
A GPIO pin configured as a digital input can only tell you high or low. Many sensors, though — a light-dependent resistor, a temperature sensor, a microphone — produce a continuously varying voltage, not a clean on/off signal. An analog-to-digital converter (ADC) is the peripheral that bridges the two worlds: it samples a voltage at a given instant and reports back the closest matching number.
That number's precision depends on the ADC's resolution, measured in bits. A common 10-bit ADC divides its full input voltage range into 1,024 discrete steps (2 to the power of 10), numbered 0 through 1023. A reading of 0 means the input was at (or below) the ADC's reference low voltage; a reading of 1023 means it was at (or above) the reference high voltage; anything in between is proportional.
| Raw reading | Approximate voltage |
|---|---|
| 0 | 0.00 V |
| 512 | 2.50 V |
| 1023 | 5.00 V |
Using an ADC typically involves selecting which pin to sample (many PICs share one ADC among several pins), starting a conversion, waiting a short time for it to finish, and then reading the result out of a pair of registers (since a 10-bit value doesn't fit in a single 8-bit register).
unsigned int read_adc(void) {
ADCON0bits.CHS = 0; // select channel AN0
ADCON0bits.GO = 1; // start conversion
while (ADCON0bits.GO); // wait for it to finish
return ((ADRESH << 8) + ADRESL); // combine into one 10-bit value
}
void main(void) {
TRISA0 = 1; // AN0 as input
ADCON1 = 0b00001110; // AN0 analog, rest digital
ADCON0 = 0b00000001; // enable the ADC module
while(1) {
unsigned int value = read_adc();
// use "value", 0–1023, however your project needs
__delay_ms(200);
}
}