performance - 如何在 PIC16F1829 上使用所需值退出查找表指令
问题描述
当我在其中包含 ADC 转换时,如何让我的代码正常工作?
我有一个使用 p16f1829 在 2 个 LED 显示器上显示两位数字的工作代码。但是,当我尝试包含一个收集 ADC 转换结果以显示在 LED 显示屏上的代码块时,就会出现问题(见下文)。
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
更准确地说,它似乎发生在我试图从查找表中获取相应值的地方(见下文):
该指令后 W-reg 中的结果应为 0x7D。但是,它退出查找表而不返回预期值。
没有 ADC 模块的原始工作代码如下:
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
我已经尝试了各种方法,目前对如何进行有一个心理障碍。任何人都可以提供的任何见解将不胜感激。
解决方案
推荐阅读
- java - 从 VSCode 使用 Ant 应用程序创建 Java
- python - 如何将 str 的数据框列转换为 float numpy.ndarray?
- laravel - 在 Apache 服务器中部署 Laravel 应用程序和 Vue 不工作
- flutter - Flutter Redux 和 Hook。如何观察 useEffect 中的变量实例变化,如反应?
- google-colaboratory - 为什么我无法在 Colab 中挂载到我的 Google 云端硬盘?
- bit-manipulation - 在 Solidity 中将 uint24 转换为 HEX 字符串
- c++ - 使用递归打印的链接列表问题
- javascript - Div 元素从下到上打开,具有滑动效果,而不是从上到下
- react-native - 首次运行应用程序时的 Expo 问题
- c# - 无法在 .net 中将事件添加到 IPC