嵌入式C程序中的高效位校验

Efficient bit checking in embedded C Program

我正在使用 atmega328 的 AVR 控制器。 我需要检查两位的状态。我有两种方法,但不确定哪一种最有效。在下面代码的第一种情况下,我使用 PIND 命令读取端口两次(进行了两次 PIND 访问)。那么这是一个问题还是我必须使用第二个 if 语句?

#define SW1 2
#define SW2 5
//check if both are high
if((PIND&(1<<SW1))&&(PIND&(1<<SW2))) 
//Or
if((PIND&((1<<SW1)|(1<<SW2)))==((1<<SW1)|(1<<SW2))) 

如果没有汇编程序的输出,很难说以上2个哪个效率更高。但是我猜想性能上的差异会很小。

在情况 2 中,您避免读取寄存器两次,但您正在执行 2 个额外的操作。

如果让我猜测的话,我会说选项 1 最有可能更快,因为 PIND 是一个 AVR 注册器,而且读取成本会更低。

话虽如此,我建议使用第一个选项,因为它更具可读性,即使它没有被发现比选项 2 更快。

我想PIND是一个外围寄存器(你说的"command"是什么意思?)

第一次检查会看一次或两次,这取决于第一次比较。如果 SW1 在第一次和第二次读取之间发生变化,这可能会产生故障。

假定 SW?是开关:一般来说,最好读取一次这样的寄存器(可能是一个变量)并测试位。这可确保您同时获得所有输入位的快照

此外,seconde 版本不一定更慢,因为它保护了一个分支(IIRC AVR 除了 branch/jump 之外没有条件指令)。

第一次读取 PIND 两次,因此效率较低且可能出错 - 如果中断或线程上下文切换介入,读取之间的时间可能很长。

第二个计算 (1<<SW1)|(1<<SW2) 两次,但在本例中它是一个编译时间常量,因此对性能应该没有影响。但老实说,您可能正在为这个级别的代码担心太多的小事情。如果你真的需要知道;看看编译器生成的代码(在调试器反汇编中或通过让编译器输出汇编列表),但是如果你打算像这样对每一行进行第二次猜测,那么编写代码将花费很长时间,