Description

100%
100%

ADC (Analogue to Digital Conversion) is needed to interface many sensors with the microcontroller. The sensor output generally is in the analogue form and so we need to convert it to digital form so that microcontroller can understand it. Today in this tutorial we are going to work with ADC single and multiple channels in PIC18.

I am using PIC18F4550 and it have

  • Single ADC with 13 channels. This means that we can connect 13 different ADC devices and work with them at the same time.
  • ADC Resolution is 10 bit which means that the converted digital values will vary from 0-1023 (2^10)

The ADC in PIC18F4550 works with 5 Registers and they are as follows

  • A/D Control Register 0 (ADCON0)
  • A/D Result High Register (ADRESH)
  • A/D Result Low Register (ADRESL)
  • A/D Control Register 1 (ADCON1)
  • A/D Control Register 2 (ADCON2)

Registers Used in ADC

ADCON0 Register

ADCON1 Register

ADCON2 Register

HOW TO

In order to program the ADC module, we have to do the following

1.) Configure the A/D module:
• Configure analog pins, voltage reference and digital I/O (ADCON1)
• Select A/D input channel (ADCON0)
• Select A/D acquisition time (ADCON2)
• Select A/D conversion clock (ADCON2)
• Turn on A/D module (ADCON0)

2.) Start conversion:
• Set GO/DONE bit (ADCON0 register)

3.) Wait for A/D conversion to complete:
• Polling for the GO/DONE bit to be cleared

4.) Read A/D Result registers (ADRESH:ADRESL)

Some Insight into the CODE

void ADC_Init (void)
{
    TRISA0 = 1;  // PA0 as INPUT
    ADCON1 = 0x0E;  // VCFG0 = 00 -> Vref = VSS, VDD,,,, PCFG3:PCFG0=1110
    ADCON2 = 0x92;  // A/D CLK=FOSC/32, 4TAD, RIGHT justified
}

ADCON1 = 0x0E; Selects the Vref Source as Vss and Vdd and AN0 is configured as analogue

ADCON2 = 0x92; A/D clock is FOSC/32, Acquasition time is 4TAD, and the A/D Result is RIGHT Justified.

uint16_t ADC_Read(uint8_t channel)
{
    ADCON0 = (channel<<2);
    
    ADCON0|=0x03; 

    while(ADCON0bits.GO_nDONE); 

    return ((ADRESH<<8) | (ADRESL));
}

Reads the particular channel by performing the following:-

  • ADCON0 =((channel<<2)); selects the channel to read
  • ADCON0|=0x03; Turns the ADC ON (ADON) and START Conversion (GO)
  • while(ADCON0bits.GO_nDONE); wait for the conversion to complete by checking GO_nDONE bit
  • return the 10 bit data obtained from the sensor

Single CHANNEL

Using single channel is pretty straight forward. Read the ADC value from the respective channel and print in on the LCD or store it.

ADC_Init ();
while (1)
{
  ADC_Result = ADC_Read(0); // read channel 0-> RA0    
  sprintf (char_value, "%04d", ADC_Result);
        
  lcd_send_cmd(0x80);
  lcd_send_string("VAL1:- ");
  lcd_send_string(char_value);
  __delay_ms (200);  // read every 200ms
}

Multiple CHANNELS

In order to read multiple channels, we need to first configure the respective channel Pins as analogue in the ADCON1 Register. For example if I want to read 3 channels AN0, AN1, AN2, I will configure Bits PCFG3:PCFG0 as 1100 to set these 3 Pins as analogue.

void ADC_Init (void)
{
    TRISA0 = 1;  // PA0 as INPUT
    TRISA1 = 1;  // PA1 as INPUT
    TRISA2 = 1;  // PA2 as INPUT
    ADCON1 = 0x0C;  // VCFG0 = 00 -> Vref = VSS, VDD,,,, PCFG3:PCFG0=1100
    ADCON2 = 0x92;  // A/D CLK=FOSC/32, 4TAD, RIGHT justified
    
}

ADC_Init ();
while (1)
{
  ADC_Result[0] = ADC_Read(0); // read channel 0-> RA0    
  ADC_Result[1] = ADC_Read(1); // read channel 1-> RA1 
  ADC_Result[2] = ADC_Read(2); // read channel 2-> RA2 
  Convert the values and print on the LCD
}

As shown above, we can read all channels one by one. We can also read them at any (random) point in our program.

YOU CAN DOWNLOAD FULL CODE AT THE END OF THIS POST

100%
100%

Connections

100%
100%
100%
100%

Result

100%
100%
Check out the VIDEO Below
100%
100%

DOWNLOAD

You can buy me a coffee sensor 🙂

Or Just download the CODE below

100%
100%

Leave a Reply

avatar
  Subscribe  
Notify of
Menu