assembly 为什么sbi会导致位切换?

pxiryf3j  于 2023-01-17  发布在  其他
关注(0)|答案(2)|浏览(104)

考虑以下AVR汇编代码:

blink:
  sbi   PINA, 0     ; Toggle PINA
  jmp   blink

根据文档,这应该设置端口A上的位0,然而,此代码实际上会导致该位切换。
为什么会这样?

pzfprimi

pzfprimi1#

为什么?因为硬件布线就可以了。让我们看看IO引脚是如何实现的。x1c 0d1x
在这里,您可以看到每个引脚的逻辑图。输出值由PORTA寄存器中的D触发器驱动。DDRA寄存器使能输出值到引脚。PINA是同步器中的第二个D触发器。PINA读取此触发器中的值。正如您所看到的,写入PIN(WPx信号)连接到多路复用器,该多路复用器为PORTA输出触发器选择输入信号。在写入一个的情况下,该多路复用器被切换到连接输出值反相状态的上部信号。同时,生成PORTA触发器的clk脉冲。结果是PORTA改变其逻辑值。
sbi PINA, 0指令不触发PINA,但触发PORTA。PINA始终在一个CPU时钟周期后跟随引脚上的信号。
如果要设置PORTA的位0,必须使用SBI PORTA, 0
I/O端口的详细说明

nimxete2

nimxete22#

为什么会这样?
因为这是它在较新的AVR设备上的工作方式:您可以通过对PIN寄存器进行SBI-ing来切换端口引脚。ATmega88就是一个例子,而较老的ATmega8只是在PIN中设置一个位。
优点是允许原子地切换端口引脚,而传统的IN-XOR-OUT不是原子的,速度更慢,消耗更多的闪存。要使其原子化,你必须(暂时)禁用IRQ。
参见ATmega48/88/168的示例数据手册,第13节I/O端口:

    • 13.2.2切换引脚**

向PINxn写入逻辑1可切换PORTxn的值,与DDRxn的值无关。请注意,SBI指令可用于切换端口中的一个位。

相关问题