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.

Some ideals on adc

Status
Not open for further replies.

be80be

Well-Known Member
What would be the best way to say catch four adc values like low to high
I have this started it works good just don't no how to save four values
Code:
	list		p=16f684		; list directive to define processor
	#include	<P16F684.inc>		; processor specific variable definitions
	errorlevel -302 ; Turn off banking message
                            ; known tested (good) code

	__CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
	


	CBLOCK 		0x020
	saveadc
	endc


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


	ORG			0x004	    ; interrupt vector location

Start:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0xFF
     movwf     TRISA          ; Make PortA all input
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0

     bcf       STATUS,RP0     ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xFF           ; we want all Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
     
     movlw     0x01
     movwf     ADCON0         ; configure A2D for Channel 0 
MainLoop:
     call	adcdelay		  ;delay to charge cap
     bsf       ADCON0,GO      ; start conversion
     btfss     ADCON0,GO      ; this bit will change to zero when the conversion is complete
     goto      $-1

     movf     ADRESH,w       ; Copy the display to the LEDs
     movwf     saveadc		  ;save value adc
     movf	 saveadc
     movwf	 PORTC
     goto      MainLoop
adcdelay:
	 nop					  ;1 cycle

	 return					  ;4 cycles (including call)
	
     end
 
Last edited:
Are you trying to save 4 ADC readings from 4 different channels/pins or 4 ADC readings from a single channel/pin?
 
Last edited:
From a single pin I was using the 16f684 for testing when I get it all working and get some 12f675 in I'm going to use them on GPIO,0 for the adc
 
Simply allocate 4 sequential variables in memory and load the FSR with the address of the first one. The IRP bit of the STATUS register should contain the 9th bit of the address.
Then you simply use the INDF register to manipulate the data which the FSR points to. You increment the FSR register, in your MainLoop, to make INDF point to the next variable in memory and after 4 intterations, reset the FSR to the address of the first variable and then do it all over again.

From the datasheet:
Code:
A simple program to clear RAM locations 20h-2Fh
using indirect addressing is shown in Example 2-1.

movlw 0x20 ;initialize pointer
movwf FSR ;to RAM
NEXT
clrf INDF ;clear INDF register and thus what FSR points to.
incf  FSR,F ;inc pointer
btfss FSR,4 ;all done?
goto NEXT ;no clear next
CONTINUE
: ;yes continue
 
Last edited:
I no this is not right but I'm lost with what i need to do How do I add to not clear
Code:
	CBLOCK 		0x020
	ad1
	ad2	
	ad3
	ad4
	endc


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


	ORG			0x004	    ; interrupt vector location

Start:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0xFF
     movwf     TRISA          ; Make PortA all input
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0

     bcf       STATUS,RP0     ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xFF           ; we want all Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
     
     movlw     0x01
     movwf     ADCON0         ; configure A2D for Channel 0 
MainLoop:
     call	   adcdelay		  ;delay to charge cap
     bsf       ADCON0,GO      ; start conversion
     btfss     ADCON0,GO      ; this bit will change to zero when the conversion is complete
     goto      $-1

     movf       ADRESH,w       ; Copy the display to the LEDs
     movlw 	 ad1 		  ;initialize pointer
     movwf     FSR            ;to RAM
NEXT
     clrf      INDF 		  ;clear INDF register and thus what FSR points to.
     incf      FSR,F          ;inc pointer
     btfss     FSR,4          ;all done?
     goto      NEXT           ;no clear next
CONTINUE                      ;yes continue  
     goto      MainLoop
adcdelay:
	 nop					  ;1 cycle

	 return					  ;4 cycles (including call)
	
     end
 
Last edited:
That example was just to demonstrate how to use indirect addressing. The following code will put 4 consecutive 8bit ADC readings into ad1-ad4 and then repeat endlessly:
Code:
    list        p=16f684        ; list directive to define processor
    #include    <P16F684.inc>        ; processor specific variable definitions
    errorlevel -302 ; Turn off banking message
                            ; known tested (good) code

    __CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
    



    CBLOCK         0x020
    ad1
    ad2    
    ad3
    ad4
    endc


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


    ORG            0x004        ; interrupt vector location

Start:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0xFF
     movwf     TRISA          ; Make PortA all input
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0

     bcf       STATUS,RP0     ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xFF           ; we want all Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
     
     movlw     0x01
     movwf     ADCON0         ; configure A2D for Channel 0 
