A7.8051 Interfacing ADC: LDR & LM35
In this tutorial, we are going to discuss the interfacing of external ADC0808/9 with 8051.
We will be reading the ADC values from channel Zero and transmitted on UART at 9600 baudrate.
Contents
[hide]ADC-0808/9
8051 does not have the inbuilt ADC and we will be using the external 8-bit ADC ie. ADC0808/ADC0809.
ADC0809 is an 8-bit Successive Approximation ADC which is multiplexed among 8 input pins.
The A/D module has high and low-voltage reference input that can be set using the pins Vref+ and Vref- as shown in the below image.
With 5v as the Vref+ and 0v as Vref- the resolution of ADC0809 can be determined as below:
$$resolution of ADC = ((Vref+) - (Vref-))/(2^{8}-1) = 5/255 =0.0196 = 19.6mv$$
The below table shows the ADC input pins multiplexed with other GPIO pins.
The ADC pin can be enabled by configuring the corresponding ACON1 register.
When the ADC function is selected for a pin ,then other Digital signals are disconnected from the ADC input pins.
Adc Channel | Pic16f877a Pin | Pin Function |
---|---|---|
0 | RA0 | AN0 |
1 | RA1 | AN1 |
2 | RA2 | AN2/VREF- |
3 | RA3 | AN3/VREF+ |
4 | RA5 | AN4 |
2 | RE0 | AN5 |
3 | RE1 | AN6 |
4 | RE2 | AN7 |
ADC Registers
The below table shows the registers associated with PIC16F877A ADC.
Register | Description |
---|---|
ADCON0 | Used to Turn ON the ADC, Select the Sampling Freq and also Start the conversion. |
ADCON1 | Used to configure the gpio pins for ADC |
ADRESH | Holds the higher byte of ADC result |
ADRESL | Holds the lower byte of ADC result |
Now lets see how to configure the individual registers for UART communication.
ADCON0 | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ADCS1 | ADCS0 | CHS2 | CHS1 | CHS0 | GO/DONE | — | ADON |
ADCS2-ADCS0:A/D Conversion Clock Select bits
CHS2-CHS0:Analog Channel Select bits
000 = Channel 0 (AN0)
001 = Channel 1 (AN1)
010 = Channel 2 (AN2)
011 = Channel 3 (AN3)
100 = Channel 4 (AN4)
101 = Channel 5 (AN5)
110 = Channel 6 (AN6)
111 = Channel 7 (AN7)
GO/DONE: A/D Conversion Status bit
When ADON = 1:
1 = A/D conversion in progress (setting this bit starts the A/D conversion which is automatically cleared by hardware when the A/D conversion is complete)
0 = A/D conversion not in progress
ADON: A/D On bit
1 = A/D converter module is powered up
0 = A/D converter module is shut-off and consumes no operating current
ADCON1 | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ADFM | ADCS2 | — | — | PCFG3 | PCFG2 | PCFG1 | PCFG0 |
ADFM: A/D Result Format Select bit
1 = Right justified. Six (6) Most Significant bits of ADRESH are read as ‘0’.
0 = Left justified. Six (6) Least Significant bits of ADRESL are read as ‘0’.
ADCS2: A/D Conversion Clock Select bit
Check ADCS1:ADCS0 of ADCON0 register.
PCFG3-PCFG0: A/D Port Configuration Control bits
Hardware Connections
Code
Below is the sample code to read the ADC value of channel0 and send it on UART at 9600 baud rate.
#include<pic16f877a.h> | |
#define SBIT_ADON 0 | |
#define SBIT_CHS0 3 | |
#define SBIT_ADFM 7 | |
void delay(int cnt) | |
{ | |
while(cnt--); | |
} | |
void ADC_Init() | |
{ | |
ADCON0=0x00; // sampling freq=osc_freq/2,ADC off initially | |
ADCON1=(1<<SBIT_ADFM); // All pins are configured as Analog pins and ADC result is right justified | |
} | |
int ADC_Read(int adcChannel) | |
{ | |
ADCON0 = (1<<SBIT_ADON) | (adcChannel<SBIT_CHS0); //select required channel and turn ON adc | |
delay(1000); //Acquisition Time(Wait for Charge Hold Capacitor to get charged ) | |
GO=1; // Start ADC conversion | |
while(GO_DONE==1); // Wait for the conversion to complete | |
// GO_DONE bit will be cleared once conversion is complete | |
return((ADRESH<<8) + ADRESL); // return right justified 10-bit result | |
} | |
int main() | |
{ | |
int adcValue=0; | |
TRISB = 0x00; // Configure PORTB and PORTD as output to display the ADC values on LEDs | |
TRISD = 0x00; | |
ADC_Init(); //Initialize the ADC module | |
while(1) | |
{ | |
adcValue = ADC_Read(0); // Read the ADC value of channel zero | |
PORTB = (adcValue & 0xff); //Adc value displayed on LEDs connected to PORTB,PORTD | |
PORTD = (adcValue>>8) & 0x03; // PORTB will display lower 8-bits and PORTD higher 2-bits | |
} | |
} |
Using ExploreEmbedded Libraries
#include "adc.h" | |
#include "uart.h" | |
int main() | |
{ | |
int adcValue; | |
ADC_Init(); /* Initialize the ADC module */ | |
UART_Init(9600); /* Initialize UART at 9600 baud rate */ | |
while(1) | |
{ | |
adcValue = ADC_GetAdcValue(0); // Read the ADC value of channel zero | |
UART_Printf("ADC0 Value:%4d \n\r",adcValue); // Send the value on UART | |
} | |
return (0); | |
} |
Downloads
Download the complete project folder from the below link:
Hardware design Files and Code Library
Have an opinion, suggestion , question or feedback about the article let it out here!