AVR 使用 struct 或 #define 定义引脚

AVR define pins with struct or #define

我看到很多人说 "always use a #define to define the pins and ports of something in a library",目前,我也是这样做的。但我正在考虑使用结构而不是这种方法。

我使用移位寄存器及其库的示例

我认为专业人士

我认为的骗局

您是否知道使用结构而不是某些#defines 的更多优点或缺点? 并且您是否会认为缺点足以使优点过重,以至于您永远不会使用结构(即使不是时间或 space-关键)?

以下代码将 AVR 引脚 (PD1) 设置为高电平(假设它已作为输出启用):

PORTD |= (1 << 1);

AVR GCC 编译器擅长将这样的代码编译成单个 AVR 汇编指令(命名为 sbi),但前提是它在编译时确切地知道您正在写入哪个寄存器(PORTD),以及您要设置的位(位 1)。

使用一条指令而不是多条指令来设置位有很多优点:

  • 它需要更少的代码 space。
  • 它 运行 更快。
  • 即使中断可能 运行 修改同一个寄存器也是安全的,因为读取、修改和写入步骤都发生在一条不能被中断的指令中。

如果您使用 #define 定义的预处理器宏来定义您的管脚,那么在预处理器 运行s 之后,您的代码看起来就像上面的代码,并且应该编译成一条指令.

另一方面,如果您使用结构来定义引脚,并将这些结构动态传递给您的库,编译器很可能无法进行此优化。

这是一个link,您可以在其中看到两种设置引脚的方法,并且可以看到 struct 方法的效率要低得多:

https://godbolt.org/g/mkxHc2

请注意,除了此处讨论的两种方法之外,还有许多其他方法可以指定和操作引脚。 Arduino 库通常将引脚表示为单个数字,然后调用 pinModedigitalWrite 等函数来操作指定的引脚。 (pinModedigitalWrite 的实现效率很低,必须禁用中断,但可以改进。)

一种更高级的技术是使用 C++ 模板参数来指定引脚,就像 FastGPIO library 那样。