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.

ADC reading

Status
Not open for further replies.
Yes it is what I thought, as App notes state that after read and conversion done, GO_DONE bit is cleared. as for delay, 5micro secs should do it? Right?

P.S. thanks for the help, eng1.
 
Ok so I modified my code, so ANSEL at the beginning of portsetup, is only time ANSEL is setup.
 
You need to change the comparison slightly. What it is doing at the moment is checking if the voltage is less than 1.7V and if it is then turn on LED. It then returns, because of the call, and checks if it's less than 3.0V which it will be as 1.7 is less than 3.0 so it turns it off again.

Try changing the code to,
Code:
result
            	movlw	low(0x015B)     ; load W with value of low 0x15
	        subwf	Word,W          ; subtract value in file Word, with value in W
        	movlw	high(0x015B)    ; load W with value of 0x15
          	btfss	STATUS,C        ; check to see if bit "C", in Status is set.
         	movlw	high(0x015B)+1  ; load W with value high 0x15 and add 1
        	subwf	Word+1,W        ; subtract value in file Word, with value in W
            	btfss	STATUS,C        ; carry clear if word is less than 0x15B
	        goto	LEDon ;    <-----changed
         	movlw	low(0x0266)
        	subwf	Word,W
        	movlw	high(0x0266)
         	btfss	STATUS,C
         	movlw	high(0x0266)+1
	        subwf	Word+1,W
            
        	btfsc	STATUS,C        ; carry set if word is greater or equal to 0x266
	        goto	LEDon  ;   <------changed
	 ;       goto start	   <------removed

            ; turn LED off here 

LEDoff		;		<-------moved
		bcf GPIO,5                      ; set bit 5 of GPIO register to 0 (low)
		goto	start ; <-------changed
		
LEDon    
		bsf GPIO,5                      ; set bit 5 of GPIO register to 1 (high)
		goto	start ; <-------changed

HTH

Mike.
 
Also, I noticed you don't allow a delay for the ADC acquisition time. I posted some code in this thread that shows how to read the ADC.

Mike.
 
Here is code modified. Pommie, you will probably recognize a lot of your work.

Please go over this, as it compiles well for asm.

Code:
Init_ADC0					        ;set for AN0
                                    ; Set ADCON0
    		movlw   b'10000001' 
    		movwf   ADCON0          ; bit 7 is set meaning results will be right justified, and bit 0 is also set, meaning A/D module is operating. no other bit are set so Channel 00 for AN0 will be read.
            return                        
    		
    		
		    

Init_ADC1					        ; set for AN1
                                    ; Set ADCON0
    		movlw   b'10000101'
    		movwf   ADCON0          ; bit 7 is set meaning results will be right justified, and bit 0 is also set, meaning A/D module is operating. bit 2 is set, meaning Channel 01 for AN1 is ready for reading.
            return
         
Read_ADC1   
            call delay1             ; small delay for A/D aquisition time.
                                    ; read CHS0 ( channel 0)
    		bsf	ADCON0, GO_DONE		; initiate conversion
    		btfsc   ADCON0, GO_DONE
    		goto    $-1			    ; wait for ADC to finish
            movf    ADRESH,W        ; move results from ADRESH file to W
    		movwf   Word            ; move value from W to file named Word
    		BANKSEL ADRESL          ; switch to bank 1
    		movf    ADRESL,W        ; move results from ADRESL file to W
    		movwf   Word+1          ; move value from W to file named Word and add 1
    		nop
    		nop
    		nop
    		return
    		
    		
Read_ADC2   
            call delay1             ; small delay for A/D aquisition time.                        
                                    ; read CHS1 (channel 1)
    		bsf	ADCON0, GO_DONE		; initiate conversion
    		btfsc   ADCON0, GO_DONE
    		goto    $-1			    ; wait for ADC to finish
         	movf    ADRESH,W        ; move results from ADRESH file to W
    		movwf   Word            ; move value from W to file named Word
    		BANKSEL ADRESL          ; switch to bank 1
    		movf    ADRESL,W        ; move results from ADRESL file to W
    		movwf   Word+1          ; move value from W to file named Word and add 1
    		nop
    		nop
    		nop
    		return
    		
    		
