Как правильно очистить оперативную память при использовании косвенной адресации с помощью PIC16F1829

#debugging #assembly #microcontroller #pic #microchip

#отладка #сборка #микроконтроллер #рис #микросхема

Вопрос:

Как вы очищаете оперативную память и правильно инициализируете регистр FSR0 при использовании косвенной адресации с PIC16F1829?

Код работает. Моя проблема в том, что при отладке переменные (т. Е. Delay1 и Delay2 в данном случае), значения которых должны храниться по адресам 0x70 и 0x71, сохраняются в 0x120 и 0x121 соответственно, несмотря на регистр FSR0, содержащий адрес 0x70.

введите описание изображения здесь

Я не знаю, что я пропустил, так как существует не так много примеров использования 16-битного регистра FSR. Поэтому любая помощь, которую кто-либо может оказать, будет очень признательна.

 LIST        p=16f1829   ;list directive to define processor
#INCLUDE    <p16f1829.inc>  ;processor specific variable definitions

 __CONFIG _CONFIG1, (_FOSC_INTOSC amp; _WDTE_OFF amp; _PWRTE_OFF amp; _MCLRE_OFF amp; _CP_OFF amp; _CPD_OFF amp; _BOREN_ON amp; _CLKOUTEN_OFF amp; _IESO_OFF amp; _FCMEN_OFF);
 __CONFIG _CONFIG2, (_WRT_OFF amp; _PLLEN_OFF amp; _STVREN_OFF amp; _LVP_OFF);
 

;————————————————————————-

 ; UDATA declares a section of uninitialised data
VARIABLES   UDATA       ; VARIABLES is the name of the section of memory
Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.


;-------------------------------------------------------------------------
; RESET VECTOR
;-------------------------------------------------------------------------

RESET_VECTOR    CODE    0x0000
    GOTO    START   

;-------------------------------------------------------------------------
; INTERRUPT SERVICE ROUTINE
;-------------------------------------------------------------------------

INT_VECTOR  CODE    0x0004  ; Interrupt vector location
    GOTO    START

;-------------------------------------------------------------------------
; MAIN PROGRAM
;-------------------------------------------------------------------------

MAIN_PROG   CODE

START

;-------------------------------------------------------------------------
; SET OSCILLATOR TO FACTORY FREQUENCY AND CLEAR GPR's
;-------------------------------------------------------------------------

    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 to RAM
    MOVWF   FSR0L
    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

;-------------------------------------------------------------------------
; REMAINDER OF PROGRAM 
;-------------------------------------------------------------------------
; Setup main init
    BANKSEL OSCCON          ; Selects memory bank containing OSCCON register 
    MOVLW   b'00111000'     ; Set CPU clock speed of 500KHz -> correlates to (1/(500K/4)) for each instruction
    MOVWF   OSCCON          ; OSCCON <- 0x38

; Configure the LEDs        
    BCF     TRISC,0             ; Make I/O Pin C0 an output for DS1
    
    BANKSEL LATC            ; Selects memory bank containing LATC
    CLRF    LATC            ; Start by turning off all of the LEDs

MAINLOOP:
    BSF LATC, 0         ; Turn LED on
 
ONDELAYLOOP:
    DECFSZ  Delay1,f        ; Waste time.
    BRA     ONDELAYLOOP     ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions
    DECFSZ  Delay2,f        ; The outer loop takes an additional 3 instructions per lap * 256 loops
    BRA     ONDELAYLOOP     ; (768 3) * 256 = 197376 instructions / 125K instructions per second = 1.579 sec.
    BCF     LATC,0          ; Turn off LED C0 - NOTE: do not need to switch banks with 'banksel' since bank2 is still selected

OFFDELAYLOOP:
    DECFSZ  Delay1,f        ; same delay as above
    BRA     OFFDELAYLOOP
    DECFSZ  Delay2,f
    BRA     OFFDELAYLOOP
    BRA     MAINLOOP        ; Do it again...

;-------------------------------------------------------------------------
; END OF PROGRAM
;-------------------------------------------------------------------------

    END         ; End of program
 

Ответ №1:

Ответ заключается в том, что ваш код:

 ; UDATA declares a section of uninitialised data
VARIABLES   UDATA       ; VARIABLES is the name of the section of memory
Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.
 

Сообщает ассемблеру поместить их в накопительную память.

Для размещения данных в общей (не привязанной) памяти используйте этот синтаксис с MPASM:

 ; UDATA_SHR declares a section of uninitialised data common to all banks
VARIABLES   UDATA_SHR   ; VARIABLES is the name of the section of memory
Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.
 

Комментарии:

1. Большое спасибо за это. Я весь день рвал на себе волосы, пытаясь понять, что я поступил неправильно, и хотя я знал об общих переменных, мне никогда не приходило в голову объявлять их такими. Для пояснения, существуют ли какие-либо другие различия между объявлением переменных в UDATA и UDATA_SHR, помимо только что усвоенного урока?

2. @aLoHa, самое главное, что общая (общая) оперативная память мала. Для PIC16F1829 это 16 байт, 15 байт при использовании внутрисхемной отладки, поскольку для инструмента ICD требуется одно общее местоположение ОЗУ для сохранения контекста для точек останова.