Proteus仿真报错:Invalid opcode 0xFFFF at PC=0x8C02 求助
Proteus仿真错误排查:
Invalid opcode 0xFFFF at PC=0x8C02 运行Proteus仿真时出现错误提示:Invalid opcode 0xFFFF at PC=0x8C02,附上我的AVR汇编代码和电路图,请求排查问题:
我的AVR汇编代码
START: LDI R18, 0XFF OUT DDRB, R18 //LET PORT B AS OUTPUT LDI R16, 0B01110101 OUT TCCR0A, R16 LDI R17, 0B01110101 OUT TCCR0B, R17 LDI R24, 0XFF OUT DDRD, R24 // LET PORT AS INPUT OUT OCR0A, R18 MAIN: IN R18, PINB //LOAD PORT B TO R18 CPI R18, 0B00000000 //CHECK IF R18 == 0 BREQ SPEED1 // JUMP TO SPEED1 IF R18 == 0 OUT OCR0A, R16 OUT OCR0B, R17 IN R18, PINB //LOAD PORTB TO R18 CPI R18, 0B00000001 //CHECK IF R18 == 1 BREQ SPEED2 // JUMP TO SPEED2 IF R18 == 1 OUT OCR0A, R16 OUT OCR0B, R17 IN R18, PINB //LOAD PORTB TO R18 CPI R18, 0B00000010 //CHECK IF R18 == 2 BREQ SPEED3 // JUMP TO SPEED3 IF R18 == 2 OUT OCR0A, R16 OUT OCR0B, R17 IN R18, PINB //LOAD PORTB TO R18 CPI R18, 0B00000011 //CHECK IF R18 == 1 BREQ SPEED4 // JUMP TO SPEED4 IF R18 == 3 OUT OCR0A, R16 OUT OCR0B, R17 RJMP MAIN SPEED1: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 255 RET SPEED2: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 180 RET SPEED3: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 100 RET SPEED4: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 0 RET
我的Proteus电路图

问题排查与修正
1. 核心错误:RET指令误用
这是触发Invalid opcode错误的直接原因:
- 你通过
BREQ跳转指令进入SPEED1-SPEED4代码块,但这些代码块末尾用的是RET指令。 RET是子程序返回指令,必须配合CALL使用(CALL会把当前PC值压入堆栈,RET再弹出恢复PC)。而BREQ只是直接跳转,没有压栈操作,执行RET时会从堆栈读出无效值(0xFFFF),导致PC指向无效内存,触发错误。
修正方法:把所有RET替换成RJMP MAIN,直接跳回主循环。
2. 其他逻辑/注释错误
- DDRD注释矛盾:代码中
OUT DDRD, R24设置R24为0xFF(输出模式),但注释写的是LET PORT AS INPUT,如果PORTD是输入,应设置DDRD为0x00;如果是输出,修正注释即可。 - SPEED4判断注释错误:
CPI R18, 0B00000011是判断R18是否等于3,但注释写的是CHECK IF R18 == 1,需修正注释为CHECK IF R18 == 3。 - MAIN循环冗余代码:每次判断后都重复执行
OUT OCR0A, R16和OUT OCR0B, R17,这些代码仅在不触发跳转时执行,可优化结构(比如把输出放在所有判断之后)。 - Timer0配置合理性:TCCR0A和TCCR0B都设置为
0B01110101,对应快速PWM模式(WGM0[2:0]=111),CS0[2:0]=101对应1024分频,需确认是否符合你的PWM输出需求。
修正后的示例代码
START: LDI R18, 0XFF OUT DDRB, R18 // PORT B 设置为输出 LDI R16, 0B01110101 OUT TCCR0A, R16 LDI R17, 0B01110101 OUT TCCR0B, R17 LDI R24, 0XFF OUT DDRD, R24 // PORT D 设置为输出(修正注释) OUT OCR0A, R18 MAIN: IN R18, PINB // 读取PORT B状态到R18 CPI R18, 0B00000000 // 判断是否等于0 BREQ SPEED1 CPI R18, 0B00000001 // 判断是否等于1 BREQ SPEED2 CPI R18, 0B00000010 // 判断是否等于2 BREQ SPEED3 CPI R18, 0B00000011 // 判断是否等于3(修正注释) BREQ SPEED4 // 所有判断不触发时,更新OCR0值 OUT OCR0A, R16 OUT OCR0B, R17 RJMP MAIN SPEED1: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 255 RJMP MAIN // 替换RET,跳回主循环 SPEED2: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 180 RJMP MAIN SPEED3: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 100 RJMP MAIN SPEED4: LDI R16, 0B00000001 OUT PORTD, R16 LDI R17, 0 RJMP MAIN
内容的提问来源于stack exchange,提问作者acemal9
相关产品推荐
相关产品推荐