result
            movlw	low(0x015B)     ; load W with value of low 0x15
	        subwf	Word,W          ; subtract value in file Word, with value in W
        	movlw	high(0x015B)    ; load W with value of 0x15
          	btfss	STATUS,C        ; check to see if bit "C", in Status is set.
         	movlw	high(0x015B)+1  ; load W with value high 0x15 and add 1
        	subwf	Word+1,W        ; subtract value in file Word, with value in W
            btfss	STATUS,C        ; carry clear if word is less than 0x15B
	        call	LEDon
         	movlw	low(0x0266)
        	subwf	Word,W
        	movlw	high(0x0266)
         	btfss	STATUS,C
         	movlw	high(0x0266)+1
	        subwf	Word+1,W
            
        	btfsc	STATUS,C        ; carry set if word is greater or equal to 0x266
	        goto	LEDon
	        

            ; turn LED off here 
	
	
	
LEDoff
   
            bcf GPIO,5                      ; set bit 5 of GPIO register to 0 (low)
            goto start      		
LEDon
    
            bsf GPIO,5                      ; set bit 5 of GPIO register to 1 (high)
            goto start
            
delay1                                      ; will delay W*8 cycles including the call/return
		    addlw	0xff                    ; add -1 to W			1
	    	btfsc	STATUS,Z                ; =zero?				1/2
	    	goto	DoneDelay               ; yes, better get out of here	2
		    nop                             ; delay a bit			1
	    	goto	$+1                     ; delay a bit more		2
	    	goto	delay1                  ; go around again			2
DoneDelay	return	                        ;						2
Thanks.
 
One little problem, the delay routine requires a value in W so put a movlw 5 before the call. The 5 assumes you have a low impedance source, if you get incorrect readings then change the 5 to something bigger. Apart from that it looks fine. Does it work?

Mike.
 
I will keep you posted, and will add value to W for delay.

I should know by early afternoon if it works. Thanks for all the help.
 
Properly selecting Banks in portsetup would help. But it didn't help. I'm still wondering what is wrong, and maybe 2V on AN0 or 1.5V on AN1 isn't enough.

I will try opamp LM358 or similar.

LED does not light up.

OH well, it's Sunday after all.
 
It's been a week, and I think I finally got it. Here is code, and again if it looks like you can improve on it, let me know.

Code:
;***** VARIABLE DEFINITIONS

Word equ 0x30 





;**********************************************************************
		ORG     0x000             ; processor reset vector
		goto    main              ; go to beginning of program
	

		ORG     0x004             ; interrupt vector location
		

; isr code can go here or be located as a call subroutine elsewhere



; these first 4 instructions are not required if the internal oscillator is not used
main    
        
		call    0x3FF             ; retrieve factory calibration value
		bsf     STATUS,RP0        ; set file register bank to 1 
		movwf   OSCCAL            ; update register with factory cal value 
		bcf     STATUS,RP0        ; set file register bank to 0


;*******************************************************************************************************
;**************************************  Begining of application code  *********************************
;*******************************************************************************************************


portsetup
       bcf STATUS, RP0  ; ensure Bank "0" is previously selected 
                        ; The default chip configuration upon start up, or reset of 12f675, is analogue input on GP0, GP1, GP2 and GP4
                        ; to alter this configuration, next 2 instructions are necessary, customize per your application.
       movlw 07h        ; move literal to working register 
       movwf CMCON      ; turn comparators off as they are not used here
       bsf STATUS, RP0  ; switch to Bank "1" to set up analogue ports                 
       movlw 03h        ; move literal 03h working register
       movwf ANSEL      ; move working register to file ANSEL, setting GP1 and GP0 as analogue input.                 
       movlw 0Bh        ; move literal to working register, 0Bh (001011b) (1 = input, 0 = output)
       movwf TRISIO     ; move working register value to TRISIO setting GP3, GP1 and GP0, as inputs, and GP2, GP4 and GP5, as digital outputs.
       bcf STATUS, RP0  ; return to Bank "0"
       
start  
       nop              ; small delay to settle micro
       nop
       nop
       nop
       nop
       btfss GPIO,3     ; check to see if PTO is engaged.(high) if set then skip next instruction
       goto start       ; if not set, loop back to start
       call Init_ADC0
       call Read_ADC0
       nop
       nop
       BANKSEL GPIO     ; this is necessary only if control of pins,(such as outputs) on GPIO5 is needed after reading A/D.
       call result
       nop
       nop
       nop              ; small delay to settle micro
       btfss GPIO,3     ; check to see if PTO is engaged.(high) if set then skip next instruction
       goto start       ; if not set, loop back to start       
       call Init_ADC1
       call Read_ADC1
       nop
       nop
       BANKSEL GPIO     ; this is necessary only if control of pins,(such as outputs) on GPIO5 is needed after reading A/D.
       call result
       goto start

