Переполнение стека в микроконтроллере Pic16F684 при использовании таблиц поиска


Моей задачей было разработать программу, которая будет мигать светодиодами от D7 до D0.
У меня есть решение, которое мигает один раз, а затем происходит переполнение стека.
Я с подозрением отношусь к таблицам поиска, потому что ранее я сталкивался с ошибкой при последней конфигурации TRISA (теперь прокомментировано). Я вставляю код.

    ;*********************************************************************************
; Filename: Pic_demonstration.asm -it should be!
; Author:   Alexander Drabek
; Date:     01.05.13
; Description:  This Assembler program for PIC16F684 turns ON and OFF LEDs from D7 to D0
;               with a delay of 0.5 second
;Check if trisa reaching the 4th and PORTA eight leds.
;To report:
;1.separate PCL in Bank1 and Bank0
;2.Lookup table and undaestanding of options of the code.
;3.we are assuming to work in Bank0
;4.overflow.
    list     p=16F684       ; List directive to define processor
    #include <p16f684.inc>  ; Processor specific variable definitions
    __CONFIG  _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CPD_OFF
;****************************** Assignment Statements ****************************
;Delay counters
    COUNT1 EQU 20h  ; Store COUNT1 at address 20h
    COUNT2 EQU 21h  ; Store COUNT2 at address 21h
    normal EQU 22h  ; Store normal at address 22h - responsible for general loop(4 times change trisa)
    COUNT3 EQU 26h ; another counter to make more delay 
;Loops counters
    PORTA_Internal EQU 23h       ;Store PORTA_Internal at address 21h
    COUNT_LED_NUMBER EQU 24h    ; Store COUNT_LED_NUMBER at address 21h
    COUNT_TRISA_NUMBER EQU 25h  ; Store COUNT_TRISA_NUMBER at address 21h
;****************************** "Start" of Program ******************************
; Initial configuration 
;errorlevel -302 ; Disable bank switch warning 
        org     0x000       ; Processor reset vector
        bcf     STATUS,RP0  ; Bank 0 selected
        movlw   07h         ; Set RA<2:0> to digital and 
        movwf   CMCON0      ; Comparators turned OFF
        bsf     STATUS,RP0  ; Bank 1 selected
        clrf    ANSEL       ; Digital I/O selected
        movlw   B'00111111' ; Move in W - 0x3F - Set all I/O pins as digital inputs
        movwf   TRISA       ; Configure I/O ports       
        clrf    INTCON      ; Disable all interrupts, clear all flags   
        bcf     STATUS,RP0  ; Bank 0 selected
        clrf    PORTA       ; Clear all outputs
;*********************************************************************************
; Load values for counters . 
AGAIN;reset the value 
        movlw   B'11101010'         ; First load a value of say, F0h in the W register
        movwf   COUNT2      ; Now move it to COUNT2 register
        movlw   0x03;       ; First load a value of say, F0h in the W register
        movwf   COUNT3      ; Now move it to COUNT2 register
        movlw   B'00000100' ; Load a value 4, in the W register
        movwf   normal      ; Move it to normal
        movlw   B'00000010' ; First load a value of say, 1 in the W register
        movwf   PORTA_Internal  ; Now move it to PORTA_Internal
        movlw   B'00000000'     ; First load a value of say, 1 in the W register
        movwf   COUNT_LED_NUMBER    ; Now move it to COUNT2 register
        movlw   B'00000000'         ; First load a value of say, 1 in the W register
        movwf   COUNT_TRISA_NUMBER  ; Now move it to COUNT2 register
        goto start_loop 
;********************************************************************************
;*********************************************************************************

Lookup_PORTA    
             movlw  low TablePORTA
             ADDWF  COUNT_LED_NUMBER,0                   
             movwf  PCL                 ; Jump to specified entry
TablePORTA   RETLW B'00000010'  ; Sending HIGH to D7 -ok
             RETLW B'00000100'  ; Sending HIGH to D6 -ok
             RETLW B'00000100'  ; Sending HIGH to D5 -ok
             RETLW B'00100000'  ; Sending HIGH to D4 -ok
             RETLW B'00000100'  ; Sending HIGH to D3 -ok
             RETLW B'00010000'  ; Sending HIGH to D2 -ok
             RETLW B'00100000'  ; Sending HIGH to D1 -ok
             RETLW B'00010000'  ; Sending HIGH to D0 -OK--------
Lookup_TRISA    
             movlw  low TableTRISA 
             ADDWF COUNT_TRISA_NUMBER,0                
             movwf  PCL                             ; Jump to Specified entry   ;     RETLW B'00111001'; 57    - overflow!      
