Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Help me write a source code for A/D converter in MPLAB

Status
Not open for further replies.

Cleong

Member level 2
Member level 2
Joined
Feb 17, 2006
Messages
53
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,789
how to write those function in mplab source code?

A=256*B+C

D=A*0.4882125
 

Re: source code help!!

What is your number size(how many bits in each number) and format(integer or fixed / floating decimal)?

TOK ;)
 

Re: source code help!!

Gorgon said:
What is your number size(how many bits in each number) and format(integer or fixed / floating decimal)?

TOK ;)

the format i wan is in interger form.
and the number size is 0-500

coz i wan get the temperature ,
the temp value is 10mV/1'k
 

Re: source code help!!

What are the ranges for the different variables A-D? I suppose all is not 0-500?

What is the resolution of your A/D converter? (I would suppose that B is this value)

TOK ;)
 

Re: source code help!!

Gorgon said:
What are the ranges for the different variables A-D? I suppose all is not 0-500?

What is the resolution of your A/D converter? (I would suppose that B is this value)

TOK ;)


ADCvalue = 256*ADRESH + ADRESL;

for 10 bit ADC the maximum value of ADCvalue is 1023, if the Vref is 5 Volt (equivalent with 500°K) then each every 1 ADCvalue = 0.48828125°K (500 / 1024)
Code:
Kelvin = ADCvalue * 0.48828125;
Min = Kelvin - (273+21);
Hex = Min /16;
 

Re: source code help!!

Cleong,
Don't use assembler, use C and all of trouble will gone!
 

Re: source code help!!

Hi
A=256*B+C

For this u hav to write a sub routine for multiplication. This can be done using successive addition. If ur value 256 is fixed then u need not want to multiply it. Simply put two zeros in right side.

For example: if B=0x23, then 256*B will be 0x2300, that is two zeroes in right side. Then add C with ur answer. if C=0x45, U will get A=0x2345.

D=A*0.4882125

Remove Decimal point and take the hex value, Multiply it and convert back to decimal and then put the decimal.

Example: In ur equation 0.4882125 , after removing the point u get 4882125, take hex manually, 4882125=0x4A7ECD
change ur equation as
D=A*0x4A7ECD
Then multiply u get 0xA436A3441
Convert it into decimal, u get 44080706625
Then put the decimal point 7 places from right , then u get 44080.706625

it is ur answer

ofcourse assembly language programming is very difficult

thanks.
 

    Cleong

    Points: 2
    Helpful Answer Positive Rating
source code help!!

Wow, you are in luck.

See, 500/1024 can be reduced to 125/256.

125 = b'01111101' = b'10000000' - b'00000100' + b'00000001' = 128 - 4 + 1

I would write as follows:

Code:
rrf ADRESH, w          ;First multiply by 128 = 256 >> 1
movwf ADCVALH
rrf ADRESL, w
movwf ADCVALM
movf ADRESH, w      ;Now add it once
addwf ADCVALM, f
btfsc STATUS, C       ;carry thru from byte to byte
    incf ADCVALH, f
movf ADRESL, w
movwf ADCVALL
rlf ADRESL, f            ;Now multiply by four
rlf ADRESH, f
rlf ADRESL, w
rlf ADRESH, f
subwf ADCVALL, f    ;Subtract 24 bit number
movf ADRESH, w
btfss STATUS, C      ;carry thru from byte to byte
    addlw 0x01         ;instead of subtracting 1, add one to what we subtract
subwf ADCVALM, f
btfss STATUS, C      ;carry thru from byte to byte
    decf ADCVALH, f      ;Now Kelvin is ADCVALH:ADCVALM

This is a first attempt, and I haven't tested the code but it should get you started in the right direction

-jonathan
 

    Cleong

    Points: 2
    Helpful Answer Positive Rating
Re: source code help!!

Cleong,
Other methode to convert ADC data to temperature is use tabulation, ADCvalue xxx = yyy °K
 

Re: source code help!!

movlw B'100000000' ;256=100000000
andwf ADRESL,ADCvalue

i use andlw(am i right?) for ADCvalue=256*adresh+adresl
after that i need take the ADCvalue to multiply with 0.48828125
since the ADCvalue is in Binary form,
can it directly multiply with decimal number?

Added after 59 seconds:

jonw0224 said:
Wow, you are in luck.

See, 500/1024 can be reduced to 125/256.

125 = b'01111101' = b'10000000' - b'00000100' + b'00000001' = 128 - 4 + 1

I would write as follows:

Code:
rrf ADRESH, w          ;First multiply by 128 = 256 >> 1
movwf ADCVALH
rrf ADRESL, w
movwf ADCVALM
movf ADRESH, w      ;Now add it once
addwf ADCVALM, f
btfsc STATUS, C       ;carry thru from byte to byte
    incf ADCVALH, f