Init_ADC0					        
       movlw   b'10000001' 
       movwf   ADCON0   ; bit 7 is set meaning results will be right justified, and bit 0 is also set, meaning A/D module is operating. no other bits are set so Channel 00 for AN0 will be set for read.
       return                        
    		
    		
		    

Init_ADC1					        
    	movlw   b'10000101'
    	movwf   ADCON0  ; bit 7 is set meaning results will be right justified, and bit 0 is also set, meaning A/D module is operating. bit 2 is set, meaning Channel 01 for AN1 is set for reading.
        return	
         
Read_ADC0   
        call delay1             ; small delay for A/D aquisition time.
                                    ; read CHS0 ( channel 0)
        bsf	ADCON0, GO_DONE		; initiate conversion
    	btfsc   ADCON0, GO_DONE
    	goto    $-1			    ; wait for ADC to finish, after which GO/DONE bit is cleared automaticaly after conversion.
        movf    ADRESH,W        ; move results from ADRESH file to W
    	movwf   Word            ; move value from W to file named Word
    	BANKSEL ADRESL          ; switch to bank 1
    	movf    ADRESL,W        ; move results from ADRESL file to W
    	movwf   Word+1          ; move value from W to file named Word and add 1
    	nop
    	nop
    	nop
    	return
    		
    		
Read_ADC1   
        call delay1             ; small delay for A/D aquisition time.                        
                                    ; read CHS1 (channel 1)
    	bsf	ADCON0, GO_DONE		; initiate conversion
    	btfsc   ADCON0, GO_DONE
    	goto    $-1			    ; wait for ADC to finish, after which GO/DONE bit is cleared automaticaly after conversion
        movf    ADRESH,W        ; move results from ADRESH file to W
    	movwf   Word            ; move value from W to file named Word
    	BANKSEL ADRESL          ; switch to bank 1
    	movf    ADRESL,W        ; move results from ADRESL file to W
    	movwf   Word+1          ; move value from W to file named Word and add 1
    	nop
    	nop
    	nop
    	return
    		
    		
result
        movlw	low(0x015B)     ; load W with value of low 0x15
	    subwf	Word,W          ; subtract value in file Word, with value in W
        movlw	high(0x015B)    ; load W with value of 0x15
        btfss	STATUS,C        ; check to see if bit "C", in Status is set.
        movlw	high(0x015B)+1  ; load W with value high 0x15 and add 1
        subwf	Word+1,W        ; subtract value in file Word, with value in W
        btfss	STATUS,C        ; carry clear if word is less than 0x15B
	    call	LEDon
        movlw	low(0x0266)
        subwf	Word,W
        movlw	high(0x0266)
        btfss	STATUS,C
        movlw	high(0x0266)+1
	    subwf	Word+1,W
            
        btfsc	STATUS,C        ; carry set if word is greater or equal to 0x266
	    goto	LEDon
	        
LEDoff
   
        bcf GPIO,5              ; set bit 5 of GPIO register to 0 (low)
        goto start      		
LEDon
    
        bsf GPIO,5              ; set bit 5 of GPIO register to 1 (high)
        goto start
            
delay1      
        movlw 05h               ; will delay W*8 cycles including the call/return
		addlw	0xff            ; add -1 to W			1
	    btfsc	STATUS,Z        ; =zero?				1/2
	    goto	DoneDelay       ; yes, better get out of here	2
		nop                     ; delay a bit			1
	    goto	$+1             ; delay a bit more		2
	    goto	delay1          ; go around again			2
DoneDelay
    	return	                 



        
		END                       ; directive 'end of program'

Does anybody know what the minimum readable voltage on A/D module is???
Can it read 1 volt,to a maximum of 5v??
Is it necessary to amplify above 1 v as this is too low???

Thanks to all who have helped me.

P.S. what stumped me for so long, was the fact that, to control an output pin,after reading A/D, you have to switch back to bank "0", after manipulating value in ADRESL.
Otherwise nothing happens.

