问题
How can I get my code to work correctly when I include ADC conversion in it?
I have a working code that displays two digits on 2 LED displays using a p16f1829. However, a problem arises when I try to include a code block that collects the results of an ADC conversion to display on the LED display (see below).
A2D:
; Start the ADC
NOP ; Requried ADC delay of 8uS => (1/(Fosc/4)) = (1/(500KHz/4)) = 8uS
BANKSEL ADCON0 ; Selects memory bank containing ADCON0 register
BSF ADCON0, GO ; Start the ADC
BTFSC ADCON0, GO ; This bit will be cleared when the conversion is complete
GOTO $-1 ; Keep checking the above line until GO bit is clear
; Grab Results and write to the LEDs
SWAPF ADRESH, w ; Get the top 4 MSbs (remember that the ADC result is LEFT justified!)
MOVWF L0
RETURN
To be more precise, it seems to occur at the very point where I am trying to grab the corresponding value from the lookup table (see below):
The result in W-reg after that instruction should be 0x7D. However, it exits the Lookup table without returning the expected value.
The original working code without the ADC block is below:
LIST p=16f1829 ;list directive to define processor
#INCLUDE <p16f1829.inc> ;processor specific variable definitions
__CONFIG _CONFIG1, (_FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF);
__CONFIG _CONFIG2, (_WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _LVP_OFF);
;-------------------------------------------------------------------------
; UDATA_SHR declares a section of shared (all across the banks) uninitialised data
INT_VAR UDATA_SHR ; INT_VAR is the section name in ACCESS RAM
TempC RES 1 ;
L0 RES 1 ;
w_temp RES 1 ; variable used for context saving
pclath_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
;-------------------------------------------------------------------------
LEDtrisA EQU TRISA
LEDtrisC EQU TRISC
LEDlatA EQU LATA
LEDlatC EQU LATC
;-------------------------------------------------------------------------
RESET_VECTOR CODE 0x0000
GOTO START ; When using debug header, ICD2 may not stop
; on instruction 0 during reset.
;-------------------------------------------------------------------------
INT_VECTOR CODE 0x0004 ; Interrupt vector location
ISR ; Relocatable Interrupt Service Routine
; Context saving for ISR
MOVWF w_temp ; save off current W register contents
MOVF STATUS, w ; move status register into W register
MOVWF status_temp ; save off contents of STATUS register
MOVF PCLATH, w ; Saves value in register PCLATH
MOVWF pclath_temp
;-------------------------------------------------------------------------
; If the interrupt came from the timer, execute the TMR0 interrupt
; service routine.
BANKSEL TMR0
MOVLW .96
MOVWF TMR0
BTFSC INTCON, TMR0IF
CALL Service_TMR0
BRA UpdateDisplay ; Refresh the display
UpdateDisplay
BANKSEL LATA ; Selects memory bank containing LATA register
MOVF LEDlatA, w ; display status -> w register
ANDLW 0x0f ; Separate the lower half byte
MOVWF TempC ; Save display status in TempC
BSF TempC, 4 ; Beginning status of LSD display
RRF TempC, F ; Set the status of the next display
BTFSS STATUS, C ; C = 1?
BCF TempC, 3 ; If not, turn off the LSD display
BTFSC TempC, 0
BRA UpdateMsd ; If it is turned on, display the MSD
; digit of the number
UpdateLsd
BCF TempC, 3
BSF TempC, 1
BTFSS STATUS, Z ; If it is, skip
MOVF L0, w ; Third LSD digit -> w
ANDLW 0x0f ; /
BRA DisplayOut ; Show it on the display
UpdateMsd
SWAPF L0, w ; MSD figure - >
ANDLW 0x0f ; /
BTFSC STATUS, Z ; MSD = 0?
MOVLW 0x0a ; If it is, skip
DisplayOut
CALL LedTable ; Take the mask for a digit
MOVWF LEDlatC ; Set the mask on port B
MOVF TempC, W ; Turn on displays
MOVWF LEDlatA
BRA ISR_END
LedTable
ADDWF PCL, F
RETLW B'00111111' ; mask for digit 0
RETLW B'00000110' ; mask for digit 1
RETLW B'01011011' ; mask for digit 2
RETLW B'01001111' ; mask for digit 3
RETLW B'01100110' ; mask for digit 4
RETLW B'01101101' ; mask for digit 5
RETLW B'01111101' ; mask for digit 6
RETLW B'00000111' ; mask for digit 7
RETLW B'01111111' ; mask for digit 8
RETLW B'01101111' ; mask for digit 9
RETLW B'00000000' ; no digit ......
;-------------------------------------------------------------------------
ISR_END
; Restore contents before returning from interrupt
MOVF pclath_temp,w ; PCLATH is given its original content
MOVWF PCLATH
MOVF status_temp,w ; STATUS is given its original content
MOVWF STATUS
SWAPF w_temp,f ; W is given its original content
SWAPF w_temp,w
BSF INTCON,GIE ; Global interrupt enabled
RETFIE ; Return from interrupt routine
;-------------------------------------------------------------------------
MAIN_PROG CODE
START
;-------------------------------------------------------------------------
ERRORLEVEL -302 ; Disable warning accessing register not in bank 0
BANKSEL OSCTUNE ; Configure OPTION_REG and TMR0
MOVLW 0x00 ; Set oscillator to factory calibrated frequency
MOVWF OSCTUNE ;
BANKSEL STATUS
ERRORLEVEL +302 ; Enable warning accessing register not in bank 0
CLEAR_RAM ; code sequence initialises all GPR's to 0x00
MOVLW 0x70 ; initialise pointer
MOVWF FSR0 ; to RAM
CLRF FSR0H
NEXT
CLRF INDF0 ; Clear INDF0 register
INCF FSR0L, F ; Inc pointer
BTFSS FSR0L, 7 ; All done?
GOTO NEXT ; No, clear NEXT
CONTINUE ; Yes, CONTINUE
NOP
;-------------------------------------------------------------------------
; MAIN BODY OF PROGRAM
;-------------------------------------------------------------------------
; Setup main init
BANKSEL OSCCON ; Selects memory bank containing OSCCON register
MOVLW b'01011000' ; Set CPU clock speed of 500KHz -> correlates to (1/(500K/4)) for each instruction
MOVWF OSCCON ; OSCCON <- 0x38
; Setup pins as digital I/O
BANKSEL ANSELA ; Selects memory bank containing ANSELA register
CLRF ANSELA ; All pins are digital
CLRF ANSELC
; Configure the input & output pins
BANKSEL TRISA ; Selects memory bank containing TRISA register
MOVLW b'11111100' ; RA0 and RA1 are configured as outputs and
; used for 7-segment display multiplexing
; RA2 is input push-button for initialization
MOVWF TRISA
CLRF LEDtrisC ; Port C is output
BANKSEL LATA ; Selects memory bank containing LATA register
CLRF LEDlatA ; Set all outputs to "0"
CLRF LEDlatC ;
BSF LEDlatA, 1 ; Turn on MSD display
; Setup Timer0 as the delay
BANKSEL OPTION_REG
MOVLW b'10000100' ; TMR0 is incremented each 32us (Fclk=8MHz)
MOVWF OPTION_REG ; ps = 32
BANKSEL TMR0 ; Selects memory bank containing TMR0 register
BSF INTCON, GIE ; Global interrupt enabled
BSF INTCON, TMR0IE ; Timer TMR0 interrupt enabled
MOVLW 0x79
MOVWF L0
MAINLOOP
BRA MAINLOOP ; Continue forever
; TIMER 0 Interrupt routine clears the TMR0 interrupt flag.
Service_TMR0:
BANKSEL INTCON
BCF INTCON, TMR0IF ; MUST ALWAYS clear this in software or else stuck in the ISR forever
RETURN
;-------------------------------------------------------------------------
; END OF PROGRAM
;-------------------------------------------------------------------------
END ; End of program
I have tried all sorts and have currently a mental block on how to proceed. Any insights that anyone can provide will be very much appreciated.
来源:https://stackoverflow.com/questions/65621679/how-can-i-exit-my-lookup-table-instruction-with-the-desired-value-on-pic16f1829