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.

A/D Converter Issue with PIC16F88

Status
Not open for further replies.

Steve311

Member
PIC16F88 A/D Converter Issues

Hello Everybody- I am trying to use the ADC on a PIC16F88 to read analog voltages which will eventually be driven by a dual axis inclinometer, converted to a 10bit digital word, and then have the voltages compared to upper and lower limits for each of the dual axis(s). Depending on where the analog voltage lies with respect to the limits, there will be an output signal to drive a small DC buzzer. I have researched the ADC and its properties and I have decided to make a small program first to read the analog signal, and output the corresponding 10bit serial word. It doesnt matter really how I output the word, as long as it is somewhat accurate. I have attached my code in Assembly (working in MPLab). When I use the simulator, the program runs great and doesnt get stuck anywhere. However after I burn the PIC, I dont get the correct outputs, and they never change, so I am clearly doing something wrong. There are alot of ;comments in the code for my own good so please bare with those! Please Help!!

;Analog to Digital Conversion
;This code will read one analog input at pin AN0.
;The code will then output the corresponding 10bit decimal value to RB0-RB7, RA6, RA7.

;Call proper header, include and source files to initialize PIC

list p=16F88 ; List directive to define processor
#include <p16F88.inc> ; Processor specific variable definitions

;Configure PIC optional properties

__CONFIG _CONFIG1, _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF
;Config directive is used to embed configuration word within .asm file.
;The labels following the directive are located in the respective .inc file.
;See datasheet for information on configuration word settings.

;Define Constant Variables and Registers

cblock 0x20 ; Defines Working registers starting at 20h
DELAY
AD_X_STORAGE_LOW
AD_X_STORAGE_HIGH
endc

;Initialize Inputs/Outputs, and Registers on the PIC16F88.
;Initialize TRISA and TRISB registers.
bsf STATUS, RP0 ;Sets bit RP0 in address STATUS to 1 (switches from bank 0 to 1).
movlw B'00000000' ;Assigns RB0-RB7 as outputs.
movwf TRISB ;Writes value to TRISB register.
movlw B'00000001' ;Assigns AN0 as input, all else as outputs.
movwf TRISA ;Writes value to TRISA register.
movlw b'00000001' ;Analog input code; Bit 7=unimplemented (0), Bit 6-0 = AN<6:0> where 1 = Analog I/O and 0 = Digital I/O
movwf ANSEL ;Load it into ANSEL (this configures the function of the port pins)
bcf STATUS, RP0 ;Shifts back to Bank 0.

;Initalize a portion of the Analog to Digital Converter Module
bcf STATUS,RP1 ;clears bank 2/3 bit
bsf STATUS,RP0 ;Set bank 1 bit
movlw b'00000001' ;Analog input code; Bit 7=unimplemented (0), Bit 6-0 = AN<6:0> where 1 = Analog I/O and 0 = Digital I/O
movwf ANSEL ;Load it into ANSEL (this configures the function of the port pins)
bcf STATUS, RP0 ;Shifts back to Bank 0.

; bsf PIE1, ADIE ;Enables A/D interrupts
; bcf PIR1, ADIF ;Clears A/D interrupt flag bit
; bcf INTCON, PEIE ;Clears peripheral interrupts
; bcf INTCON, GIE ;Clears all interrupts

;Start of Main Program
; bsf PORTA, 0
START_MAIN_PROGRAM
goto ADC_GET_X

;Initalization of 'Main Program' section.
;INIT_MAIN_PROGRAM
;clrf AD_X_STORAGE_LOW ;Clearing the working register
;clrf AD_X_STORAGE_HIGH ;Clearing the working register
;goto AD_GET_X

;Get Analog Input X from AN0
ADC_GET_X
;clrf AD_X_STORAGE_LOW ;Clearing the working register
;clrf AD_X_STORAGE_HIGH ;Clearing the working register
;bcf PORTA,0 ;Clears Bit 0, AN0, (Analog Input) on Port A
;bcf STATUS,C ;Clear carry flag
movlw b'11000101' ;Bit 7-6 (ADCS<1:0>) sets the clock to be derived from the internal A/D module RC ocsilliator
;Bit 5-3 (CHS<2:0>) Analog select bits. Bit 2 = GO/DONE bit which is the AD/Conversion Status.
;if ADON=1 and GO/DONE=1, conversion in progress, 0 = not in progress. Bit 1 = unimplemented.
;Bit 0 = AD on bit; 1 = AD is on, 0 = AD is off and consumes no operating current.
movwf ADCON0 ;Move new value into ADCON0 (This is an A/D Control Register @ 1Fh)

