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.

Help! Adc On A Pic12f675

Status
Not open for further replies.

UrabnBadger

New Member
Hi, I'm pretty new to this lark.
I'm tryin to do a simple adc on a 12F675 and then built on the program from there.

The Circuit:

5V (5.5V MAX) regulator connected to Vdd & Vss
5V LED connected over Vdd & Vss
0.1 microfarad decoupling cap over the Vdd & Vss pins

GP0/AN0 connected to a 500K Potentiometer (Also connected to Vss and Vdd)
GP1 connected to 5V LED (red)
GP2 connected to 5V LED (green)

10bit adc so 0V = 0 & 5.5V = 1023

Very simple!

I am writing in assembly using MPLAB IDE,
I went through my program and narrowed the problem down to the adc results. I setup a little test to blink out the results held in each bit of the ADRESL and ADRESH files

When ADCON0,ADFM is set (results right justified) my test revealed
bits 2-7 of ADRESH are always clear (as expected) so you would expect that bits 0 & 1 of ADRESH and bits 0-7 of ADRESL would contain the results

Instead I got the following:
V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT
0.0V 00000000 00000000 0 0
0.5V 00000000 00000000 0 93
1.0V 00000000 00000000 0 186
1.5V 00000001 00000001 257 279
2.0V 00000001 00000001 257 372
2.5V 00000001 00000001 257 465
3.0V 00000010 00000010 514 558
3.5V 00000010 00000010 514 651
4.0V 00000010 00000010 514 744
4.5V 00000011 00000011 771 837
5.0V 00000011 00000011 771 930
5.5V 00000011 00000011 771 1023

It seem odd that ARESH is the same as ADRESL, also the relusts aren't waht I expected, can anyone make any sense of these results?

So next I changed to ADCON0,ADFM clear (results left justified) my test revealed bits 0-5 of ADRESL aren't always clear as you would expect
(Note that on the data sheet P42 it says for ADFM=0 bits 0-5 of ADRESL read as 0)

My results are below:
V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT
0.0V 00000100 00000100 1028 0
0.5V 00011100 00011100 7196 93
1.0V 00110000 00110000 12336 186
1.5V 01001000 01001000 18504 279
2.0V 01011100 01011100 23644 372
2.5V 01111100 01111100 31868 465
3.0V 10001100 10001100 35980 558
3.5V 10100110 10100110 42662 651
4.0V 10111001 10111001 47545 744
4.5V 11001100 11001100 52428 837
5.0V 11100100 11100100 58596 930
5.5V 11110001 11110001 61937 1023

Again ARESH is the same as ADRESL, is this correct? shouldn't bits 0-5 of ADRESL always be 0?

If only bits 0-7 of ADRESH and bits 6 & 7 of ADRESL are used the following decimal equivalents are obtained:

V@AN0 ARESH ADRESL DEC RESULT EXPECTED DEC RESULT
0.0V 00000100 00 16 0
0.5V 00011100 00 112 93
1.0V 00110000 00 192 186
1.5V 01001000 01 289 279
2.0V 01011100 01 369 372
2.5V 01111100 01 497 465
3.0V 10001100 10 562 558
3.5V 10100110 10 666 651
4.0V 10111001 10 742 744
4.5V 11001100 11 819 837
5.0V 11100100 11 915 930
5.5V 11110001 11 967 1023

This would apper to be correct! but to summarise:

What is happening with the results for ADFM = 1 incorrect
Why are the results of ADRESH and ADRESL the same for ADFM = 1 of 0
Why aren't the bits 0-5 of ADRESL 0 when ADFM = 0

Hope someone can shed some light as I'm tearing my hair out!

Cheers
 
I wonder if you're experiencing banking problems? Are you switching banks correctly between ADRESL and ADRESH? It's a "gotcha" that seems to catch everyone at one time or another...
 
