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.

Problems with PIC 16F690 Analogue to Digital Conversion

Status
Not open for further replies.

chisokot

New Member
Hi


I am a newbie on Microprocessors and have been learning to program the devices. The code below only works if I take the converted output from ADRESH and place it on PORTC. When I add the highlighted section it fails. I have tried everything I could think out but without success. Could someone please point me in the right direction.


Thanks

#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

cblock 0x20
Display ; define a variable to hold the diplay
Delay

endc

org 0

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 Analoga
movwf ANSEL
bcf STATUS,RP0 ; address Register Page 0
bcf STATUS,RP1
movlw 0x01
movwf ADCON0 ; configure A2D for Channel 0 (RA0), Left justified, and turn on the A2D module

MainLoop:
call Delay200mS
bsf ADCON0,GO ; start A2D conversion
btfss ADCON0,GO ; this bit will change to zero when the conversion is complete
goto $-1
movf ADRESH,w ; read the A2D
movwf Display
movf Display,w ; save the value

;movf PORTC ; send to PORTC

TEST_0:
sublw 0xDE ; Subtract W from Reference
btfsc STATUS,C ; Is battery Voltage higher than Reference?
goto Switch0
bsf PORTC,0 ; If battery Voltage is higher than Reference - Set PORTC,0 to high
goto TEST_1
Switch0:
bcf PORTC,0 ; If battery Voltage is lower than Reference - Set PORTC,0 to low

TEST_1:
sublw 0xE2 ; Subtract W from Reference
btfsc STATUS,C ; Is battery Voltage higher than Reference?
goto Switch1
bsf PORTC,1 ; If battery Voltage is higher than Reference - Set PORTC,1 to high
goto MainLoop
Switch1:
bcf PORTC,1 ; If battery Voltage is lower than Reference - Set PORTC,1 to low
goto MainLoop

Delay200mS:
decfsz Delay,f ; delay
goto $-1
decfsz Delay+1,f ; delay 768uS
goto $-3
return

end
 
Hi,

Your highlighted code does not show up, so not sure what code your are refering to.
When you post code use the # icon so it keeps its format, or if its large, zip or rar it.

One thing that stands out, your load FF to ANSEL, turns on the first 8 analogue ports, but it you see the datasheet, page 6 table 5, it shows that some of PortC pins are some of these first 8 analogue ports, so you already have a conflict that can cause weird problems,
 
Thanks Wp100 for your response and suggestions.

I have setup only one analogue input but the code still fails. Here is the code with the suggested changes. As stated before the code works well when I pass the converted output to PORTC. When I add the part in red - convrsion fails

#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)


cblock 0x20
Display ; define a variable to hold the display
Delay

endc

org 0

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 0x01 ; make PortA,1 pin Analogue
movwf ANSEL
bcf STATUS,RP0 ; address Register Page 0
bcf STATUS,RP1
movlw 0x01
movwf ADCON0 ; configure A2D for Channel 0 (RA0), Left justified, and turn on the A2D module

MainLoop:
call Delay200mS
bsf ADCON0,GO ; start A2D conversion
btfss ADCON0,GO ; this bit will change to zero when the conversion is complete
goto $-1
movf ADRESH,w ; read the A2D
movwf Display
movf Display,w ; save the value
;movwf PORTC ; send to PORTC

TEST_0:
sublw 0xDE ; Subtract W from Reference
btfsc STATUS,C ; Is battery Voltage higher than Reference?
goto Switch0
bsf PORTC,0 ; If battery Voltage is higher than Reference - Set PORTC,0 to high
goto TEST_1
Switch0:
bcf PORTC,0 ; If battery Voltage is lower than Reference - Set PORTC,0 to low

TEST_1:
sublw 0xE2 ; Subtract W from Reference
btfsc STATUS,C ; Is battery Voltage higher than Reference?
goto Switch1
bsf PORTC,1 ; If battery Voltage is higher than Reference - Set PORTC,1 to high
goto MainLoop
Switch1:
bcf PORTC,1 ; If battery Voltage is lower than Reference - Set PORTC,1 to low
goto MainLoop


Delay200mS:
decfsz Delay,f ; delay
goto $-1
decfsz Delay+1,f ; delay 768uS
goto $-3
return

end
 
Hi,

Looks like Test_0 works ok as does Test_1, but what is W when you start Test_1 ?

Have you tried running your code in Mplab Debugger 'Simulator' - where you can F7 single step through your code and observe your registers - W and Status are on the bottom toolbar.
 
If your code is supposed to do what the comments state then I think you need a few changes,

Code:
TEST_0:
		sublw	0xDE		; Subtract W from Reference
		btfs[COLOR="red"]s[/COLOR]	STATUS,C	; Is battery Voltage higher than Reference?
		goto	Switch0 
		bsf	PORTC,0		; If battery Voltage is higher than Reference - Set PORTC,0 to high
		goto	TEST_1
