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",目前,我也是这样做的。但我正在考虑使用结构而不是这种方法。
我使用移位寄存器及其库的示例
我认为专业人士
- 用一个库轻松处理多个移位寄存器
- 您无需更改库的源文件中的任何内容
我认为的骗局
- 占用 space(与 #define 不同)
- 可能需要更多时间来计算,因为您必须考虑到每个移位寄存器可以使用不同的端口,并且您必须检查
您是否知道使用结构而不是某些#defines 的更多优点或缺点?
并且您是否会认为缺点足以使优点过重,以至于您永远不会使用结构(即使不是时间或 space-关键)?
以下代码将 AVR 引脚 (PD1) 设置为高电平(假设它已作为输出启用):
PORTD |= (1 << 1);
AVR GCC 编译器擅长将这样的代码编译成单个 AVR 汇编指令(命名为 sbi
),但前提是它在编译时确切地知道您正在写入哪个寄存器(PORTD
),以及您要设置的位(位 1)。
使用一条指令而不是多条指令来设置位有很多优点:
- 它需要更少的代码 space。
- 它 运行 更快。
- 即使中断可能 运行 修改同一个寄存器也是安全的,因为读取、修改和写入步骤都发生在一条不能被中断的指令中。
如果您使用 #define
定义的预处理器宏来定义您的管脚,那么在预处理器 运行s 之后,您的代码看起来就像上面的代码,并且应该编译成一条指令.
另一方面,如果您使用结构来定义引脚,并将这些结构动态传递给您的库,编译器很可能无法进行此优化。
这是一个link,您可以在其中看到两种设置引脚的方法,并且可以看到 struct 方法的效率要低得多:
请注意,除了此处讨论的两种方法之外,还有许多其他方法可以指定和操作引脚。 Arduino 库通常将引脚表示为单个数字,然后调用 pinMode
和 digitalWrite
等函数来操作指定的引脚。 (pinMode
和 digitalWrite
的实现效率很低,必须禁用中断,但可以改进。)
一种更高级的技术是使用 C++ 模板参数来指定引脚,就像 FastGPIO library 那样。
我看到很多人说 "always use a #define to define the pins and ports of something in a library",目前,我也是这样做的。但我正在考虑使用结构而不是这种方法。
我使用移位寄存器及其库的示例
我认为专业人士
- 用一个库轻松处理多个移位寄存器
- 您无需更改库的源文件中的任何内容
我认为的骗局
- 占用 space(与 #define 不同)
- 可能需要更多时间来计算,因为您必须考虑到每个移位寄存器可以使用不同的端口,并且您必须检查
您是否知道使用结构而不是某些#defines 的更多优点或缺点? 并且您是否会认为缺点足以使优点过重,以至于您永远不会使用结构(即使不是时间或 space-关键)?
以下代码将 AVR 引脚 (PD1) 设置为高电平(假设它已作为输出启用):
PORTD |= (1 << 1);
AVR GCC 编译器擅长将这样的代码编译成单个 AVR 汇编指令(命名为 sbi
),但前提是它在编译时确切地知道您正在写入哪个寄存器(PORTD
),以及您要设置的位(位 1)。
使用一条指令而不是多条指令来设置位有很多优点:
- 它需要更少的代码 space。
- 它 运行 更快。
- 即使中断可能 运行 修改同一个寄存器也是安全的,因为读取、修改和写入步骤都发生在一条不能被中断的指令中。
如果您使用 #define
定义的预处理器宏来定义您的管脚,那么在预处理器 运行s 之后,您的代码看起来就像上面的代码,并且应该编译成一条指令.
另一方面,如果您使用结构来定义引脚,并将这些结构动态传递给您的库,编译器很可能无法进行此优化。
这是一个link,您可以在其中看到两种设置引脚的方法,并且可以看到 struct 方法的效率要低得多:
请注意,除了此处讨论的两种方法之外,还有许多其他方法可以指定和操作引脚。 Arduino 库通常将引脚表示为单个数字,然后调用 pinMode
和 digitalWrite
等函数来操作指定的引脚。 (pinMode
和 digitalWrite
的实现效率很低,必须禁用中断,但可以改进。)
一种更高级的技术是使用 C++ 模板参数来指定引脚,就像 FastGPIO library 那样。