movf ADRESL, w
movwf ADCVALL
rlf ADRESL, f            ;Now multiply by four
rlf ADRESH, f
rlf ADRESL, w
rlf ADRESH, f
subwf ADCVALL, f    ;Subtract 24 bit number
movf ADRESH, w
btfss STATUS, C      ;carry thru from byte to byte
    addlw 0x01         ;instead of subtracting 1, add one to what we subtract
subwf ADCVALM, f
btfss STATUS, C      ;carry thru from byte to byte
    decf ADCVALH, f      ;Now Kelvin is ADCVALH:ADCVALM

This is a first attempt, and I haven't tested the code but it should get you started in the right direction

-jonathan



RRF f,d

The contents of register ’f’ are
rotated one bit to the right through
the Carry Flag.

""If ’d’ is 0,""

the result is placed in the W register.

""If ’d’ is 1,""

the result is placed back in
register ’f’.


rlf ADRESL, w
rlf ADRESH, f

how can i know the w and f is 1 or 0?


rrf ADRESH,w ;first multiply by 128

when rota right , for example 10-->01, mean the value already divide by 2, so how to say is multiply 128?

Can u give more detail for each instruction?
sry that im new in this...

what have u write is jz for A=256*B+c only right?
then how about the D=A*0.48828125?
 

Re: source code help!!

The easiest way to multiply with 0.48828125 is to break it down to 125/256. Take your 16 bit ADC value multiply with 125 and remove the lowest byte (=/256).

Ex:
Your value is 200 (00C8h) * 125 = 25000 (61A8) I would then have added 80h to this, just to reduce the dividing error getting 61A8+80=6228 (/256 cut away low byte) Answer is then 0062h or 98 decimal.

If you do this with real numbers 200 * 0.48828125 = 97.65625. Not bad!

TOK ;)
 

Re: source code help!!

dont tell him make him work
or he will learn nothing !!!

this is my advice:D:arrow::idea:
 

Re: source code help!!

dont tell him make him work
or he will learn nothing !!!

Maybe he will learn by seeing code? How will he learn if no one helps? I didn't just read about assembly, someone taught and later I read more then I got better. With the foundation provided with assistance I can build on it.

Some more explanation:

First, remember that a register is only a byte (8 bits wide). The command

movlw D'256'

is the same as

movlw D'0'

because the leading 1 is the ninth bit. To use numbers greater than one byte, you imagine stringing bytes together. So, it is not necessary to calculate

C = 256*A + B

because you already have it as a 10 bit number spread across two bytes.

In my code, I am representing ADRESH:ADRESL as a ten bit number (actually two 8 bit registers).