movlw b'10000000' ;Bit 7 = AD Format, 1 = Right Justified, 0 = Left justified; Bit 6 = ADSC2 (Clock /2 select, 0 = off)
;Bit 5-4 = VCFG<1:0> = A/D Voltage Reference Config bits, 00 = Vdd as +Vref, and Vss as -Vref
;Bit 3-0 = unimplemented, read as 0
movwf ADCON1 ;Move new value into ADCON1 (This is an A/D Control Register @ 9Fh)



movlw b'00001111'
movwf DELAY
WAIT_X
decfsz DELAY, 1 ;Delay for 256 instruction cycles
goto WAIT_X ;Wait for A/D acquisition time
;bcf PIR1,ADIF ;Clear A/D interruption flag bit
bsf ADCON0,GO ;Start A/D conversion
;pbcf ADCON0,GO ;simultation purpose only
goto WAIT1_X
WAIT1_X
bcf ADCON0, GO ;simulation purpose only
btfsc ADCON0,GO ;Tests GO bit to see if A/D conversion is complete, 1 = In Progress; 0 = Not In Progress
goto WAIT1_X ;Wait for conversion to complete

movf ADRESH,W ;get conversion high byte
movwf AD_X_STORAGE_HIGH ;store it in AD_X_STORAGE_HIGH
bcf STATUS,RP1 ;clear bank 2/3
bsf STATUS,RP0 ;set bank 1
movf ADRESL,W ;get conversion low byte
;bcf STATUS,RP0 ;reset bank 0
movwf AD_X_STORAGE_LOW ;store it in AD_X_STORAGE_LOW
;bcf PIR1,ADIF ;Clear A/D interrupt flag bit
;bcf ADCON0,GO ;Ensures A/D Cnversion is not in progress.

movf AD_X_STORAGE_HIGH,W ;Move the results to the output pins
movwf PORTA
movf AD_X_STORAGE_LOW,W ;Move the results to the output pins
movwf PORTB
movlw b'11111111'
movwf DELAY
WAIT_OUTPUT
decfsz DELAY, 1
goto WAIT_OUTPUT

goto START_MAIN_PROGRAM

;goto SEND_OUTPUT ;Goes to output sending routine



;END_OUTPUT
;bsf PORTB, OUTPUT
;goto WAIT_OUTPUT

;WAIT_OUTPUT
;decfsz DELAY,F ;Delay for 256 instruction cycles
;goto WAIT_OUTPUT
;WAIT_OUTPUT1
;decfsz DELAY,1 ;Delay for 256 instruction cycles
;goto WAIT_OUTPUT

end
 
When you post code, use the 'code' tags (icon on the 'go advanced' screen), overwise it's too jumbled to read.

However, if you check my tutorials it explains how to use the analogue inputs, in an easier way than the datasheet.
 
When it works in the simulator but not in hardware then check.
1. You have the right crystal/oscillator settings. You config has no oscillator entry.
2. MCLR is held high.

To make sure your pic is running do a simple flashing LED first.

Mike.
BTW, for anyone with more time, here is the code after being run through my code tidier. There is a huge amount of remmed code in there.
Code:
;Analog to Digital Conversion  
;This code will read one analog input at pin AN0.  
;The code will then output the corresponding 10bit decimal value to RB0-RB7, RA6, RA7.   

;Call proper header, include and source files to initialize PIC  

		list	p=16F88		; List directive to define processor
#include	<p16F88.inc> 		; Processor specific variable definitions

;Configure PIC optional properties  

		__config _CONFIG1, _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF 
;Config directive is used to embed configuration word within .asm file.  
;The labels following the directive are located in the respective .inc file.  
;See datasheet for information on configuration word settings.  

;Define Constant Variables and Registers   

		cblock	0x20		; Defines Working registers starting at 20h
DELAY			 
AD_X_STORAGE_LOW 	 
AD_X_STORAGE_HIGH 	 
		endc

;Initialize Inputs/Outputs, and Registers on the PIC16F88.  
;Initialize TRISA and TRISB registers.   
		bsf	STATUS,RP0	;Sets bit RP0 in address STATUS to 1 (switches from bank 0 to 1).
		movlw	B'00000000'	;Assigns RB0-RB7 as outputs. 
		movwf	TRISB		;Writes value to TRISB register.
		movlw	B'00000001'	;Assigns AN0 as input, all else as outputs. 
		movwf	TRISA		;Writes value to TRISA register. 
		movlw	b'00000001'	;Analog input code; Bit 7=unimplemented (0), Bit 6-0 = AN<6:0> where 1 = Analog I/O and 0 = Digital I/O
		movwf	ANSEL		;Load it into ANSEL (this configures the function of the port pins)
		bcf	STATUS,RP0	;Shifts back to Bank 0.