MainLoop:
     movlw      0x20           ;initialize pointer
     movwf     FSR            ;to ad1 @ 0x20
NEXT
     call       adcdelay          ;delay to charge cap
     bsf       ADCON0,GO      ; start conversion
     btfss     ADCON0,GO      ; this bit will change to zero when the conversion is complete
     goto      $-1
     movf      ADRESH,w       ; Copy the display to the LEDs
     movwf       PORTC
     movwf     INDF           ;Copy the display to what FSR points to (ad1,2,3,or 4).
     incf      FSR,F          ;inc pointer
     btfss     FSR,2          ;Are we done 4 bytes yet?
     goto      NEXT           ;no so goto next
     goto      MainLoop
adcdelay:
     nop                      ;1 cycle

     return                      ;4 cycles (including call)
    
     end
 
Last edited:
Thanks Kchriste This is kind of cool I set it to show two of the values with a delay between. I found some good reading for indirect addressing. going to read up
them
Code:
 list        p=16f684        ; list directive to define processor
    #include    <P16F684.inc>        ; processor specific variable definitions
    errorlevel -302 ; Turn off banking message
                            ; known tested (good) code

    __CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
    



    CBLOCK         0x020
    ad1
    ad2    
    ad3
    ad4
	d1
	d2
	d3
	endc


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


    ORG            0x004        ; interrupt vector location

Start:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0xFF
     movwf     TRISA          ; Make PortA all input
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0

     bcf       STATUS,RP0     ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xFF           ; we want all Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
     
     movlw     0x01
     movwf     ADCON0         ; configure A2D for Channel 0 
MainLoop:
     movlw      0x20           ;initialize pointer
     movwf     FSR            ;to ad1 @ 0x20
NEXT
     call       adcdelay          ;delay to charge cap
     bsf       ADCON0,GO      ; start conversion
     btfss     ADCON0,GO      ; this bit will change to zero when the conversion is complete
     goto      $-1
     movf      ADRESH,w       ; Copy the display to the LEDs
     ;movwf       PORTC
     movwf     INDF           ;Copy the display to what FSR points to (ad1,2,3,or 4).
     incf      FSR,F          ;inc pointer
     btfss     FSR,2          ;Are we done 4 bytes yet?
     goto      NEXT           ;no so goto next
     movf	   ad2
     movwf	   PORTC
     call	   Delay
     movf	   ad4
     movwf	   PORTC
     call	   Delay
     goto      MainLoop
adcdelay:
     nop                      ;1 cycle

     return                      ;4 cycles (including call)
Delay
			;499994 cycles
	movlw	0x03
	movwf	d1
	movlw	0x18
	movwf	d2
	movlw	0x02
	movwf	d3
Delay_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	$+2
	decfsz	d3, f
	goto	Delay_0

			;2 cycles
	goto	$+1

			;4 cycles (including call)
	return
    
     end
 
Last edited:
If I was getting a bit conversion and I wanted to check for
I would do some thing like 256/5 = 51.2
1. 0 to 1 volt 208 to 256
2. 1 to 2 volt 156 to 207
3. 2 to 3 volt 104 to 155
4. 3 to 4 volt 52 to 103
5. 4 to 5 volt 0 to 51
I rounded it off a little but is this some what the ideal or am I backward. In thinking. ?
 
I don't understand what you are asking. Do mean that you want to scale the 8-bit ADRESH ADC result of 0-255 to some other range such as 1-5?
 
When the Adc gets a conversion In 8 bit mode the 8-bit converter has 256 states so is Internal Reference say set to 5 volts it will be = 256 2.5volts would be = 128
and 0 would be = 0 or is this wrong.
 
That is correct.
What I don't understand is what you want to do with the 0-255 data. Do you want to display the voltage as 0.00 to 5.00 on an LCD or LED display?
 
Say I read 0 to 1 volt my program will do (A)
If I read 1 to 2 volts my program will do (b)
and so on to 5 volts
 
OK, I see what you want to do now. Well, you don't need to do any scaling with the PIC at all then. Just do a bunch of comparisons and gotos. Something like this maybe:

Code:
#define _1VOLT 0x33
#define _2VOLT 0x66
#define _2_5VOLT 0x7F
#define _3VOLT 0x99
#define _4VOLT 0xCC
#define _5VOLT 0xFF



