我用汇编语言为avr atmega328P编写了这段代码。它使用按钮来打开和关闭LED,但在Proteus中我得到了以下错误:
PC=0x002A上的操作码0xFFFF无效
这是我的代码:
.INCLUDE "M328Pdef.inc"
ldi r16,HIGH(RAMEND)
out SPH, R16
ldi r16,LOW(RAMEND)
out SPL, R16
start:
ldi r16,0xFF
out DDRB,r16
ldi r17,0x00
out DDRD,r17
ldi r21,0x00
ldi r23,0x01
Forever:
in r20,PIND
cp r20,r21
BREQ ledon
cp r20,r23
BREQ ledoff
rjmp Forever
ledon:
ldi r22,0x01
out PORTB,r22
ret
ledoff:
ldi r24,0x00
out PORTB,r24
ret
有没有人能解决这个问题?
1条答案
按热度按时间gupuwyp21#
问题就在这里:
你分别分支到
ledon
和ledoff
,这只是一个条件跳转,但是在各个块的末尾,你使用的是ret
,就好像你通过[r]call
调用代码一样。ret
将从堆栈中弹出2个字节,并将这些字节用作要返回的字地址。代码目标很可能具有未初始化的闪存,该闪存保存0xff,并且两个0xff是0xffff,这不是法律的的AVR操作码。0x002a是发出非法跳转的最后一个ret
的字节地址。要解决这个问题,您可以使用
rjmp Forever
而不是ret
,但这取决于您希望使用代码实现什么。