Nerdegutta's logo

nerdegutta.no

PIC16F690 - Day 9: Reading Analog Input with ADC

18.11.25

Embedded

Goal

Learn to use the Analog-to-Digital Converter (ADC) to read analog voltages. We’ll read a potentiometer on AN0 (RA0) and:

Hardware Setup

Concepts

Code 1: Read ADC and Show Top 4 Bits on LEDs

#define _XTAL_FREQ 4000000
#include < xc.h >
#include < stdint.h >

// CONFIG
#pragma config FOSC = INTRCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF

void adc_init(void) {
    ADCON0 = 0b00000001;  // AN0 selected, ADC on
    ADCON1 = 0b00110000;  // Right justify, Fosc/8
    ANSEL = 0b00000001;   // RA0 analog
    TRISA0 = 1;           // Input
}

uint16_t adc_read(void) {
    __delay_ms(2);            // Acquisition time
    GO_nDONE = 1;
    while (GO_nDONE);         // Wait until done
    return ((ADRESH << 8) + ADRESL);
}

void main(void) {
    TRISB = 0xF0;  // RB0–RB3 as output
    ANSELH = 0;
    adc_init();

    while (1) {
        uint16_t value = adc_read();   // 0–1023
        uint8_t top4 = value >> 6;     // Get top 4 bits (0–15)
        PORTB = (PORTB & 0xF0) | (top4 & 0x0F);  // Show on LEDs
        __delay_ms(100);
    }
}

Code 2: Use ADC to Set 4-Digit Value (0–1023) on 7-Segment Display

This version integrates with the Day 8 Timer0-based display to show the ADC value.Update inside main loop only:
uint16_t value = adc_read();  // 0–1023
digit_values[0] = (value / 1000) % 10;
digit_values[1] = (value / 100) % 10;
digit_values[2] = (value / 10) % 10;
digit_values[3] = value % 10;