[SOLVED] 8051 and ADC0804 interface code related Convert ADC Value to display voltage

Status
Not open for further replies.

papunblg

Advanced Member level 3
Joined
Oct 22, 2010
Messages
716
Helped
172
Reputation
344
Reaction score
165
Trophy points
1,343
Location
Kolkata India
Activity points
6,421
Hi All!

I am trying to make a 0-15 volt regulated power supply with LCD display. I am using AT89S52, ADC0804 and JHD162A LCD Display. I am using Assemby code to program the microcontroller. Every thing is working fine. The ADC is sending the digital data output in binary value which I am converting to Decimal and then to ASCII digits to display on the LCD(for example, 3.3V is showing 165) . The displayed value is almost accurate. But the Problem is, with assembly code I cann't display the actual volt(say, 3.3V).
Actually, how to convert the folowing calculation to assembly code:-

X = (Dicimal Value given by ADC * Step Size (say, 19.53mV))/1000
Now, To display value of X upto two palaces after decimal point.

Please Help!!!!!!!!!!!!
 

Please put your schematic and firmware here to help you well

Thanks

MedTronic
 

    V

    Points: 2
    Helpful Answer Positive Rating
Ok sir, I will upload codes, schematic etc tonight after returning home.
 

    V

    Points: 2
    Helpful Answer Positive Rating
    V

    Points: 2
    Helpful Answer Positive Rating



part of the code:-

Code:
RAM_ADDR  	EQU 30H
COUNT     	EQU 3
hundreds 	equ 30h
tens      	             equ 31h
ones      	             equ 32h



ADC:
      [INDENT] mov A,P0 ;Reading from ADC
       nop
       nop
       ret[/INDENT]

Bin2Dec:                              ;Convert to Decimal
      [INDENT] mov b,#100d
       div ab
       mov hundreds,a              ;Store at 30h
       mov a,b
       mov b,#10d
       div ab
       mov tens,a                       ;Store at 31h
       mov ones,b                       ;Store at 32h
       ret       [/INDENT]       

DEC_ASCI_CONVRT: 
	[INDENT]MOV R0,#RAM_ADDR 	;pointing to 30h
	MOV R2,#3   	             ; for 3 location[/INDENT]

BACKk: 	
               [INDENT] MOV A,@R0   	
	ORL A,#30H  	
	ACALL	DATA_DISPLAY      ; displayed to LCD
	INC R0      	
	DJNZ R2,BACKk  	
	RET
 
Last edited:
At last I have solved my problem myself. Thanks to all the posts of edaboard related to float variables and LCD. Thanks....Thanks...Thanks!!!!

This time I have changed my assembly code to C Language. I could have done it using assembly. But C is more easy.

The code is given below:- [Remember that the Vin (pin 6) of ADC0804 is using a resistance voltage divider to cut down 15VDc to 5volt DC, i.e., 3:1 ratio. I am using a 10K preset for fine tuning].Also a 10K preset for Vref pin and adjust to let it pass nearly 2.50V
These are not shown in the circuit posted in the previous post.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<8051.h>
#include<stdio.h>
#include<lcd.c>
void disp_digits(int n);
__sfr __at (0x80) ADC_PORT;
 
unsigned int temp;
int thous,hundreds,tens,ones;
unsigned int getadc;
char strbuff[12];
void main(){
while(1){
getadc=ADC_PORT;
MSDelay(100);
LCD_init();
LCD_command(0x86);
temp=getadc*6;
if(temp>=1000)
{
ones=temp%10;
temp=temp/10;
tens=temp%10;
temp=temp/10;
hundreds=temp%10;
thous=temp/10;
sprintf(strbuff,"%d%d.%d%d Volt",thous,hundreds,tens,ones);
LCD_sendstring(strbuff);
}
else
{
ones=temp%10;
temp=temp/10;
tens=temp%10;
hundreds=temp/10;
sprintf(strbuff,"%d.%d%dV",hundreds,tens,ones);
LCD_sendstring(strbuff);
}
MSDelay(100);
}
}

 
Last edited by a moderator:
hey #1

can you please give your assembly program??????

i hope you will send....

thanks in advance
 

Mr. Doshi,
The code I have written earlier was showing the ADC's output. The ADC is sending the digital data output in binary value which I am converting to Decimal and then to ASCII digits to display on the LCD(for example, 3.3V is showing 165) .
Please refer the C code above and make changes to show the actual value in volt .


Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0h
 
RAM_ADDR        EQU 30H
;ASCI_RSULT     EQU 50H
COUNT           EQU 3
 
hundreds        equ 30h
tens            equ 31h
ones            equ 32h
 
 
                 ACALL  DELAY_200M
                ACALL   ONETIME_LCDINIT
 
 STT:   
        ACALL   ADC
        ACALL   Bin2Dec
        ACALL   DEC_ASCI_CONVRT
        ACALL   DELAY_200M
        ACALL   DELAY_200M
        ACALL   DELAY_200M
        sjmp    STT
 
;=================================================
;this subroutine is used to take data from ADC and
;keep to Accumulator
;=================================================
ADC:   mov A,P0
       nop
       nop
       ret
Bin2Dec:
       mov b,#100d
       div ab
       mov hundreds,a
       mov a,b
       mov b,#10d
       div ab
       mov tens,a
       mov ones,b
       ret       
       
DEC_ASCI_CONVRT: 
        MOV R0,#RAM_ADDR        
        MOV R2,#3       
BACKk:  MOV A,@R0       
        ORL A,#30H      
        ACALL   DATA_DISPLAY
        INC R0          
        DJNZ R2,BACKk   
        RET
 
