Using ADC Module of PIC Microcontroller – Hi Tech C

Analog to Digital Converter (ADC) is a device that converts an analog quantity (continuous voltage) to discrete digital values. This is very useful when we want to do some processing on physical quantities, which are normally analog in nature. Most of the PIC Microcontrollers have built in ADC Module. Here we are using PIC 16F877A for demonstrating the working.

ADC_Symbol

ADC_Symbol

ADC of PIC Microcontrollers have 5 inputs for 28 pin devices and 8 inputs for 40/44 pin devices. It is a 10-bit ADC, ie the conversion of analog signal results in corresponding 10-bit digital number. The positive and negative reference voltage (+Vref and -Vref) of PIC ADC is software selectable, which can be VDD, VSS, voltage at RA2 or RA3. This A/D Converter module can also operate in sleep mode in which clock is derived from its internal RC oscillator. Following points may help you to understand the concept of reference voltages.

  • When the ADC input is -Vref, result will be 0000000000
  • When the ADC input is +Vref, result will be 1111111111
  • Resolution of ADC = (+Vref – -Vref)/(210 – 1), which is the minimum voltage required to change the ADC result by one bit.

We require some hardware knowledge to program PIC ADC in Hi-Tech C. If you don’t need hardware knowledge please skip this part and go to Circuit Diagram.

ADC Module in Detail

Registers

PIC ADC has 4 registers :

  • ADCON0 – ADC Control Register 0
  • ADCON1 – ADC Control Register 1
  • ADRESH – ADC Result High Register
  • ADRESL – ADC Result Low Register

 ADCON0 Register

ADCON0 Register - PIC 16F877A

ADCON0 Register – PIC 16F877A

  • ADCS1 and ADCS2 are used to select A/D Conversion Clock. It should be selected in accordance with device clock.
  • CH2, CH1 and CH0 are used to select one of the analog input channel out of eight channels.
  • GO/DONE is the A/D Conversion Status bit. Setting this bit initializes A/D Conversion and will be automatically cleared when the conversion is complete.
  • ADON is used to switch on/off the ADC Module. When it is 1, the ADC Module turns ON and when it is 0, the ADC Module will be OFF.

ADCON1 Register

ADCON1 Register - PIC 16F877A

ADCON1 Register – PIC 16F877A

  • ADFM is the ADC Result Format select bit. Two 8 bit register (ADRESH and ADRESL) are provided to store the 10-bit result of A/D Conversion, thus we need’t use 6 bits. When ADFM is 1, the result will be right justified, ie Most Significant Bits of ADRESH will be read as 0. When ADFM is 0, the result will be left justified, ie Least Significant Bits of ADRESL will be read as zero.
  • ADCS2 is used to select A/D Conversion Clock in association with ADCS1 and ADC2 of ADCON0 register.
  • PCFG3 – PCFG0 are the A/D Port Configuration Control bits. Each pin amoung AN0 – AN7 is configured as analog, digital or reference voltage inputs according to the status of these configuration bits as given below.
PIC ADC Port Configuration Bits

PIC ADC Port Configuration Bits

Note : TRIS Registers of Analog inputs must be configured as input for the proper operation.

ADC Block Diagram

ADC Module Block Diagram - PIC16F877A

ADC Module Block Diagram – PIC16F877A

Selection of A/D Conversion Clock

The time for A/D Conversion per bit is defined as TAD and it requires minimum 12TAD to generate the 10-bit result. The time TAD is determined by the A/D Conversion Clock which is software selectable to following options.

  •  2 TOSC
  • 4 TOSC
  • 8 TOSC
  • 16 TOSC
  • 32 TOSC
  • 64 TOSC
  • Internal RC oscillator of ADC Module

TOSC is the time period of the device clock usually provided by the crystal oscillator.
Care should be taken while selecting the A/D Conversion Clock, such that the clock should provide the minimum TAD (1.6μS) required for the correct A/D Conversion. So refer the following table before setting the ADC clock.

ADC Clock Selection Table - PIC 16F877A

ADC Clock Selection Table – PIC 16F877A

Circuit Diagram

Using Internal ADC Module of PIC Microcontroller

Using Internal ADC Module of PIC Microcontroller

I hope that you already go through our first tutorials, so I am not going to explain deeply about the circuit. The reference voltages of ADC is set to VDD (5V) and VSS (GND) though software (code given below). Analog input is given to Channel 0 using a potentiometer, thus we can vary the ADC input voltage from VSS to VDD. The 10-bit result of ADC is displayed using 10 LEDs, and 470Ω resistors are used to limit current through them.

Hi-Tech C Code

#include<htc.h>
#include<pic.h>

#define _XTAL_FREQ 8000000