Switch0:
		bcf	PORTC,0		; If battery Voltage is lower than Reference - Set PORTC,0 to low

TEST_1:		[COLOR="red"]movfw	Display		;get the value again[/COLOR]
		sublw	0xE2		; Subtract W from Reference
		btfs[COLOR="red"]s[/COLOR]	STATUS,C	; Is battery Voltage higher than Reference?
		goto	Switch1 
		bsf	PORTC,1		; If battery Voltage is higher than Reference - Set PORTC,1 to high
		goto	MainLoop
Switch1:
		bcf	PORTC,1		; If battery Voltage is lower than Reference - Set PORTC,1 to low
		goto	MainLoop

To post code so it comes out as above type [code] before it and [/code] after it.

Edit, I see Wp100 spotted the problem earlier. I should read before I type.

Mike.
 
Last edited:
Hi Wp100

When i step through the code ADRESH register shows 0x00 and ADRESL also shows 0x00
Are these two registers supposed to show their values?

The value of W also appears to be 0x00 indicating that the ADC has failed to convert the analogue input.
btfsc STATUS,C is set in both TEST_0 and TEST_1 indicating that:
W<= 0xDE
W<= 0xE2

If I use a different register as below
Code:
movfw    ADRESH,w    ; move ADC output to W
movwf    FSR              ; place W into FSR

FSR register also shows 0x00

My view is that something is stopping the ADC from working properly
 
hi,
It reads the ADC ok for me on the Oshonsoft sim.

What values are you loading into the MPLAB Sim for the ADC to work with.?
AAesp03.gif
 
Hi Pommie

Thanks for the guidance in posting code:
I have implimented "getting the value again" on TEST2

On changing btfsc to btfss.
For it to work, I would have to change the code to look something like this:

Code:
TEST_0:
		sublw	0xDE		; Subtract W from 0xDE
		btfss	STATUS,C	   	; Is battery Voltage higher than 0xDE?
		goto	Switch0 
		bcf	PORTC,0		; If battery Voltage is lower than 0xDE - Set PORTC,0 low
		goto	TEST_1
Switch0:
		bsf	PORTC,0		; If battery Voltage is higher than 0xDE - Set PORTC,0 high

TEST_1:
                	movf     Display,w         ; Get the value again
		sublw	0xE2		; Subtract W from 0xE2
		btfss	STATUS,C		; Is battery Voltage higher than 0xE2?
		goto	Switch1 
		bcf	PORTC,1		; If battery Voltage is lower than 0xE2 - Set PORTC,1 to low
		goto	TEST_1
Switch1:
		bsf	PORTC,1		; If battery Voltage is higher than 0xE2 - Set PORTC,1 to high
		goto	MainLoop

The problem here seems to be that the ADC stops converting for some unknown reason.
 
There was an error in the code. Here is the corrected version

Hi Pommie

There was an error in my code. Here is the corrected version

Code:
TEST_0:
		sublw	0xDE		; Subtract W from 0xDE
		btfss	STATUS,C	   	; Is battery Voltage higher than 0xDE?
		goto	Switch0 
		bcf	PORTC,0		; If battery Voltage is lower than 0xDE - Set PORTC,0 low
		goto	TEST_1
Switch0:
		bsf	PORTC,0		; If battery Voltage is higher than 0xDE - Set PORTC,0 high

TEST_1:
                	movf     Display,w         ; Get the value again
		sublw	0xE2		; Subtract W from 0xE2
		btfss	STATUS,C		; Is battery Voltage higher than 0xE2?
		goto	Switch1 
		bcf	PORTC,1		; If battery Voltage is lower than 0xE2 - Set PORTC,1 to low
		goto	MainLoop
Switch1:
		bsf	PORTC,1		; If battery Voltage is higher than 0xE2 - Set PORTC,1 to high
		goto	MainLoop
 
Hi ericgibbs

I am using Microchip PICkit2.

I see that you are able to simulate an analog input. As for me, I am not able to provide an input to the simulator.
When I load the program into the PIC it is supposed to read the voltage connected to the input. The ADC input has a 10k variable resistor connected to it. This allows the input voltage to be varied between 0 and 5 volts. The simulator LEDs do not change when I vary the input.
 
Hi ericgibbs

I am using Microchip PICkit2.

I see that you are able to simulate an analog input. As for me, I am not able to provide an input to the simulator.
When I load the program into the PIC it is supposed to read the voltage connected to the input. The ADC input has a 10k variable resistor connected to it. This allows the input voltage to be varied between 0 and 5 volts. The simulator LEDs do not change when I vary the input.

hi,
Check your ADCON0.GO bit test sense after BSF ADCON0.GO

I found in the sim it was reading the ADC every other pass thru the subr..
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top