TableTRISA   RETLW B'00011011'; 27-DECIMAL    ; Element 0 of lookup table
             RETLW B'00101011'; 43-DECIMAL  ; Element 1 of lookup table
             RETLW B'00001111'; 15-DECIMAL          ; Element 2 of lookup table                     
;it is always loading first one of eac lookup tables!
;*********************************************************************************
start_loop      
    ;Temporary solution for overflow 
             bsf    STATUS,RP0      ; Bank 1 selected
             movlw   B'00111001'        ; TRISA for D6 and D7
             movwf  TRISA
             bcf    STATUS, RP0 ; Bank 0 selected
             call   DELAY
             CALL   Lookup_PORTA  ; Call the table. -it should obtain the address for next memory cell with PORTA config
             movwf  PORTA       ;light this diod!
             call   DELAY       ; for a half second                 
             clrf   PORTA       ;  Clear PORTA 
             incfsz COUNT_LED_NUMBER,1 ;increase LED NUmber! save into variable!
             call   DELAY
             CALL Lookup_PORTA  ; Call the table. -it should obtain the address for next memory cell with PORTA config
             movwf  PORTA       ;light this diod!
             call   DELAY       ; for a half second                 
             clrf   PORTA       ;  Clear PORTA 
             incfsz COUNT_LED_NUMBER,1
;end of temporary solution
ITERNAL_TRISA_LOOP ;Change the trisa after 2 diods ,do it till end of lookup table
             CALL Lookup_TRISA  ; Call the table. -it should obtain the address for next memory cell with trisa config
             bsf  STATUS,RP0    ;Bank 1
             movwf TRISA        ;Move config to TRISA
             bcf STATUS, RP0    ;Reset bank to 0 
             decfsz normal,1    ;Decrease the number of posible configuration in this iteration value of 5 -Not sure --it will omit las one (option 4)
             goto INTERNAL_LOOP_2DIODS ; Blink 2 diods including delays
             goto AGAIN ; 

INTERNAL_LOOP_2DIODS  ;develop the delay ! +TRISA CHANGE
             bcf    STATUS, RP0 ; 
             call   DELAY
             CALL Lookup_PORTA  ; Call the table. -it should obtain the address for next memory cell with PORTA config
             movwf  PORTA       ;light this diod!
             call   DELAY       ; for a half second                 
             clrf   PORTA       ;  Clear PORTA 
             incfsz COUNT_LED_NUMBER,1 ;increase LED NUmber! save into variable!
             decfsz PORTA_Internal,1 ; it should have value of 2 XD
             goto INTERNAL_LOOP_2DIODS ; only 1 repeat!
             incfsz COUNT_TRISA_NUMBER,1 ;increase the TRISA config number
             movlw  B'00000010'         ; First load a value of say, 1 in the W register
             movwf  PORTA_Internal  ; Now move it to COUNT2 register
             goto  ITERNAL_TRISA_LOOP      ;- Loop forever -
goto AGAIN
;*********************************************************************************
; DELAY Subroutine
;*********************************************************************************
; Generate a delay period
DELAY
LOOP1   decfsz   COUNT1,1   ; Decrement COUNT1 and skip next instruction if zero
        goto     LOOP1      ; else loop back to LOOP1
        decfsz   COUNT2,1   ; Decrement COUNT2 and skip next instruction if zero
        goto     LOOP1      ; else loop back to LOOP1
        decfsz   COUNT3,1   ; Decrement COUNT1 and skip next instruction if zero
        goto     LOOP1      ; else loop back to LOOP1
        movlw    0x03       ; Reload the second counter for the next iteration
        movwf    COUNT3     ; Decrement COUNT3 and skip next instruction if zero
        movlw    0xF0       ; Reload the second counter for the next iteration
        movwf    COUNT2
        return              ; else loop back to LOOP1

;*********************************************************************************
        end
;*********************************************************************************


Кто-нибудь знает, что может быть не так? Во время отладки значение для каждого счетчика кажется мне приемлемым.
Я пытался искать помощь, но я совершенно новичок в программировании на ассемблере.


person Alex    schedule 02.05.2013    source источник


Ответы (1)


Ваша процедура таблицы поиска goto сделана неправильно! Установите PCLATH перед использованием вычисляемого перехода. Нравиться:

Lookup_PORTA    
        movlw  high TablePORTA
        movwf  PCLATH
        movlw  low TablePORTA
        ADDWF  COUNT_LED_NUMBER,0                   
        movwf  PCL                 ; Jump to specified entry
TablePORTA   
        RETLW B'00000010'  ; Sending HIGH to D7 -ok
        RETLW B'00000100'  ; Sending HIGH to D6 -ok
        ...

И убедитесь, что таблица TablePORTA находится внутри 256-байтовой страницы.

person GJ.    schedule 03.05.2013