Then, I am representing ADCVAL as ADCVALH:ADCVALM:ADCVALL (a 24 bit number). However, I only want to keep ADCVALH:ADCVALM as the integer answer. If I wanted to represent to the right of the decimal point I would include ADCVALL, but really since I'm only starting with a 10 bit number I can't gain the full 24 bits of precision (ADCVALL won't really tell you much).

Updated code with a bug fix and additional comments. This code just multiplies by 125. You can pick the upper two bytes to get Kelvin = 125/256*(ADRESH:ADRESL)

Code:
bcf STATUS, C           ;Clear C
rrf ADRESH, w           ;First multiply by 128 = 256 >> 1.  WREG = ADRESH/2, C = LSB of ADRESH
movwf ADCVALH           ;Now, we move that into ADCVALH, effectively multipling by 256
rrf ADRESL, w           ;WREG = (LSB of ADRESH) * 128 + ADRESL / 2, basically this 
                        ;completes the divide by 2 of the 10 bit number
movwf ADCVALM           ;move to ADCVALM, effectively multiplying by 256
movf ADRESH, w          ;Now add it once, WREG = ADRESH 
addwf ADCVALM, f        ;Add ADRESH to ADCVALM
btfsc STATUS, C         ;carry thru from byte to byte, if the addition results in a carry 
    incf ADCVALH, f     ;then increment ADCVALH
movf ADRESL, w          ;This is a trick.  I don't have to add ADRESL to ADCVALL because ADCVALL
                        ;is assumed to be 0 initially.
movwf ADCVALL           ;Therefore, I just move it thru WREG straight away
rlf ADRESL, f           ;Now multiply by four.  The order of the commands matters because now
                        ;C = MSB of ADRESL
rlf ADRESH, f           ;and now LSB of ADRESH = C = MSB of ADRESL
rlf ADRESL, w           ;Do it again, but I want WREG to keep ADRESL so I can subtract it next
rlf ADRESH, f 
subwf ADCVALL, f        ;Subtract 24 bit number, start with ADCVALL = ADCVAL - ADRESL 
movf ADRESH, w          ;Prepare for the next subtraction 
btfss STATUS, C         ;carry thru from byte to byte, check if I need to borrow 
    addlw 0x01          ;instead of subtracting 1, add one to what we subtract, instead of 
                        ;borrowing, just add 1 to what I'm about to subtract.
                        ;This takes fewer instructions (it's a short cut) which is possible 
                        ;because the high nibble of ADRESH is 0.
                        ;Therefore, I don't have to take care of another overflow
                        ;that I would have to take care of if I borrowed 
subwf ADCVALM, f        ;Now subtract the mid significant bytes
btfss STATUS, C         ;carry thru from byte to byte, take care of the carry bit again
    decf ADCVALH, f     ;Now Kelvin is ADCVALH:ADCVALM, and I'm done

I'll let you figure out how to round ADCVALH:ADCVALM as Gorgon suggests. Now, I have spent an hour spelling out an answer to your problem. I'd advise you spend atleast four hours trying to figure out your next problem on your own before you post.

-jonathan
 

    Cleong

    Points: 2
    Helpful Answer Positive Rating
Re: source code help!!

jonw0224

thank for ur help,
sure i will spend time(untill i realy understand) on what u write for me.

[quote
Maybe he will learn by seeing code? How will he learn if no one helps? I didn't just read about assembly, someone taught and later I read more then I got better. With the foundation provided with assistance I can build on it.

[/quote]



and u are rite,
i need someone guide me in the 1st step.
tq alot.....
:D
 

Re: source code help!!

Hi,
Why you write code by C complier. Now not more people can understand assemble language.
 

source code help!!

Cleong,

I told you the code was untested. Thanks to another poster who pointed out my code wouldn't work for odd numbers, I have corrected my code.

Code:
bcf STATUS, C           ;Clear C 
rrf ADRESH, w           ;First multiply by 128 = 256 >> 1.  WREG = ADRESH/2, C = LSB of ADRESH 
movwf ADCVALH           ;Now, we move that into ADCVALH, effectively multipling by 256 
rrf ADRESL, w           ;WREG = (LSB of ADRESH) * 128 + ADRESL / 2, basically this 
                        ;completes the divide by 2 of the 10 bit number 
movwf ADCVALM           ;move to ADCVALM, effectively multiplying by 256
clrf ADCVALL			;Take care of the carry
rrf ADCVALL, f 
movf ADRESH, w          ;Now add it once, WREG = ADRESH 
addwf ADCVALM, f        ;Add ADRESH to ADCVALM 
btfsc STATUS, C         ;carry thru from byte to byte, if the addition results in a carry 
    incf ADCVALH, f     ;then increment ADCVALH 
movf ADRESL, w          
addwf ADCVALL           
rlf ADRESL, f           ;Now multiply by four.  The order of the commands matters because now 
                        ;C = MSB of ADRESL 
rlf ADRESH, f           ;and now LSB of ADRESH = C = MSB of ADRESL 
rlf ADRESL, w           ;Do it again, but I want WREG to keep ADRESL so I can subtract it next 
rlf ADRESH, f 
subwf ADCVALL, f        ;Subtract 24 bit number, start with ADCVALL = ADCVAL - ADRESL 
movf ADRESH, w          ;Prepare for the next subtraction 
btfss STATUS, C         ;carry thru from byte to byte, check if I need to borrow 
    addlw 0x01          ;instead of subtracting 1, add one to what we subtract, instead of 
                        ;borrowing, just add 1 to what I'm about to subtract. 
                        ;This takes fewer instructions (it's a short cut) which is possible 
                        ;because the high nibble of ADRESH is 0. 
                        ;Therefore, I don't have to take care of another overflow 
                        ;that I would have to take care of if I borrowed 
subwf ADCVALM, f        ;Now subtract the mid significant bytes 
btfss STATUS, C         ;carry thru from byte to byte, take care of the carry bit again 
    decf ADCVALH, f     ;Now Kelvin is ADCVALH:ADCVALM, and I'm done

Thanks for your help, yager. If this isn't an appropriate fix, please let me know. No one is perfect.

Btw, when did the appropriate answer for "help me write this in assembly" become write it in C?

-jonathan
 

    Cleong

    Points: 2
    Helpful Answer Positive Rating
Re: source code help!!

jonw0224 said:
Cleong,

I told you the code was untested. Thanks to another poster who pointed out my code wouldn't work for odd numbers, I have corrected my code.



Thanks for your help, yager. If this isn't an appropriate fix, please let me know. No one is perfect.

Btw, when did the appropriate answer for "help me write this in assembly" become write it in C?

-jonathan


jz a simple equation
Kelvin = 125/256*(ADRESH:ADRESL)
then need write so many code @@
mayb i should listen to others learn the C to write the program.
:cry:

but anyway,
i stil wan to know how to make the ADRESH:ADRESL in one?
 

Re: source code help!!

i stil wan to know how to make the ADRESH:ADRESL in one?
You never can do that!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top