ONETIME_LCDINIT:
        MOV     A,#38H          
        ACALL   COMMAND         
        MOV     A,#0EH          
        ACALL   COMMAND         
        MOV     A,#01H          
        ACALL   COMMAND         
        MOV     A,#06H          
        ACALL   COMMAND         
        MOV     A,#86H          
        ACALL   COMMAND         
        RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
COMMAND:
        ACALL   READY           
        MOV     P1,A            
        CLR     P2.0            
        CLR     P2.1            
        SETB    P2.2            
        CLR     P2.2            
        RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DATA_DISPLAY:
        ACALL   READY           
        MOV     P1,A            
        SETB    P2.0            
        CLR     P2.1            
        SETB    P2.2            
        ACALL   DELAY           
        CLR     P2.2            
        RET
READY:  SETB    P1.7                    
        CLR     P2.0            
        SETB    P2.1            
BACK:   CLR     P2.2                    
        ACALL   DELAY           
        SETB    P2.2            
        JB      P1.7,BACK       
        RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DELAY_200M:
        MOV     R7,#30H
L1_DELAY:       
        MOV     TMOD,#10
        MOV     TH1,#3CH
        MOV     TL1,#0B0H
        SETB    TR1
AGAIN:  JNB     TF1,AGAIN
        CLR     TR1
        CLR     TF1
        DJNZ    R7,L1_DELAY
        RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DELAY:  MOV     R3,#50
HERE3:  MOV     R4,#255 
HERE2:  DJNZ    R4,HERE2
        DJNZ    R3,HERE3
        RET
        END

 
Last edited by a moderator:
Mr. papunblg

thanks for reply and give me your program...
 

Hello Mr. papunblg
I am doing a temp control project .Thank u 4 your helpful information. I am confused with your READY subroutine.If I use the subroutins below are they the same as your subroutines.


Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
en_pulse:
        setb  en
        acall delay1
        clr en
        acall delay1
        ret
;==================================================================
 
 
comnwrt:
        clr en
        mov P2,a
        
        clr rw
        
        acall delay1
        clr rs
        acall delay1
        
        acall en_pulse
ret 
;==================================================================
datawrt:
        clr en
        mov P2,a
        clr rw
        acall delay1
        setb rs
        acall delay1
        acall en_pulse
        ret
========================================================================
Plz check if I got Lcd interfacing pins in your program correct
2.2     en
2.0     rs
2.1     rw
 P1     data
1.7     is it connected to some input signal??
Plz help
:-?

 
Last edited by a moderator:

Hi Barasha,
Thank you for your question.
There are 2 ways to send commands/data to LCD. --(1) Call a time delay before sending next data/command to an LCD (2) To monitor the busy flag before issuing a command / data to the LCD.

The READY subroutine follows the second method.
Note:- D7 bit of (command reg) LCD is busy flag which is connected to P1.7 of the microcontroller in my case(as D0 to D7 connected to port 1). To check that flag you need to make R/S=1 and RS=0 and a low to high pulse for the E pin. After that P1.7 reflects the state of busy flag.

READY:
SETB P1.7 ;To make P1.7 input port
CLR P2.0 ;RS=0 to access command reg
SETB P2.1 ;R/W = 1 to read command Reg​
BACK:
CLR P2.2 ;E=0 to provide low to high pulse
ACALL DELAY ; give some time(pulse time)
SETB P2.2 ; low to high pulse ends
JB P1.7,BACK ; stay till busy flag=0
RET​

Hope this will throw some light.
Today its already very late. I will check your code tomorrow.
Thanks

Rajsekhar
 
Mr. papunblg
Thanks for your help.
Since my program is not working,I changed the interfacing lines in your program according 2 my hardware with 80c52.When i supplied power it displays 255 repeatedly.The calculated value isn't the same according 2 my input.I am trying to solve the problem.Did you too get repeated outputs?



Barasha
 

Hi Barasha,

Thanks for helpful points.

Its unusual that your circuit displays 255. Please check the voltage at pin 6(Vin+)and pin 9(Vref/2) when there is no input voltage and also check those when connected to a 3V supply. It would be helpful if you give the schematic and the code.
Note:- pin 3 and 5 should be connected

The maximum analog voltage you can give to ADC0804 (Vin pin, in this case pin 6) is 5V. So whatever analog signal you are trying to measure, make sure that the i/p volt to that pin should not exceed beyond 5V. If you want to measure voltage more than 5V, you should use resistor voltage divider network. The values of resistances required depends on the range of input voltage. You said you If you are seeing 255, it means ADC0804 getting 5V or more(if there is no other h/w error).

What type of temperature sensor you are using?

What does Vref/2 (pin 9) do?
Suppose in your experiment, if you are sure that your input analog signal will always between 3-5V, then you can fix the Vref/2(pin 9) pin to exact 1.5V (3volt / 2), and use the entire 8-bit range to measure the voltage between 3-5V. That means you will get reading 0 for i/p 3V, and 256 for i/p 5V or more. This enhances the accuracy of analog measurements.

Use a preset (if Zever diode of required value is not available) to supply pin 9. Adjust the preset so that pin 9 gets required Voltage.

Note:- When not connected, Vref/2 is 2.5 volts for Vcc = 5 Volts.
 
Last edited:
Mr. papunblg
Thanks for your helpful information.
The sensor is Lm35 and its range is 0 -100.After changing the reference i got some output at the ADC pins.
 

Mr. papunblg
Thanks for your helpful information.
The sensor is Lm35 and its range is 0 -100.After changing the reference i got some output at the ADC pins.
 

Attachments

  • schematic.png
    31.7 KB · Views: 250
Hello papunblg, I am doing a simliar project with ADC0804 and LM35, but it's data on LCD is not changing, which it's not giving me any degree back, and i had post a thread, plz can you help me out, and I have copy the code above into Keil, and it give me error on #include<lcd.c>, wondering why?
thank you
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…