adc interfacing

Thread Starter

tharunmalli

Joined Apr 7, 2014
12
I am actually interfacing adc 0804 to p89v51rd2. My main task is to vary the analog input to adc and get the resulting value on hyper terminal in hex format.
I know how to interface adc but the problem is how to convert the binary data to hex format and send it through serial communication.
Please any one post the c program to convert binary data to hex in 8051.
Please help me...
 

t06afre

Joined May 11, 2009
5,934
Ah well this some sort of school assignment is it not ;) So just posting the solutions would be wrong do you not think so?
Hyperterm work with ACSII codes http://www.asciitable.com/ So if your ADC result is say 0xA5 You will need to send the following bytes in hex 0x41 and 0x35 Since you will be sending a series of samples sending a space 0x20 after the two bytes would be wise.
The first thing you will need to do is isolating the ADC result into two groups of 4 bits(nibble). Then take close look at the ASCII table. You see that numbers start at 0x30 hex. So if the result for one of the nibbles is in range 0 to 9. You just add 0x30 to the nibble and send it out on the serial line. If the nibble is range 0x0A to 0x0F it is a little bit more tricky. But I leave it to you to sort that out
 

Thread Starter

tharunmalli

Joined Apr 7, 2014
12
I am interfacing adc 0804 with p89v51rd2. my aim is to get the adc output in the form of 00-FF on hyper terminal. I am attaching the code i wrote..I am using keil software , this program shows no error but in hardware its not working .
the problem is adc is sending the binary data to controller . but on hyperterminal i am getting only one character i.e T=ox54.... please help to figure out whats the problem.. please help

Rich (BB code):
#include<reg51.h>
#define input P1 //Input port to read the values of ADc
sbit wr= P0^1;    // Write pin. It is used to start the conversion.
sbit rd= P0^0;    // Read pin. It is used to extract the data from internal register to the output pins of ADC.
sbit intr= P0^2;
void delay(unsigned int msec )     // The delay function provides delay in msec.
{ int i,j ;
for(i=0;i<msec;i++) for(j=0; j<1275; j++);
}

void adc()          // Function to read the values from ADC and store it accumulator.
{
rd=1;
wr=0;
delay(1);
wr=1;
while(intr==1);
rd=0;
ACC=input;
delay(1);
intr=1;
}
void main()
{ unsigned char a,b,c,d,i,j,x[3],z[2];
input=0xff;       
while(1)
{ adc();
delay(1);
a=ACC;
b=ACC;
c=a&0x0F;
d=b&0xF0;
d=d>>4;
z[0]=d;
z[1]=c;
delay(1);
for(i=0;i<=1;i++)
{
switch(z)
{
case 0000:
x=0x30;
break;
case 0001:
x=0x31;
break;
case 0010:
x=0x32;
break;
case 0011:
x=0x33;
break;
case 0100:
x=0x34;
break;
case 0101:
x=0x35;
break;
case 0110:
x=0x36;
break;
case 0111:
x=0x37;
break;
case 1000:
x=0x38;
break;
case 1001:
x=0x39;
break;
case 1010:
x=0x41;
break;
case 1011:
x=0x42;
break;
case 1100:
x=0x43;
break;
case 1101:
x=0x44;
break;
case 1110:
x=0x45;
break;
case 1111:
x=0x46;
break;
}}
x[2]=0x54;
delay(1);
TMOD=0x20;
TH1=0xFD;
SCON=0x50;
TR1=1;
for(j=0;j<=3;j++)
{
SBUF=x;
while(TI==0);
TI=0;
delay(1);
}
}
}
 
Last edited by a moderator:

Thread Starter

tharunmalli

Joined Apr 7, 2014
12
I am interfacing adc 0804 with p89v51rd2. my aim is to get the adc output in the form of 00-FF on hyper terminal. I am attaching the code i wrote..I am using keil software , this program shows no error but in hardware its not working .
the problem is adc is sending the binary data to controller . but on hyperterminal i am getting only one character i.e T=ox54.... please help to figure out whats the problem.. please help

