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
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