void ADC_Init()
{
  ADCON0 = 0x41; //ADC Module Turned ON and Clock is selected
  ADCON1 = 0xC0; //All pins as Analog Input
                 //With reference voltages VDD and VSS
}

unsigned int ADC_Read(unsigned char channel)
{
  if(channel > 7) //If Invalid channel selected 
    return 0;     //Return 0

  ADCON0 &= 0xC5; //Clearing the Channel Selection Bits
  ADCON0 |= channel<<3; //Setting the required Bits
  __delay_ms(2); //Acquisition time to charge hold capacitor
  GO_nDONE = 1; //Initializes A/D Conversion
  while(GO_nDONE); //Wait for A/D Conversion to complete
  return ((ADRESH<<8)+ADRESL); //Returns Result
}

void main()
{
  unsigned int a;
  TRISB = 0x00; //PORTB as output
  TRISC = 0x00; //PORTC as output
  TRISA = 0xFF; //PORTA as input
  ADC_Init(); //Initializes ADC Module

  do
  {
    a = ADC_Read(0); //Reading Analog Channel 0
    PORTB = a; //Lower 8 bits to PORTB
    PORTC = a>>8; //Higher 2 bits to PORTC
    __delay_ms(100); //Delay
  }while(1); //Infinite Loop
}

I think the program is completely explained through its comments. If you have any doubts please comment below.

You can download Hi-Tech C and Proteus files here…

Using Internal ADC PIC Hi-Tech C



  • saurabh

    could you please explain how to convert this 10bit output of PIC to 8 bit output? Basically is it possible to convert this PIC to 8 bit resolution?

  • http://www.electrosome.com/ Ligo George

    Just ignore the least significant two bit.. you will get 8 bit resolution output..
    ie, if ‘adc’ is the 10 bit value… then try
    adc = adc>>2;

  • saurabh

    alright,thank you.
    there should be no differences in the code while using PIC16f877A and PIC16f877B right?

  • http://www.electrosome.com/ Ligo George

    PIC 16F877B ??? I can’t find that microcontroller…

  • Arun

    Hello, i would like to light LED based on the voltage level like a level indicator. how can i configure in software? may be 5 LED’s to show the voltage level from 0V to 5V..

  • Arun

    Im working with pic16f1788.. In this pic, I configured the ADCON0 to give 10bit result. so the resolution will be 1024. i directly checked the value of the variable ‘a’ like(a256 && a<512, etc etc..) using if statement. But it didn't work. Kindly help me.

  • http://www.electrosome.com/ Ligo George

    Hello, your logic is correct….. so it will work.. if you properly written the code..

  • Atoki

    nice explanation, kudos to you

  • Atoki

    Ligo, please I need you to explain to me which of the leg pic16f88 can I connect current sensing from my op-amp to and voltage sensing from my voltage divider ? I am confused about the legs which I will connect them to. I am designing dc-dc boost converter taking my source from solar panel. thanks

  • http://www.electrosome.com/ Ligo George

    Refer the pin diagram of pic 16f88… you can use pins AN0, AN1, AN2 etc..

  • Dinesh

    I have read ur tutorial on ADC for hi-tech c complier.I have a doubt in the function called a= adc_read(4),What 4 indicates??

  • http://www.electrosome.com/ Ligo George

    4 indicates.. 4th channel of ADC… There was an error in the above program.. which is corrected..

  • Susheel Parashar

    Hi… im working with PIC16f72 …8 bit adc resolution and adc is going well and i want to change the adc value (e.g.0-255) into range (0000-3300) on 4 digit 7 segment display..so plz anybody help how to change it in that range.

  • harsh

    am working on pic16f877a.. a am basically making a sound level meter. so after i acquire the analog signal to digital and store it in the register, i need to convert that into decibels. how to do that? look-up table?

  • saba

    how to connect the output of water level indicator to pic 16f877a using internal adc plz help me…

  • harsh

    getting error.. undefined identifier “GO_nDONE”
    how to rectify it?

  • Atoki

    Hi Ligo George,
    please how can i program pic16f88 to be able to measure voltage current sampling ? I need it to track mppt of a 12V solar panel. I have written one program in hitech c, but not measuring anything.
    Cheers.

  • sangeetha

    hi sir,

    i got an following errors

    (890) Your evaluation period has ended. To continue to experience maximum performance, contact HI-TECH Software to purchase a license. (warning)

    Error [192] H:second yearPHASE 2ADC1.c; 19.1 undefined identifier “GO_nDONE”

    Error [285] H:second yearPHASE 2ADC1.c; 39.1 no identifier in declaration

    Warning [374] H:second yearPHASE 2ADC1.c; 39.1 missing basic type; int assumed

    Error [314] H:second yearPHASE 2ADC1.c; 39.1 “;” expected