Start:
    movlw _1VOLT
    subwf ADRESH, w
    BNC LessThan1V                ; Branch if less than 1V
    movlw _2VOLT
    subwf ADRESH, w
    BNC LessThan2V                ; Branch if Between 1V and 2V
    movlw _2_5VOLT
    subwf ADRESH, w
    BNC LessThan2_5V             ; Branch if Between 2V and 2.5V
    movlw _3VOLT
    subwf ADRESH, w
    BNC LessThan3V                ; Branch if Between 2.5V and  3V
    movlw _4VOLT
    subwf ADRESH, w
    BNC LessThan4V                ; Branch if Between 3V and 4V
    ;Hmmm..  must be 4V or more here.
 
Last edited:
BNC = branch not carry. It is a pseudo op that compiles to,

Code:
    btfss STATUS,C
    goto  label

Mike.
 
Ok Just to make sure I have the right

movlw _1VOLT This puts 0x33 in W

subwf ADRESH, w This Subtract W from f

BNC LessThan1V This branch on no carry

So the way this works forget it I see now that wrote it out like this.

This puts 0x33 in W Subtract W from f branch on no carry
So it keeps stepping up till it finds the one that it is smaller then
Thanks a bunch Kchriste
Some thing like this
Code:
Start:
	movlw _1VOLT
	subwf ADRESH, w
	BNC LessThan1V    ; if adc = 33or less run code at LessThen1V
	
	
LessThen1V:
				;run code I want to run here
 
Last edited:
Now I'm getting some where this turns on the leds by the voltages
But it think it's set for 10 bit conversion
Code:
list		p=16f684		; list directive to define processor
	#include	<P16F684.inc>		; processor specific variable definitions
	errorlevel -302 ; Turn off banking message
                            ; known tested (good) code

	__CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
	


	CBLOCK 		0x020
	endc
	#define _1VOLT 0x33
	#define _2VOLT 0x66
	#define _2_5VOLT 0x7F
	#define _3VOLT 0x99
	#define _4VOLT 0xCC
	#define _5VOLT 0xFF




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


	ORG			0x004	    ; interrupt vector location

init:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0xFF
     movwf     TRISA          ; Make PortA all input
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0

     bcf       STATUS,RP0     ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xFF           ; we want all Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
     
     movlw     0x01
     movwf     ADCON0         ; configure A2D for Channel 0 
MainLoop:
     call	adcdelay		  ;delay to charge cap
     bsf       ADCON0,GO      ; start conversion
     btfss     ADCON0,GO      ; this bit will change to zero when the conversion is complete
     goto      $-1

     movf     ADRESH,w       ; Copy the display to the LEDs
    movlw 	_1VOLT
    subwf	 ADRESH, w
    BNC 	LessThan1V                ; Branch if less than 1V
    movlw 	_2VOLT
    subwf	 ADRESH, w
    BNC 	LessThan2V                ; Branch if Between 1V and 2V
    movlw 	_2_5VOLT
    subwf 	ADRESH, w
    BNC 	LessThan2_5V             ; Branch if Between 2V and 2.5V
    movlw 	_3VOLT
    subwf	 ADRESH, w
    BNC 	LessThan3V                ; Branch if Between 2.5V and  3V
    movlw 	_4VOLT
    subwf 	ADRESH, w
    BNC 	LessThan4V                ; Branch if Between 3V and 4V
    								;Hmmm..  must be 4V or more here.
    goto      MainLoop
LessThan1V:
	bsf		PORTC,0
	return
LessThan2V
	bsf		PORTC,1					; lights led thats in volt range 
	return
LessThan2_5V 
	bsf		PORTC,2 
	return
LessThan3V
    bsf		PORTC,3	  
	return	
LessThan4V
	bsf		PORTC,4
	return
 

   
adcdelay:
	 nop					  ;1 cycle

	 return					  ;4 cycles (including call)
	
     end
 
I have read more then I need to lol my head is killing me but not one apnote
I have read tells you which way the conversion gos That's what was getting me and I found out the 16f684 has only a 10 bit conversion
 
I have read more then I need to lol my head is killing me but not one apnote
I have read tells you which way the conversion gos That's what was getting me and I found out the 16f684 has only a 10 bit conversion

Read my PIC ADC tutorial, you can't set PIC's to only be 8 bit, BUT you can (usually) set then right or left justified. By setting this correctly you can read just the top 8 bits, effectively giving you an 8 bit conversion.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top