我正在为一个课程做一个项目,我必须在汇编中编写一些程序,我正在使用PIC 16F887,我知道它有一个8级堆栈,我找不到为什么/在哪里我会在它上面。
代码看起来像这样:
targ_temp EQU 0x20
CONT1 EQU 0x20
CONT2 EQU 0x21
TTEMPU EQU 0x22
TTEMPD EQU 0X23
aux EQU 0X24
FLAGS EQU 0X25
TEMPU EQU 0X26
TEMPD EQU 0X27
PESO EQU 0X28
CONT EQU 0X30
;**********************************************************************
ORG 0x000
goto main
ORG 0x004
BTFSC INTCON,2
CALL TIMEROVERFLOW
BTFSC INTCON,1
CALL SENSORVASO
BTFSC INTCON,0
CALL LEERTECLADO
BTFSC PIR1,6
CALL CONVERSOR
;BTFSC PIR1,5
;CALL EUSARTRECIEVE
;BTFSC PIR1,4
;CALL EUSARTTRANSMIT
// clearing flags
retfie ; return from interrupt
main
//setup
GOTO $
LEERTECLADO ;polling the keypad
call DELAY
movlw 0x0F
iorwf PORTC,1
MOVLW 0XFF ;I use this to check at the end if a button is actually pressed, or if it was let go/pressed some other key that I'm not mapping
BCF PORTC,3
BTFSS PORTB,7 ;<- this is where the stack overflow originates from
movlw 0x1
BTFSS PORTB,6
movlw 0x2
BTFSS PORTB,5
movlw 0x3
BTFSS PORTB,4
goto tempres
clrf PORTC
bsf PORTC,3
bcf PORTC,2
BTFSS PORTB,7
movlw 0x4
BTFSS PORTB,6
movlw 0x5
BTFSS PORTB,5
movlw 0x6
BTFSS PORTB,4
goto tempset
clrf PORTC
BSF PORTC,2
BCF PORTC,1
BTFSS PORTB,7
movlw 0x7
BTFSS PORTB,6
movlw 0x8
BTFSS PORTB,5
movlw 0x9
clrf PORTC
BSF PORTC,1
BCF PORTC,0
BTFSS PORTB,6
movlw 0x0
BCF PORTC,3
BCF PORTC,2
BCF PORTC,1
BCF PORTC,0
addlw 0x1 ;here I check if w overflows, if it does it means no buttons were pressed
btfsc STATUS,2 ;
goto term ;
sublw 0x1 ;if it didn't overflow I bring it back to the original value
movwf aux
movf TTEMPU,0
movwf TTEMPD
movf aux,0
movwf TTEMPU
goto term
tempset movlw 0X26
movwf FSR
BCF PORTA,7
BSF PORTA,6
BCF STATUS,7
BCF STATUS,6
goto term
tempres clrf TTEMPU
clrf TTEMPD
MOVLW 0x22
movwf FSR
BCF PORTA,7
BSF PORTA,6
BCF STATUS,7
BCF STATUS,6
term return
CONVERSOR
BTFSC FLAGS,6
GOTO SERV
CLRF TEMPD
CLRF TEMPU
MOVLW .25
adec SUBWF ADRESH,1
INCF TEMPD,1
BTFSC STATUS,0
GOTO over
BTFSS STATUS,2
GOTO adec
GOTO tempter
over DECF TEMPD,1
ADDWF ADRESH,1
MOVLW .10
SUBWF TEMPD,0
BTFSC STATUS,2
GOTO cien
MOVLW .3
aun SUBWF ADRESH,1
INCF TEMPU,1
BTFSC STATUS,0
GOTO overun
BTFSS STATUS,2
GOTO aun
GOTO tempter
overun DECF TEMPU,1
GOTO tempter
cien MOVLW .10
MOVWF TEMPD
CLRF TEMPU
BCF PORTA,4
GOTO FINADC
tempter MOVF TEMPD,0
SUBWF TTEMPD,0
BTFSC STATUS,0
GOTO apagar
BTFSS STATUS,2
GOTO mant
MOVF TEMPU,0
SUBWF TTEMPU,0
BTFSC STATUS,0
GOTO apagar
BTFSS STATUS,2
GOTO apagar
mant BSF PORTA,4
BCF FLAGS,7
GOTO FINADC
apagar BCF PORTA,4
BSF FLAGS,7
GOTO FINADC
SERV
MOVLW PESO
SUBWF ADRESH,0
BTFSC STATUS,0
GOTO VLLENO
BTFSS STATUS,2
GOTO VLLENO
GOTO FINADC
VLLENO BCF FLAGS,6
BCF PORTA,5
BCF ADCON0,3
INCF CONT,1
MOVFW CONT
BANKSEL TXREG
MOVWF TXREG
BSF TXSTA,5
BANKSEL CONT
FINADC BSF ADCON0,1
RETURN
SENSORVASO
call DELAY
BTFSS FLAGS,7
GOTO ENDVASO
BSF PORTA,5
BSF FLAGS,6
BSF ADCON0,3
ENDVASO return
TIMEROVERFLOW
btfsc PORTA,7
goto inver
incf FSR,1
movf INDF,0
call TABLA
movwf PORTD
BCF PORTA,6
BSF PORTA,7
goto termi
inver
DECF FSR,1
movf INDF,0
call TABLA
movwf PORTD
BCF PORTA,7
BSF PORTA,6
termi
return
TABLA
ADDWF PCL,F
RETLW b'11111100' ;devuelve 0
RETLW b'01100000' ;1
RETLW b'11011010' ;2
RETLW b'11110010' ;3
RETLW b'01100110' ;4
RETLW b'10110110' ;5
RETLW b'10111110' ;6
RETLW b'11100000' ;7
RETLW b'11111110' ;8
RETLW b'11110110' ;9
RETLW b'11111010' ;.0
DELAY ;delay routine mainly for debouncing
movlw .3
movwf CONT2
ext
movlw .250
movwf CONT1
int
decfsz CONT1,1
goto int
decfsz CONT2,1
goto ext
return
END
请原谅西班牙语的标签,我得到一个堆栈溢出警告时模拟在proteus和触摸按钮连接RB7和RC3,也实现了它在一个试验板和有(我相信)同样的事情发生,这意味着从我可以看到的显示停止切换,只有一个会卡住与相同的值显示无论我做了什么。
我正在使用proteus检查一切是否按照预期工作,然后将其移动到董事会,直到我遇到这个。它启动的确切错误是:[PIC16 CORE] PC = 0x00E9。执行CALL指令的堆栈溢出。[U1]我尝试使用异步刺激在MPLAB X上进行调试,我逐行跟踪代码,它按预期工作。我在另一个论坛上读到的一件事是,tabla中添加的值(将其添加到pc)可能是负的,它可能会以这种方式进入另一个调用并溢出,但我看不到这里发生,因为它是中断上的一段代码,所以它不能被缩短,它要么放置一个0 - 9之间的值,要么返回。我会留下一些我认为没有必要的代码,但可能有什么我没有看到。我不知道该怎么办
2条答案
按热度按时间xnifntxz1#
堆栈溢出发生在
TIMEROVERFLOW
函数/例程中,我不能证明为什么,但使用指针和间接寻址发送了一个错误的W reg值调用TABLA,这导致pc去了它不应该去的地方,即使我在设置中初始化值为0。我用一个标志替换了这个例程,它检查我试图显示的内容,而不是依赖于指针,这样我就不会再出现堆栈溢出。ffvjumwh2#
是的,看起来你只使用了三个级别(中断本身,对特定处理函数的调用,以及其中一些对延迟的调用)(1)。
我所能建议的是,首先找出哪段代码位于
0x00e9
,即堆栈溢出错误消息中列出的地址。这可能会提供一个线索。然后,也许在
TABLA
的开头放置一些保护代码,以便它只对特定的可接受值进行添加。如果没有,请执行其他操作,例如选择默认值或输入另一个无限循环(如main: goto $
循环)。希望您可以通过地址总线上永不改变的PC来获取它。在我看来,这似乎是唯一一个在你正常(三级)途径之外的召唤载体。例如,
addw pcl, f
* 可能 * 最终有效地跳回到中断例程中的某个地方,并再次调用其中一个处理函数。这样做几次,砰,你的堆栈耗尽了。根据模拟器的性能,您可以跟踪程序计数器的每个值并查看它的去向。
(1)在线调试器可能会增加另一个级别,但这 * 仍然 * 只有4个,远远低于
16F877
的8个限制。