Rich (BB code):
#include<reg51.h>
#define input P1 //Input port to read the values of ADc
sbit wr= P0^1; // Write pin. It is used to start the conversion.
sbit rd= P0^0; // Read pin. It is used to extract the data from internal register to the output pins of ADC.
sbit intr= P0^2;
void delay(unsigned int msec ) // The delay function provides delay in msec.
{ int i,j ;
for(i=0;i<msec;i++) for(j=0; j<1275; j++);
}

void adc() // Function to read the values from ADC and store it accumulator.
{
rd=1;
wr=0;
delay(1);
wr=1;
while(intr==1);
rd=0;
ACC=input;
delay(1);
intr=1;
}
void main()
{ unsigned char a,b,c,d,i,j,x[3],z[2];
input=0xff; 
while(1)
{ adc();
delay(1);
a=ACC;
b=ACC;
c=a&0x0F;
d=b&0xF0;
d=d>>4;
z[0]=d;
z[1]=c;
delay(1);
for(i=0;i<=1;i++)
{
switch(z)
{
case 0000:
x=0x30;
break;
case 0001:
x=0x31;
break;
case 0010:
x=0x32;
break;
case 0011:
x=0x33;
break;
case 0100:
x=0x34;
break;
case 0101:
x=0x35;
break;
case 0110:
x=0x36;
break;
case 0111:
x=0x37;
break;
case 1000:
x=0x38;
break;
case 1001:
x=0x39;
break;
case 1010:
x=0x41;
break;
case 1011:
x=0x42;
break;
case 1100:
x=0x43;
break;
case 1101:
x=0x44;
break;
case 1110:
x=0x45;
break;
case 1111:
x=0x46;
break;
}}
x[2]=0x54;
delay(1);
TMOD=0x20;
TH1=0xFD;
SCON=0x50;
TR1=1;
for(j=0;j<=3;j++)
{
SBUF=x;
while(TI==0);
TI=0;
delay(1);
}
}
}
 
Last edited by a moderator:

t06afre

Joined May 11, 2009
5,934
I am sorry for that you struggle. But have you tried some sort of debugging of your code. Like single stepping and using watches. Then you will find out at which point your code do not do what it is expected to do.
 

tshuck

Joined Oct 18, 2012
3,534
I think the problem is that the switch cases are being interpreted in decimal, and you've written them as hexadecimal - if that's the problem, switching to the method referenced in post #2 will fix it, or you could fix the case statements...
 
Last edited:

THE_RB

Joined Feb 11, 2008
5,438
Doesn't the C compiler have a function to convert byte to ASCII Hex? That would make your code so much better.

Or you could use a lookup table;
ascii_data[16]
containing the 16 chars 0-9 and A-F.
 

djsfantasi

Joined Apr 11, 2010
9,163
Is that not what
Rich (BB code):
c=a&0x0F;
d=b&0xF0;
does?:)
Almost, if you include the next line. Missed that when I was trying to figure out how he was reading the ADC. I first thought he was reading the ADC twice, but now see ACC is the last reading. Still not clear on the actual read function, but as long as ACC contains the last ADC value after the call to adc().

However, I think I see the problem. The line
Rich (BB code):
SBUF=x(i);
should use the variable j. The previous FOR loop leaves the value of i=2. Then, before the j FOR loop, x(2)=0x54 is executed. In the j FOR loop, x(2) is moved to SBUF repeatedly, and the ASCII values expected in x(0) and x(1) never get sent. This is consistent with the behavior the OP reported.

Also, I totally agree with tshuck's observation. CASE 1011 is testing for decimal one thousand eleven, not decimal 11, which corresponds to 0x0B.

RB's suggestions are excellent. There are many ways to code a problem, and only by coding yourself and reading other's code will you learn. In fact, there was one line where I thought you were going to define a lookup table, but…
 
Last edited:

Thread Starter

tharunmalli

Joined Apr 7, 2014
12
Thanks for ur advice.
I am attaching the code i wrote. when I execute it only T (just to differentiate between each transmission) is displayed. so please help me out... Thanks in advance

