Proteus仿真PIC18F4580遇栈溢出,LED控制功能异常求助
PIC18F4580 LED控制汇编代码与Proteus仿真问题
问题概述
首次使用MPLAB和Proteus开发PIC18F4580的LED控制程序,遇到两类问题:
- 初始代码仿真时触发栈溢出报错:
[PIC18 STACK] PC=0x000E. Stack overflow is forcing device reset. [U1] - 更新代码后,LED1始终常亮,按下按键后熄灭,但未实现80次高低脉冲效果,LED2也无法点亮
初始代码(触发栈溢出)
;硬件连接要求: ;(a) 按键PB接RD4,按下时RD4=0(低电平),释放时RD4=1(高电平) ;(b) LED1接RC1,RC1=0(低电平)时亮,RC1=1(高电平)时灭 ;(c) LED2接RC2,RC2=1(高电平)时亮,RC2=0(低电平)时灭 ;功能需求:持续监测按键,当按键按下(门打开)时,给LED1发送80次高低脉冲,之后熄灭LED1、点亮LED2;否则保持LED1亮、LED2灭 PORTD EQU 0xF83 PORTC EQU 0xF82 TRISC EQU 0xF94 TRISD EQU 0xF95 Counter EQU 0x20 ;LED1 > RC1 亮:0 灭:1 ;LED2 > RC2 亮:1 灭:0 BSF TRISD, 4 BCF TRISC, 1 BCF TRISC, 2 LoopPB1: MOVLW D'80' MOVWF Counter Call PB1 DECFSZ Counter Call LoopPB1 BSF PORTC, 1 BSF PORTC, 2 return PB1: BCF PORTC, 1 ;置低 BCF PORTC, 1 return BTFSS PORTD, 4 BCF PORTC,1 BRA PB1 RETURN END
更新后代码(逻辑异常)
ORG 0 ;硬件连接与功能需求同初始代码 PORTD EQU 0xF83 PORTC EQU 0xF82 TRISC EQU 0xF94 TRISD EQU 0xF95 Counter EQU 0x20 ;LED1 > RC1 亮:0 灭:1 ;LED2 > RC2 亮:1 灭:0 BSF TRISD, 4 BCF TRISC, 1 BCF TRISC, 2 MOVLW D'80' MOVWF Counter LoopPB1: MOVLW D'80' MOVWF Counter Loopn: BSF PORTC, 1 ;置高 BCF PORTC, 1 DECFSZ Counter, F BRA Loopn BSF PORTC, 2 BSF PORTC, 1 BRA Check Check: BTFSS PORTD, 4 BRA Check BRA LoopPB1 END
问题分析与解决建议
1. 初始代码栈溢出问题
- 原因:
LoopPB1中递归调用自身,每次调用都会占用栈空间,80次递归远超PIC18F4580的栈深度(PIC18系列栈深度通常为31级),直接导致栈溢出触发芯片复位。 - 修复:将递归结构改为循环结构,避免反复占用栈空间。
2. 更新后代码逻辑异常问题
- LED1无脉冲效果:脉冲序列中
BSF PORTC,1后立刻BCF PORTC,1,MCU执行速度极快,肉眼无法分辨电平变化,看起来LED1一直常亮。必须添加延时子程序,让高低电平状态保持足够时长。 - 按键触发逻辑颠倒:
Check段中BTFSS PORTD,4的逻辑错误——该指令是当位为1时跳过下一条,当前逻辑变成按键未按下时死等,按下时才进入脉冲循环,与需求完全相反。 - LED2无法保持点亮:脉冲结束后设置
BSF PORTC,2,但立刻跳回Check,若按键未释放会卡在等待;若释放则重新进入循环重置LED2为低电平,导致LED2无法持续点亮。
修正后的参考代码
ORG 0 PORTD EQU 0xF83 PORTC EQU 0xF82 TRISC EQU 0xF94 TRISD EQU 0xF95 Counter EQU 0x20 ;LED1: RC1=0亮,RC1=1灭 ;LED2: RC2=1亮,RC2=0灭 ;端口初始化 BSF TRISD, 4 ;RD4设为输入(按键) BCF TRISC, 1 ;RC1设为输出(LED1) BCF TRISC, 2 ;RC2设为输出(LED2) MAIN_LOOP: BTFSS PORTD, 4 ;检测按键:未按下(RD4=1)则跳过下一条 BRA DO_PULSES ;按键按下(RD4=0)则执行脉冲序列 ;按键未按下时:LED1亮,LED2灭 BCF PORTC, 1 BCF PORTC, 2 BRA MAIN_LOOP DO_PULSES: MOVLW D'80' MOVWF Counter PULSE_LOOP: ;LED1灭(高电平) BSF PORTC, 1 CALL DELAY ;延时 ;LED1亮(低电平) BCF PORTC, 1 CALL DELAY ;延时 DECFSZ Counter, F BRA PULSE_LOOP ;脉冲完成后:LED1灭,LED2亮 BSF PORTC, 1 BSF PORTC, 2 ;等待按键释放 WAIT_RELEASE: BTFSC PORTD, 4 ;按键仍按下(RD4=0)则跳过下一条,继续等待 BRA MAIN_LOOP ;按键释放(RD4=1)则返回主循环 BRA WAIT_RELEASE ;延时子程序(可根据需求调整延时长度) DELAY: MOVLW 0xFF MOVWF 0x21 DELAY_LOOP1: MOVLW 0xFF MOVWF 0x22 DELAY_LOOP2: DECFSZ 0x22, F BRA DELAY_LOOP2 DECFSZ 0x21, F BRA DELAY_LOOP1 RETURN END
原理图注意事项
- 按键RD4需配置上拉电阻(或启用MCU内部上拉),确保未按下时RD4为高电平,按下时为低电平。
- LED1需串联限流电阻,连接方式为RC1→电阻→LED→GND(符合RC1=0时LED亮的逻辑);LED2连接方式为VCC→电阻→LED→RC2(符合RC2=1时LED亮的逻辑)。
内容的提问来源于stack exchange,提问作者user2253859
相关产品推荐
相关产品推荐