;Initalize a portion of the Analog to Digital Converter Module  
		bcf	STATUS,RP1	;clears bank 2/3 bit 
		bsf	STATUS,RP0	;Set bank 1 bit
		movlw	b'00000001'	;Analog input code; Bit 7=unimplemented (0), Bit 6-0 = AN<6:0> where 1 = Analog I/O and 0 = Digital I/O
		movwf	ANSEL		;Load it into ANSEL (this configures the function of the port pins)
		bcf	STATUS,RP0	;Shifts back to Bank 0.

; bsf PIE1, ADIE ;Enables A/D interrupts   
; bcf PIR1, ADIF ;Clears A/D interrupt flag bit  
; bcf INTCON, PEIE ;Clears peripheral interrupts  
; bcf INTCON, GIE ;Clears all interrupts  

;Start of Main Program 
; bsf PORTA, 0
START_MAIN_PROGRAM 
		goto	ADC_GET_X

;Initalization of 'Main Program' section.   
;INIT_MAIN_PROGRAM 
;clrf AD_X_STORAGE_LOW ;Clearing the working register  
;clrf AD_X_STORAGE_HIGH ;Clearing the working register  
;goto AD_GET_X

;Get Analog Input X from AN0  
ADC_GET_X
;clrf AD_X_STORAGE_LOW ;Clearing the working register  
;clrf AD_X_STORAGE_HIGH ;Clearing the working register  
;bcf PORTA,0 ;Clears Bit 0, AN0, (Analog Input) on Port A  
;bcf STATUS,C ;Clear carry flag  
		movlw	b'11000101'	;Bit 7-6 (ADCS<1:0>) sets the clock to be derived from the internal A/D module RC ocsilliator
;Bit 5-3 (CHS<2:0>) Analog select bits. Bit 2 = GO/DONE bit which is the AD/Conversion Status.   
;if ADON=1 and GO/DONE=1, conversion in progress, 0 = not in progress. Bit 1 = unimplemented.  
;Bit 0 = AD on bit; 1 = AD is on, 0 = AD is off and consumes no operating current.  
		movwf	ADCON0		;Move new value into ADCON0 (This is an A/D Control Register @ 1Fh)

		movlw	b'10000000'	;Bit 7 = AD Format, 1 = Right Justified, 0 = Left justified; Bit 6 = ADSC2 (Clock /2 select, 0 = off)
;Bit 5-4 = VCFG<1:0> = A/D Voltage Reference Config bits, 00 = Vdd as +Vref, and Vss as -Vref  
;Bit 3-0 = unimplemented, read as 0  
		movwf	ADCON1		;Move new value into ADCON1 (This is an A/D Control Register @ 9Fh)



		movlw	b'00001111'
		movwf	DELAY 
WAIT_X			 
		decfsz	DELAY,1		;Delay for 256 instruction cycles
		goto	WAIT_X		;Wait for A/D acquisition time 
;bcf PIR1,ADIF ;Clear A/D interruption flag bit   
		bsf	ADCON0,GO	;Start A/D conversion
;pbcf ADCON0,GO ;simultation purpose only  
		goto	WAIT1_X
WAIT1_X
		bcf	ADCON0,GO	;simulation purpose only
		btfsc	ADCON0,GO	;Tests GO bit to see if A/D conversion is complete, 1 = In Progress; 0 = Not In Progress
		goto	WAIT1_X		;Wait for conversion to complete

		movf	ADRESH,W	;get conversion high byte
		movwf	AD_X_STORAGE_HIGH  ;store it in AD_X_STORAGE_HIGH
		bcf	STATUS,RP1	;clear bank 2/3
		bsf	STATUS,RP0	;set bank 1
		movf	ADRESL,W	;get conversion low byte
;bcf STATUS,RP0 ;reset bank 0  
		movwf	AD_X_STORAGE_LOW  ;store it in AD_X_STORAGE_LOW
;bcf PIR1,ADIF ;Clear A/D interrupt flag bit   
;bcf ADCON0,GO ;Ensures A/D Cnversion is not in progress.  

		movf	AD_X_STORAGE_HIGH,W  ;Move the results to the output pins
		movwf	PORTA 
		movf	AD_X_STORAGE_LOW,W  ;Move the results to the output pins
		movwf	PORTB
		movlw	b'11111111'
		movwf	DELAY
WAIT_OUTPUT
		decfsz	DELAY, 1
		goto	WAIT_OUTPUT 

		goto	START_MAIN_PROGRAM