Rich (BB code):
#include<reg51.h>
#define input P1 //Input port to read the values of ADc
sbit wr= P0^1; // Write pin. It is used to start the conversion.
sbit rd= P0^0; // Read pin. It is used to extract the data from internal register to the output pins of ADC.
sbit intr= P0^2;
void delay(unsigned int msec ) // The delay function provides delay in msec.
{ int i,j ;
for(i=0;i<msec;i++) for(j=0; j<1275; j++);
}

void adc() // Function to read the values from ADC and store it accumulator.
{
rd=1;
wr=0;
delay(1);
wr=1;
while(intr==1);
rd=0;
ACC=input;
delay(1);
intr=1;
}
void main()
{ unsigned char a,b,c,d,i,j,x[3],z[2];
input=0xff; 
while(1)
{ adc();
delay(1);
a=ACC;
b=ACC;
c=a&0x0F;
d=b&0xF0;
d=d>>4;
z[0]=d;
z[1]=c;
delay(1);
for(i=0;i<=1;i++)
{
switch(z)
{
case 0000:
x=0x30;
break;
case 0001:
x=0x31;
break;
case 0010:
x=0x32;
break;
case 0011:
x=0x33;
break;
case 0100:
x=0x34;
break;
case 0101:
x=0x35;
break;
case 0110:
x=0x36;
break;
case 0111:
x=0x37;
break;
case 1000:
x=0x38;
break;
case 1001:
x=0x39;
break;
case 1010:
x=0x41;
break;
case 1011:
x=0x42;
break;
case 1100:
x=0x43;
break;
case 1101:
x=0x44;
break;
case 1110:
x=0x45;
break;
case 1111:
x=0x46;
break;
}}
x[2]=0x54;
delay(1);
TMOD=0x20;
TH1=0xFD;
SCON=0x50;
TR1=1;
for(j=0;j<=3;j++)
{
SBUF=x;
while(TI==0);
TI=0;
delay(1);
}
}
}
 
Last edited by a moderator:

Thread Starter

tharunmalli

Joined Apr 7, 2014
12
Thank u so much.. I changed the variable from i to j in SBUF= x .. But the problem is I am getting 00T even if i vary the adc.adc working properly may be some problem with program.. I am posting my modified program

Rich (BB code):
#include<reg51.h>
#define input P1 //Input port to read the values of ADc
sbit wr= P0^1;    // Write pin. It is used to start the conversion.
sbit rd= P0^0;    // Read pin. It is used to extract the data from internal register to the output pins of ADC.
sbit intr= P0^2;
void delay(unsigned int msec )     // The delay function provides delay in msec.
{ int i,j ;
for(i=0;i<msec;i++) for(j=0; j<1275; j++);
}

void adc()          // Function to read the values from ADC and store it accumulator.
{
rd=1;
wr=0;
delay(1);
wr=1;
while(intr==1);
rd=0;
ACC=input;
delay(1);
intr=1;
}
void main()
{ unsigned int a,b,c,d,i,z[3],x[4],j;
input=0xff;       
while(1)
{ adc();
delay(1);
a=ACC;
b=ACC;
c=a&0x0F;
d=b&0xF0;
d=d>>4;
z[0]=d;
z[1]=c;
delay(1);
for(i=0;i<=1;i++)
{
switch(z)
{
case (0):
x=0x30;
break;
case (1):
x=0x31;
break;
case (2):
x=0x32;
break;
case (3):
x=0x33;
break;
case (4):
x=0x34;
break;
case (5):
x=0x35;
break;
case (6):
x=0x36;
break;
case (7):
x=0x37;
break;
case (8):
x=0x38;
break;
case (9):
x=0x39;
break;
case (10):
x=0x41;
break;
case (11):
x=0x42;
break;
case (12):
x=0x43;
break;
case (13):
x=0x44;
break;
case (14):
x=0x45;
break;
case (15):
x=0x46;

}}
x[2]=0x54; // ASCII value for T just to differeciate between each transmission;
delay(1);
TMOD=0x20;
TH1=0xFD;
SCON=0x50;
TR1=1;
for(j=0;j<=3;j++)
{
SBUF=x[j];
while(TI==0);
TI=0;
delay(1);
}
}
}
 
