Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

how to get more memory location for ADC?

Status
Not open for further replies.

meera83

New Member
i m using PIC16F877.
i had been ask to use potentiometer as analog input(0-5V) for PIC and display a range value(00.00-10.00) on LCD..

may i know that is it for one analog signal input to PIC, there are only 256 location to store the convert result?
since every port consist of 8 bits(mean 2^8)..
10/256=0.04 mean that every location store differential value for 0.04?

if i want to hv differential value less than 0.04, mean that i need to have memory location more than 256 place,then what should i do?
for example, if i hv 500memory location, then one location will be 10/500=0.02 which is more precise..

may i know what method can i use in order to get more memory location for store more data?

is it by using external memory EEPROM??

thanks..
 
meera83 said:
i m using PIC16F877.
i had been ask to use potentiometer as analog input(0-5V) for PIC and display a range value(00.00-10.00) on LCD..

may i know that is it for one analog signal input to PIC, there are only 256 location to store the convert result?
since every port consist of 8 bits(mean 2^8)..
10/256=0.04 mean that every location store differential value for 0.04?
The 16F877 ADC's are 10bit, ie 1023

if i want to hv differential value less than 0.04, mean that i need to have memory location more than 256 place,then what should i do?
for example, if i hv 500memory location, then one location will be 10/500=0.02 which is more precise..

may i know what method can i use in order to get more memory location for store more data?

is it by using external memory EEPROM??
You can add external EERAM memory, eg: serial SPI if required.
thanks..

Are you confusing ADC resolution with available memory registers?

Hope this helps

Eric
 
Last edited:
not the clearest question I've seen in a while. I think he is asking about how he can use a table to convert ADC readings to a representation value.

meera, you are trying to use a table approach to convert ADC values into the actual output value. This is not going to work on microcontrollers - memory is scarce. Instead, figure out the algorithm by which you convert the adc value to what you want to display. This will take less memory.

to answer your direct question - you can add memory but it is extremely complex and much harder than my suggestion above.
 
As he is using a 16F877 then he has 8K of program space, he could easily use half of that to store data logger type data. He could have a 1K table if he just wanted a lookup table. Going by the confused question, he definitely doesn't want to try and interface external EEPROM.

Mike.
 
I'm sure he's talking about the ADC resolution.

He says that the port (ADC pin) has 256 different possible values (8 bit) and that the output is ment to be 0.00 to 10.00, therefore 10 / 256 = 0.04 which is the minimum resolution with an 8 bit ADC.

