我对如何使用 ATSAM3X8E 上的寄存器感到困惑。例如,在PIO 的中,几乎所有东西都有两个寄存器。
例如,有PIO_PER
和PIO_PDR
寄存器用于启用和禁用 PIO 寄存器。那么,如果我想启用 GPIO 线路 1,我应该同时设置和取消设置这两个寄存器吗,还是只需设置PIO_PER
就足够了?
启用
PIO_PER = (1U << 1);
或者
PIO_PER = (1U << 1);
PIO_PDR = ~(1U << 1);
另外,两者的顺序重要吗?拥有两个独立的寄存器的目的是什么?
\endgroup
最佳答案
2
如果要启用某个引脚,则将要启用的引脚写入位 1。位 0 不执行任何操作。
因此,您使用单一启用的示例是可以的。
根据您想要执行的操作,您的第二个启用可能完全错误。
第一行只启用您想要的位。第二行禁用除您刚刚启用的引脚之外的所有其他引脚。这可能是您想要的,也可能不是,但它将禁用所有其他引脚。顺序本身并不重要,除非您想按该顺序执行操作。
因此,为什么要有单独的设置和清除寄存器的更大概念是原子性。
假设您想对某个寄存器的某个位执行某些操作。如果您熟悉“传统”的做事方式,例如打开 LED 意味着您需要读取数据寄存器、设置位并写入数据寄存器 – 即读取-修改-写入操作。
再想象一下,您想通过定时器中断控制第二个 LED,而这发生在读取数据寄存器之后但在写入数据寄存器以点亮第一个 LED 之前。定时器中断还需要对同一寄存器执行读取-修改-写入操作。第二个 LED 在中断中打开,但主代码返回寄存器的值,其中第二个 LED 熄灭但第一个 LED 亮起。显然,在对第一个 LED 执行读取-修改-写入操作时应该防止定时器中断发生,这样定时器中断也可以正确地读取-修改-写入第二个 LED。也许可以通过禁用中断来实现。
因此,拥有单独的清除和设置寄存器是原子的,并提供“硬件加速”,您无需花时间在无用的读取 – 修改 – 写入序列上,也无需担心操作的原子性。
例如,您可以通过告诉硬件要设置或清除哪些位以及要保持哪些位不变,在一次操作中设置或清除某些位。
\endgroup
|
补充一下@Justme 的回答,这对于内容被微控制器修改的寄存器尤其重要。
想象一下一个中断状态寄存器(包含多个中断源),它由微控制器更新,需要在中断服务例程中清除。如果微控制器在读取/修改/写入过程中更新了不同的中断状态,则使用读取/修改/写入方法清除中断将导致问题。
\endgroup
|
|