Last edited by a moderator:

tshuck

Joined Oct 18, 2012
3,534
You do realize that your code doesn't just magically appear in code tags(which provides a special formatting to code so it's easier to read), right? Bertus is constantly modifying your posts to do us and (by extension) you a favor. Please use code tags when you post your code(either click the "#" button while posting, or write [code ] & [/code ], without the space, around your code) so the forum knows how to format it. It is quite annoying to attempt read it without the formatting.

That said, have you tried putting fixed values for your ADC results? That way you can tell if it is an error in your transmission/formatting code, or your ADC.

Try the following(notice the use of code tags changes the formatting making it easier to read?;)):
Rich (BB code):
#include<reg51.h>
#define input P1 //Input port to read the values of ADc
sbit wr= P0^1;    // Write pin. It is used to start the conversion.
sbit rd= P0^0;    // Read pin. It is used to extract the data from internal register to the output pins of ADC.
sbit intr= P0^2;
void delay(unsigned int msec )     // The delay function provides delay in msec.
{
	int i,j ;
	for(i=0;i<msec;i++)
		for(j=0; j<1275; j++);
}

void adc()          // Function to read the values from ADC and store it accumulator.
{
	rd=1;
	wr=0;
	delay(1);
	wr=1;
	while(intr==1);
	rd=0;
	ACC=input;
	delay(1);
	intr=1;
}
void main()
{
	unsigned int a,b,c,d,i,z[3],x[4],j;
	input=0xff;       
	while(1)
	{
		adc();
		delay(1);
		//Uncomment the following lines to use the ADC results
		//a=ACC;
		//b=ACC;
		a=0x7F;
		b=a;
		c=a&0x0F;
		d=b&0xF0;
		d=d>>4;
		z[0]=d;
		z[1]=c;
		delay(1);
		for(i=0;i<=1;i++)
		{
			switch(z)
			{
				case (0):
				{
					x=0x30;
					break;
				}
				case (1):
				{
					x=0x31;
					break;
				}
				case (2):
				{
					x=0x32;
					break;
				}
				case (3):
				{
					x=0x33;
					break;
				}
				case (4):
				{
					x=0x34;
					break;
				}
				case (5):
				{
					x=0x35;
					break;
				}
				case (6):
				{
					x=0x36;
					break;
				}
				case (7):
				{
					x=0x37;
					break;
				}
				case (8):
				{
					x=0x38;
					break;
				}
				case (9):
				{
					x=0x39;
					break;
				}
				case (10):
				{
					x=0x41;
					break;
				}
				case (11):
				{
					x=0x42;
					break;
				}
				case (12):
				{
					x=0x43;
					break;
				}
				case (13):
				{
					x=0x44;
					break;
				}
				case (14):
				{
					x=0x45;
					break;
				}
				case (15):
				{
					x=0x46;
					break;
				}

			}
		}
		x[2]=0x54; // ASCII value for T just to differeciate between each transmission;
		delay(1);
		TMOD=0x20;
		TH1=0xFD;
		SCON=0x50;
		TR1=1;
		for(j=0;j<=3;j++)
		{
			SBUF=x[j];
			while(TI==0);
			TI=0;
			delay(1);
		}
	}
}


Also note the indentation that makes it easier to read and the addition of curly braces on your case statements.

You should see "7FT".
 

THE_RB

Joined Feb 11, 2008
5,438
I really don't like that huge ugly switch case statement with "magic numbers" for the ascii text characters.

Why not use a lookup table like this;
Rich (BB code):
char ascii_table[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};


  // this now replaces your massive 16 element switch/case statement;
  x = ascii_data[z];

:)
 

MrChips

Joined Oct 2, 2009
30,824
There are two simple ways to convert from 4-bit binary to ASCII.

1) The first method consists of examining the ASCII codes for 0-9 and A-F.

0 = 48
:
9 = 57

A = 65

Hence the mathematical algorithm is

ADD 48 to 4-bit binary
if the result is greater than 57, ADD 7

2) Use a lookup table such as

char hex_char[] = "0123456789ABCDEF";
 
Top