To get the required accuracy to 2 decimal places (Well I assume that's why he sais "10.00" instead of just "10"), there are 10 / 0.01 = 1000 possible values, which would require atleast a 10 bit resolution (1024 possible values).

Some PICs have ADCs with a 10 bit mode, I'm unsure on which PICs do though.

Hope that atleast clears up the question.
 
sorry for confusing all of u..

yap, what i mean is the ADC resolution(i still not familiar with the term use to describe thing inside PIC)..

is it the resolution only hv maximum 256?
can i get more higher resolution?

A2D
btfss INTCON,T0IF
goto A2D

bcf INTCON,T0IF
bsf ADCON0,GO ;Start A/D conversion
btfsc ADCON0,GO
goto $-1
Wait
btfss PIR1,ADIF ;Wait for conversion to complete
goto Wait

call LCD_Line1

movf ADRESH,w
movwf AARGB0 ;move adresh into AARGB1

movlw 0x5FB ;multiple with
movwf BARGB0
bcf PCLATH,4 ;page 1
bsf PCLATH,3
call UMUL0808L

movlw 0x40 ;divide result
movwf BARGB0
call UDIV1608L
clrf PCLATH

movf AARGB0,w
movwf NumH

movf AARGB1,w ;addlw b'00000010' ;~start with number of 4
movwf NumL
call bin16_bcd ;get volts ready for LCD

movf Thou,w ;get hunds
call bin_bcd
movf LSD,w ;send high digit from the LSD #.xx
call LCD_Char

movf Hund,w ;get hunds
call bin_bcd
movf LSD,w ;send high digit from the LSD #.xx
call LCD_Char

movlw A'.' ;send decimal point "."
call LCD_Char

movf Tens,w ;get tens
call bin_bcd
movf LSD,w ;send low digit x.#x
call LCD_Char

movf Ones,w ;get ones
call bin_bcd
movf LSD,w ;send low digit x.x#
call LCD_Char
 
above is the program i use..
the result show on LCD 0.00-10.00
mean that in hex the calculation is
max value(hex) = 100xFB/40=3EC(1000 in decimal)

100hex=256decimal..

the resolution only 256..

how should i do if i want to use 10 bit resolution or higher than that resolution?

thanks
 
A2D
btfss INTCON,T0IF
goto A2D

bcf INTCON,T0IF
bsf ADCON0,GO ;Start A/D conversion
btfsc ADCON0,GO
goto $-1
Wait
btfss PIR1,ADIF ;Wait for conversion to complete
goto Wait

call LCD_Line1

movf ADRESH,w
movwf AARGB0 ;move adresh into AARGB1

movlw 0x5FB ;multiple with
movwf BARGB0
bcf PCLATH,4 ;page 1
bsf PCLATH,3
call UMUL0808L

movlw 0x40 ;divide result
movwf BARGB0
call UDIV1608L
clrf PCLATH

the program code is from internet,
the ADC is store in ADRESH and ADRESL,
but in the code, they only use ADRESH to do the math calculation,
ADRESH form by 8 bit =256 resolution..

so how should i do if i want the calculation involve 10bit,
mean ADRESH and ADRESL together involve in math calculation..

thanks..
 
I just noticed that ericgibbs has already said the PIC16F877 has a 10bit ADC, therefore it will be able to give a resolution of 1024 values, which is more than the number that you need.

Your best bet is to look at the datasheet for the PIC16F877. It should state which register you need to set (If any) to enable 10bit mode. The value that the ADC will return will be split across two registers. Each register is only 8bits wide therefore the two most significant bits (Highest value, on the right of the number) will be in one register and the other 8 bits will be in another.

I've not worked with ASM much so I can't really help you with it.

From a design point of view, the value that you want to display on your is:
OutputNumber = ADCValue / 102.4f
Where ADCValue is the 10bit value straight from the ADC.

That will give you a floating point OutputNumber, which is in the right format to display on your LCD as 0.00 -> 10.00. There is floating point calculation which will slow it down, however.

Hope that helps.
 
You are doing it the hard way. Allocate 4 bytes for the 1000s, 100s, 10s & 1s digits for your display (Call them dec1000, dec100, dec10 & dec1 and zero them). Allocate 2 more bytes for a 16bit number. Put your ADRESH & ADRESL results into these two bytes (Call them HighByte and LowByte).
1) Use a 16bit subtraction routine on HighByte and LowByte to first subtract 1000 (0x3E8). If the result underflows discard answer and goto step 2. If not, increment the dec1000 byte and put result (From 16bit subtraction) in HighByte and LowByte and repeat step 1.
2) Use a 16bit subtraction routine on HighByte and LowByte to subtract 100 (0x64) If the result underflows discard answer and goto step 3. If not, increment the dec100 byte and put result in HighByte and LowByte and repeat step 2.
3) Use a 16bit subtraction routine on HighByte and LowByte to subtract 10 (0x0A) If the result underflows discard answer and goto step 4. If not, increment the dec10 byte and put result in HighByte and LowByte and repeat step 3.
4) Put the remainder (Now less than 10) from LowByte into the dec1 byte.
Now you will have a BCD representation of the ADC value in dec1000, dec100, dec10 & dec1 which are easily converted to proper display codes for your LCD via a lookup table. No multiplication or fancy divide routines eating up processor cycles.
 
Last edited:
You gotta admit the integer 16/8=8 divider and 8*8=16 multiplier are fun subroutines to write :) (that is, if you don't just grab them from a library...)

But indeed, I think the subtract method may be faster and clearly easier to understand, I ended up having to do other arbitrary multiply and divide for my project so I had to write them anyway. I guess the main reason for the divide is to (virtually) calculate 1/x along with multiply y*z... where x, y, z are collected data... yikes!

(turns out, they aren't way too slow, they appear to be O(n) (n=number of digits in the number) but there are a lot (but fixed number) of instructions per iteration. It probably won't beat the 10^x subtract method. However it saved memory space for me to reuse for the LED displays, so... it gets reused!)

... just avoid floating point on microcontrollers... they are evil (and I did avoid even though I had to calculate 1/x!)
 
hi meera,

>> the program code is from internet,
the ADC is store in ADRESH and ADRESL,
but in the code, they only use ADRESH to do the math calculation,
ADRESH form by 8 bit =256 resolution..

so how should i do if i want the calculation involve 10bit,
mean ADRESH and ADRESL together involve in math calculation..



If you set the ADC result to 'left justify' this will give 255 in the ADRESH.

As you require 10bit resolution, set for 'right justify'.

Read ADRESH and ADRESL to get the 10 bit result.

Eric
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top