Also,the datasheet is wrong .
Code:
movlw 07h
movwf CMCON
This is example given to setup analogue pins on (ANSEL) register.
It does not setup ANSEL register or modify analogue inputs, but makes sure that Comparators are turned off.
Code:
 
Code:
Read_ADC0   
        call delay1             ; small delay for A/D aquisition time.
                                    ; read CHS0 ( channel 0)
        bsf	ADCON0, GO_DONE		; initiate conversion
    	btfsc   ADCON0, GO_DONE
    	goto    $-1			    ; wait for ADC to finish, after which GO/DONE bit is cleared automaticaly after conversion.
        movf    ADRESH,W        ; move results from ADRESH file to W
    	movwf   Word            ; move value from W to file named Word
    	BANKSEL ADRESL          ; switch to bank 1
    	movf    ADRESL,W        ; move results from ADRESL file to W
    	movwf   Word+1          ; move value from W to file named Word and add 1
    	nop
    	nop
    	nop
    	return

Why are you moving the ADRESH into Word and the ADRESL into Word+1, shouldn't it be the other way around? It seems, due to this, you are manipulating the wrong values throughout the code. I may be wrong...
 
Actually, I never thought of it as a problem. I just followed the example that was given to me by Pommie.
Remember, this is work in progress, so I am open to any suggestions.
Thanks.
 
Hi hjl4,

Burg is right in his observation, the high byte should go in word+1 and the low byte should go in word. You should swap them in the ADC routines. Which way round the bytes of a 16 bit word are stored is called Endian. I was brought up to use little endian so the low byte goes in the first location. See a better explanation of Endianness. From your comment, "move value from W to file named Word and add 1" I can see that you have misunderstood the instruction. Movwf Word+1 placed whatever is in W into location Word+1 - in this case that would be in the SFR located at 0x31.

The other thing wrong with your code is the delay routine. You have placed the movlw 5 inside the delay loop and so it will never return.
I would suggest changing it to,
Code:
delay1      
		movlw 05h               ; will delay W*8 cycles including the call/return
[COLOR="Red"]DelayW[/COLOR]		addlw	0xff            ; add -1 to W			1
		btfsc	STATUS,Z        ; =zero?				1/2
		goto	DoneDelay       ; yes, better get out of here	2
		nop                     ; delay a bit			1
		goto	$+1             ; delay a bit more		2
		goto	[COLOR="red"]DelayW[/COLOR]          ; go around again			2
DoneDelay
		return

Mike.
 
One other thing, a lot of programmers write over the calibration byte at location 0x3ff. If your programmer does this then your code will never work. I would remove the first 4 instructions from your code.

Mike.
 
I hate endian, it can get really confusing. Is there any requirement by PIC's in general? To my understanding they only (ones I've dealt with) use 1 byte at a time (i.e. no word size, long, etc.), so Endian wouldn't be specified by the PIC itself, just the programmer.
 
burg said:
I hate endian, it can get really confusing. Is there any requirement by PIC's in general? To my understanding they only (ones I've dealt with) use 1 byte at a time (i.e. no word size, long, etc.), so Endian wouldn't be specified by the PIC itself, just the programmer.

Yes, Endian is (human) programmer specific on PICs. I guess when using C or Basic then Endianness would be fixed but in asm it's up to you.

I always preferred litle endian because on processors like 80486 it meant I could use the same label no matter what size operation I was preforming.
I.E.
Code:
   mov  al,Var     -8 bit
   mov  ax,Var    -16 bit
   mov  eax,Var  -32 bit

Mike.

Mike.
 
burg said:
I hate endian, it can get really confusing. Is there any requirement by PIC's in general? To my understanding they only (ones I've dealt with) use 1 byte at a time (i.e. no word size, long, etc.), so Endian wouldn't be specified by the PIC itself, just the programmer.

It makes no difference whatsoever, it's purely down to personal choice.
 
Thanks Pommie and to all who have given their input, on this project.

Well Burg, I was open to suggestions from the beginning, and thanks again for the help. That whole routine of result, would take me a week to fully understand.

Yes my comment about movwf Word+1, was wrong as pointed out by Pommie, but I knew what it meant, so I changed that.

This coming Monday, I will be implementing this program, on a circuit board, and when, if it works, I will take pics of it and update you guys, as to how this all works.

I can only hope the results will be positive, as it works now, on the simulator.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top