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$$
ADC Pins
Lets see the pins of the ADC0809
- Addres Lines(A,B,C): As mentioned earlier, ADC0809 has 8-muliplexed ADC channels. A particular input channel is selected by using these address bits as shown below.
C | B | A | Selected ADC channel |
---|---|---|---|
0 | 0 | 0 | INO |
0 | 0 | 1 | IN1 |
0 | 1 | 0 | IN2 |
0 | 1 | 1 | IN3 |
1 | 0 | 0 | IN4 |
1 | 0 | 1 | IN5 |
1 | 1 | 0 | IN6 |
1 | 1 | 1 | IN7 |
- Address Latch Enable (ALE): A low-to-high signal at this pin will latch the above-selected address and selected the respective channel for ADC conversion.
- START Conversion (SOC): The A/D converter’s successive approximation register (SAR) is reset on the positive edge of the start conversion (SC) pulse. Thus we need to generate a LOW-HIGH-LOW pulse for starting the ADC conversion.
- End of Conversion (EOC): Once the conversion is over, this pin is pulled HIGH by ADC0809. This pin needs to be monitored for the conversion to complete and then read the data.
- Output Enable(OE): ADC0809 does the adc conversion and holds the data in the internal registers. A HIGH signal on this pin will bring the data on the output lines.
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!