Thanks for the fast replies! I should have posted ages ago in stead on banging my head on the wall :(

Ok Thanks for pointing that out mike, I hadn't even thought of changing banks..... (as I said beginner to this)

I pressume dropping the pot value is to increase the input current? does this then have an effect on the accuracy?

I will give it bash and let you guys know what happens.

The girlfriend is on her way over so my 'fun' time is limited haha
 
UrabnBadger said:
Thanks for the fast replies! I should have posted ages ago in stead on banging my head on the wall :(

Ok Thanks for pointing that out mike, I hadn't even thought of changing banks..... (as I said beginner to this)

I pressume dropping the pot value is to increase the input current? does this then have an effect on the accuracy?

The PIC has an internal sample and hold, and it takes current to charge and discharge the capacitor - the maximum advised source impedance is about 2.5K - you're using 250K or so!.

The girlfriend is on her way over so my 'fun' time is limited haha

I would hope you have more fun when she's there? - we might be geeks, but we're not that big a geeks :p
 
Ok, a tad harsh, she is fun :D

I've just started lookin at my program again.....paying attention to bank locations ;) and I changed to a 1K pot.

Maybe a stupid question at the end but here goes.....

Below is an extract from the start of my program:

; EQUATES SECTION

TMR0 EQU 01H ; TMR0 is file 1.
TRISIO EQU 85H ; TRISIO, the PORTA I/O selection is file 85H
GPIO EQU 05H ; GENERAL I/O PORT is file 5.
STATUS EQU 03H ; STATUS is file 3.
ZEROBIT EQU 2 ; ZEROBIT is bit 2 of STATUS
CARRY EQU 0 ; CARRY is bit 0 of STATUS
ANSEL EQU 9FH ; ANALOGUE SELECT REGISTER is file 9EH
ADCON0 EQU 1FH ; A/D CONTROL RESISTER is file 1FH
GO EQU 1 ; GO/DONE is bit 1 of ADCON0
ADRESH EQU 1EH ; The A/D RESULT upper
ADRESL EQU 9EH ; The A/D RESULT lower
OPTION_R EQU 81H ; OPTION register is file 81H
CMCON EQU 19H ; COMPARATOR CONTROL REGISTER is file 19H
OSCAL EQU 90H ; OSCILLATOR CALIBRATION REGISTER is file 90H
COUNT EQU 20H ; User RAM location.

Here the STAUS REGISTER is only refered to the bank0 location of 03H and not the BANK1 location of 83H (Can you see where I'm going here :confused: )

Below is an extract from the setup part of my program:

;CONFIGURATION SECTION

START BSF STATUS,5 ;Turns to Bank1

MOVLW B'00111001' ;GP 1 & 2 set as OP all others IP
MOVWF TRISIO

MOVLW B'00010001'
CLRF ANSEL ;A/D Clock FOSC/8, (GP0) Set as analogue

MOVLW B'00000111' ;Prescaler is /256
MOVWF OPTION_R ;TIMER pulses every 1/3906.25 secs

CALL 3FFH
MOVWF OSCAL ;Calibrates 4MHz oscillator

BCF STATUS,5 ;Turn to Bank0

MOVLW B'00000111'
MOVWF CMCON ;Turns off comparator

MOVLW B'00000001'
MOVWF ADCON0 ;left justified, Ref Vdd, AN0, ADC on

CLRF GPIO ;Clears GP

Here when I select BANK1 I use 'BSF STATUS,5' (which I linked to file 03H) which is fine as the data sheet says bit 5 is clear on POR/BOD, therefore initially I am in BANK0.

Now going by what was said about ensuring files I call up are in the bank I'm working in........ Surely to change back to BANK0 when in BANK1 I would need to clear bit 5 of the STATUS REGISTER......but 03H is no longer the STATUS REGISTER, it is now 83H.....

Does the extract from my program work? It's the same method I have used before when messing about with simple digital Input/output programs and they have all worked fine.

Does it not matter what address I use to call up the STATUS REGISTER regardless of which bank I am in. If so am I correct in saying this doesn't apply to any of the other addresses, ie ADRESH & ADRESL?


Cheers!
 
Get rid of the equates section and use
Code:
#include <p12F675.inc>
instead.

Some registers like STATUS are in all banks.

Also try STATUS, RP0 (it makes it easier to read)

Can you zip and attach the entire program?
 
Last edited:
Thanks, I'll just tidy it up and stick it on.....there isn't much to it though....

I understand from P8 of the datasheet that STATUS is in both banks but my point was it has a different address depending on which bank I am in.
So the way I understand it.....

if i'm in BANK0 is use address 03H
if I'm in BANK1 I use address 83H

Calling up 03H in BANK1...... 03H isn't STATUS in BANK1....
am I barking up the wrong tree here?


you say to use 'STATUS,RP0' is this because 'STATUS,5' is ambigous to 'people' reading the program?

Also you say get rid of the equates section, I had this so I could use the name tags assigned to files ie 'BSF STATUS,RP0' instead of 'BSF 03H,5'
You say to insert:

#include <p12F675.inc>

Do I just put this as a line of code exactly as it is above, what does it do and can I still use commands like 'BSF STATUS,RP0'?

Thanks guys you're legends!
 
UrabnBadger said:
Thanks, I'll just tidy it up and stick it on.....there isn't much to it though....

I understand from P8 of the datasheet that STATUS is in both banks but my point was it has a different address depending on which bank I am in.
So the way I understand it.....

if i'm in BANK0 is use address 03H
if I'm in BANK1 I use address 83H

Calling up 03H in BANK1...... 03H isn't STATUS in BANK1....
am I barking up the wrong tree here?

Don't use either of them! - use 'STATUS' and it does it all for you. Just to let you know, whatever you use (either STATUS, 0x03, or 0x83), the actual value in the resultant code is 0x03 - but there's no need for you to know that! :D

you say to use 'STATUS,RP0' is this because 'STATUS,5' is ambigous to 'people' reading the program?

Also you say get rid of the equates section, I had this so I could use the name tags assigned to files ie 'BSF STATUS,RP0' instead of 'BSF 03H,5'
You say to insert:

#include <p12F675.inc>

Do I just put this as a line of code exactly as it is above, what does it do and can I still use commands like 'BSF STATUS,RP0'?

Yes, that's what it's there for - adding your own is a waste of time and confusing.

If you don't use the equate labels (like Status etc.) many people won't bother reading your posts, it's too much like hard work.

When you post code surround it with the 'code' tags (see the 'go advanced' screen).
 
Working!

Ok it's kind of working now! The .asm is attached... fell a bit embaressed after all this..... anyway have a look....


Ah all is clear on the STATUS thing, so effectively the status is the same file regardless of which bank you're in (if not, never mind! I think I see your point now).

When you post code surround it with the 'code' tags (see the 'go advanced' screen).

?? Sorry don't follow that :confused:



I haven't taken out the equates section but it seems to be doing the adc now although it switches on the LED ate 1.29V whic I think is wrong.

5.65V max
10 bit adc
(5.65/1023)*250 = 1.38V

Maybe it's just down to my cheapy £4.99 Maplin multimeter...... :eek:

Another point.... when I go above 1.29V the LED goes on and off randomly but I assume this is because I have ignored the contents of the two bits in ADRESH..... so ADRESL fluctuates above and below 250 (B'11111010').
 

Attachments

  • 12F675 Int 4MHz ADC.asm
    4.2 KB · Views: 213
Code:
; HEADER84A.ASM  for 12F675.
;The OPTION Register is set to /256 to give timing pulses of 1/3906.25 of a second
;when using the internal 4MHz RC.
	
;*********************************************************

; EQUATES SECTION

#include <p12F675.inc>

COUNT	EQU	20H		; USER RAM 'COUNT'

;*********************************************************

LIST	P=12F675	;we are using the 12F629.
ORG		0			;the start address in memory is 0
GOTO	START		;goto start!

;**********************************************************************
; Configuration Bits

__CONFIG H'3F84'   	;Oscillator - Internal RC
					;WDT - off
					;PUT - on
					;Master Clear Enable - Internal
					;BOD - of
					;Code Protection - off
					;Data EE Read Protect - off

;*********************************************************
;SUBROUTINE SECTION.

; P01 second delay.
DELAY	CLRF	TMR0					;START TMR0.
LOOPA	MOVF	TMR0,W					;READ TMR0 INTO W.
		SUBLW	.39						;TIME - 39
		BTFSS	STATUS,Z		  		;Check TIME-W = 0
		GOTO 	LOOPA					;Time is not = 3906
		RETLW	0						;Time is 39, return.

; P1 second delay.
DELAYP1	MOVLW	.10						;Move 10 into W.
		MOVWF	COUNT					;Set COUNT=10
TIMEB	CALL	DELAY					;Wait 0.01 seconds.
		DECFSZ	COUNT					;COUNT-1, skip if 0
		GOTO	TIMEB					;Count is not = 10
		RETLW	0						;Count is = 10, return.

; P5 second delay.
DELAYP5	MOVLW	.50						;Move 50 into W.
		MOVWF	COUNT					;Set COUNT=50
TIMEC	CALL	DELAY					;Wait 0.01 seconds.
		DECFSZ	COUNT					;COUNT-1, skip if 0
		GOTO	TIMEC					;Count is not = 50
		RETLW	0						;Count is = 50, return.

; 1 second delay.
DELAY1	MOVLW	.100					;Move 100 into W.
		MOVWF	COUNT					;Set COUNT=100
TIMED	CALL	DELAY					;Wait 0.01 seconds.
		DECFSZ	COUNT					;COUNT-1, skip if 0
		GOTO	TIMED					;Count is not = 100
		RETLW	0						;Count is = 100, return.

;RED LED on
RLEDON	BCF		STATUS,RP0				;Turn to Bank0
		BSF 	GPIO,1					;Turn on red LED
		GOTO	RUN						;Restart ADC

;RED LED off
RLEDOFF	BCF		STATUS,RP0				;Turn to Bank0
		BCF 	GPIO,1					;Turn off red LED
		GOTO	RUN						;Restart ADC

;*********************************************************


START	BSF		STATUS,RP0	;Turns to Bank1

		MOVLW	B'00111001'	;GP 1 & 2 set as OP all others IP
		MOVWF	TRISIO

		MOVLW	B'00010001'
		CLRF	ANSEL		;A/D Clock FOSC/8, AN0(GP0) Set as analogue

		MOVLW	B'00000111'	;Prescaler is /256
		MOVWF	OPTION_REG	;TIMER pulses every 1/3906.25 secs

		CALL	3FFH
		MOVWF	OSCCAL		;Calibrates 4MHz oscillator
	
		BCF		STATUS,RP0	;Turn to Bank0
	
		MOVLW	B'00000111'
		MOVWF	CMCON		;Turns off comparator

		MOVLW	B'10000001'
		MOVWF	ADCON0		;Result right justified, Ref Vdd, Select AN0, ADC on

		CLRF	GPIO		;Clears GP

;*********************************************************
;Program starts now.

BEGIN							
		BSF		GPIO,1			;Test flash sequence
		BSF		GPIO,2
		CALL	DELAYP1
		BCF		GPIO,1
		BCF		GPIO,2
		CALL	DELAYP1
		BSF		GPIO,1
		BSF		GPIO,2
		CALL	DELAYP1
		BCF		GPIO,1
		BCF		GPIO,2
		CALL	DELAY1

RUN
		BSF		ADCON0,GO		;Start A/D conversion

WAIT	BTFSC	ADCON0,GO	
		GOTO	WAIT			;Wait until A/D conversion is complete

		BSF		STATUS,RP0		;Switch to Bank1
		MOVF	ADRESL,W		;Move A/D conversion result to working directory
		SUBLW	.250			;(L-W) Subtract result from .250 (i.e. 1.41V, 1023=5.76V)  

		BTFSC	STATUS,C		;Check CARRY BIT (SET for +ve, CLEAR for -ve i.e. clear for result>literal  )
		CALL	RLEDOFF			;Turn LED on subroutine
		CALL	RLEDON			;Turn LED off subroutine

END								;This must always come at the end of your code
 
Multimeter battery

Hi again!..... changed my multimeter battery and the meter now give the following values

5V regulator output = 5.01V

so expected input voltage to turn on LED

10 bit adc
(5.01/1023)*250 = 1.22V

I measured the voltage to turn on the LED and its 1.13V

A bit more reasonable now :)
 
Status
Not open for further replies.

Latest threads

Back
Top