The data we process in a microcontroller normally deals with digital signals. But there may a situation where we have to deal with external inputs such as analog signals. All most all the input signals from physical sensors are of analog signals. In such cases, we can interface the microcontroller with an external device such as an ADC0808 to convert the analog signal to a digital signal. Because our microcontrollers can only understand 0 and 1. In this article, we look into the details of ADC interfacing with 8051.
In the present time, there are lots of microcontrollers in the market which has inbuilt ADC with one or more channels, E.g.: PIC18F4550, LPC1768, etc. And by using their ADC registers we can interface. Unfortunately, 8051 doesn’t have an internal module so we will go for an external ADC. which is ADC0808.
ADC0808 is a commonly used External 8 bit ADC and it has 28 pins. It can measure up to eight ADC values from 0 to 5 volt since it has eight channels. when voltage reference is +5V, its Step size will be 19.53mV. That is, for every increase of 19.53mV on the input side there will be an increase of 1 bit at the output side.
ADC0808 needs an external clock to operate. The ADC needs some specific control signals for its operations like start conversion and bring data to output pins. When the conversion is complete the EOC pins go low to indicate the end of a conversion and that the data is ready to be picked up.
We can select any input channel by using the Address lines ADD A, ADD B and ADD C. As you can see in the below table, We can select the input line IN0 by keeping all three address lines ADD A, ADD B and ADD C Low.
Voltage value for each increase of bit can be found using the equation :
Step Size = (Vref+ – Vref-)/256
Step size can be multiplied with ADC output to get the voltage.
If Vref+ is connected to 5v and Vref- is connected to ground the equation becomes :
Step size = (5 – 0)/256= 19.53 mv
In such a case if the output value is 01101110 = 110
The voltage value will be : 110 x 19.53 mV = 2.14 V .
The following circuit shows the interfacing of ADC with 8051. In this circuit, we have used AT89S52 as an 8051 microcontroller and ADC0808 as an external ADC module. we will use a Potentiometer to vary the voltage. It is connected to channel 0 of the ADC0808. instead, if you want you can use real sensors. Also, to display the output we will use a 16×2 character LCD. We have connected the output of ADC0808 to port 1.
First, we will include header files and define variable and input & output pins for ADC and LCD.
#include<reg51.h> #include<stdio.h> sbit ale=P3^3; sbit oe=P3^6; sbit start=P3^4; sbit eoc=P3^5; sbit clk=P3^7; sbit ADDA=P3^0; //Address pins for selecting input channels. sbit ADDB=P3^1; sbit ADDC=P3^2; #define lcd P2 //lcd sbit rs=P2^0; sbit rw=P2^2; sbit en=P2^1; #define Adc_Data P1 //ADC int result[3],ADC_value;
We will give the clock for the ADC module using our controller itself s, for that, we have made a Function to generate a clock of frequency 500KHZ using Timer 0 interrupt.
void timer0() interrupt 1 { clk=~clk; }
Functions are made for delay and LCD.
void delay(unsigned int count) { int i,j; for(i=0;i<count;i++) for(j=0;j<100;j++); } void lcd_data(unsigned char ch) { rs=1; rw=0; lcd=ch & 0xF0; en=1; delay(1); en=0; lcd=ch<<4 & 0xF0; en=1; delay(1); en=0; } void lcdcmd(unsigned char ch) { rs=0; lcd=ch & 0xf0; en=1; delay(1); en=0; lcd=ch<<4 & 0xF0; en=1; delay(1); en=0; } lcdprint(char *str) //Function to send string data to LCD. { while(*str) { lcd_data(*str); str++; } } void lcd_init() //Function to inisialize the LCD { lcdcmd(0x02); lcdcmd(0x28); lcdcmd(0x0e); lcdcmd(0x01); }
In the function adc() first, the required channel is chosen using ADD A, ADD B and ADD C pins. After which read_adc() function is called. In read_adc() function, we wait for the conversion and the output is given to the variable ADC_value. which is then displayed after converting to string.
void show() { sprintf(result,"%d",number); lcdprint(result); lcdprint(" "); } void read_adc() //Function to drive ADC { ADC_value=0; ale=1; start=1; delay(1); ale=0; start=0; while(eoc==1); while(eoc==0); oe=1; ADC_value=Adc_data; delay(1); oe=0; } void adc() { ADDC=0; // Selecting input channel IN0 using address lines ADDB=0; ADDA=0; lcdcmd(0xc0); read_adc(); show(); }
In the main function timer 0 interrupt is configured for the clock to drive ADC0808. LCD and the ADC0808 is also initialized.
A while(1) loop has been created to read and display the ADC value again and again.
void main() { eoc=1; ale=0; oe=0; start=0; TMOD=0x02; TH0=0xFD; lcd_init(); IE=0x82; TR0=1; while(1) { adc(); ADC_value=0; } }