;goto SEND_OUTPUT ;Goes to output sending routine  



;END_OUTPUT
;bsf PORTB, OUTPUT 
;goto WAIT_OUTPUT  

;WAIT_OUTPUT 
;decfsz DELAY,F ;Delay for 256 instruction cycles  
;goto WAIT_OUTPUT  
;WAIT_OUTPUT1 
;decfsz DELAY,1 ;Delay for 256 instruction cycles  
;goto WAIT_OUTPUT 

		end
 
Hi, Steve

Code:
movlw b'11000101' ;Bit 7-6 (ADCS<1:0>) sets the clock to be derived from the internal A/D module RC ocsilliator
;Bit 5-3 (CHS<2:0>) Analog select bits. Bit 2 = GO/DONE bit which is the AD/Conversion Status. 
;if ADON=1 and GO/DONE=1, conversion in progress, 0 = not in progress. Bit 1 = unimplemented.
;Bit 0 = AD on bit; 1 = AD is on, 0 = AD is off and consumes no operating current.
movwf ADCON0 ;Move new value into ADCON0 (This is an A/D Control Register @ 1Fh)

movlw b'10000000' ;Bit 7 = AD Format, 1 = Right Justified, 0 = Left justified; Bit 6 = ADSC2 (Clock /2 select, 0 = off)
;Bit 5-4 = VCFG<1:0> = A/D Voltage Reference Config bits, 00 = Vdd as +Vref, and Vss as -Vref
;Bit 3-0 = unimplemented, read as 0
movwf ADCON1 ;Move new value into ADCON1 (This is an A/D Control Register @ 9Fh)

you write to ADCON0 and ADCON1 without any bank switching in between ...

Alain
 
Thank you very much for your responses I will look into all recommendations. Please tell me more about this code tidier...? I am unfamilar with this
 
Hi Again All; I am still having difficulties with my A/D converter on the PIC16F88. As a program summary; I am simply trying to read one analog input (AN0) and convert it to a 10bit word. The digital outputs should be sent to RB0-RB7, RA6 and RA7 (this corresponds to the 10bit output). Currently, when I run MPLAB SIM, The program seems to run fine ((except the GO/DONE bit should only be cleared when the A/D conversion is complete, and with no analog input during simulation, I don't know how the simulator can run all the way through....shouldn't the SIM continue to test the GO/DONE bit forever during simulation because there is no actual input??)). Anyhow, I have 0 errors when I build all. Is there an easier way to look at the 10bit output rather than using sending them to individual output pins?..I'm not sure if I even did that part correct. I am using the internal osc so I can eventually run in sleep mode. nyhow, I have 0 errors when I build all but still get no output after the PIC is burned. Please help! Attached is my code
 

Attachments

  • A_D Conversion Code.asm
    4.6 KB · Views: 160
Alain; I made sure (at least i think i did) to switch to the correct banks for each and every line, and now my output pins read 0V across all. Any other suggestions?

I have attached a cleaner version of the .asm

Thanks in Advance!
 

Attachments

  • A_D Conversion Code.asm
    4.5 KB · Views: 146
If you step through your code with the simulator, you will get the following error.

ADC-W0011: The Go/Done bit must not be set in the same cycle as the Enable bit.

When it executes,
Code:
		movlw	b'11000101'	;Bit 7-6 (ADCS<1:0>) sets the clock to be derived from the internal A/D module RC ocsilliator
		movwf	ADCON0		;Move new value into ADCON0 (This is an A/D Control Register @ 1Fh)
This will prevent the ADC from working correctly as no acquisition time is allowed for. It is also not advisable to switch on the ADC until all ADC registers are setup. You setup ADCON1 after switching the ADC on.

Also, you are using the default internal clock speed of 31.25kHz which is very slow. Try writing 0x70 to OSCCON (bank 1) to switch to 8MHz.

Mike.
 
Last edited:
Pic16f88 adc

Bee- I believe I have my oscilliator turned on correctly...

Pommie- Good Catch, I did what you had suggested and unfortunately I still don't believe the ADC is functioning properly, if any at all. Any other suggestions you can think of? Attached is my .asm
 

Attachments

  • A_D Conversion Code.asm
    4.2 KB · Views: 154
I also just saw this other error : ADC-W0008: No stimulus file attached to ADRESL for A/D. Does anyone know what this implies? How would there be no stimulus file for ADRESL when there is one for ADRESH?
 
Have you had this pic working ie; ports on,off , flashing leds ect
Is the pic doing anything at all when you test it with this code
And what are your connections to this pic
I am just running through what i do when the things dont work,
Just that its not always the code at fault

bee
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top