AVR使用struct或#define定义引脚

时间:2018-05-07 13:04:40

标签: c avr

我见过很多人说"总是使用#define定义库中某些东西的引脚和端口"而目前,这也是我所做的。但我正在考虑使用结构而不是这种方法。

我使用shiftregister及其库的示例

我认为是专业人士

  • 使用一个库轻松处理多个shiftregister
  • 您不需要更改库的源文件中的任何内容

我所看到的是什么

  • 占用空间(与#define不同)
  • 可能需要更多时间进行计算,因为您必须考虑可以为每个班次注册使用不同的端口,并且您必须检查

您是否了解使用结构而不是某些#defines的优缺点? 并且你会认为缺点是足够重要的东西,所以你永远不会使用结构(即使它不是时间或空间关键)?

1 个答案:

答案 0 :(得分:0)

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

PORTD |= (1 << 1);

AVR GCC编译器善于将这样的代码编译成单个AVR汇编指令(名为sbi),但前提是它在编译时确切知道您要写入的寄存器(PORTD ),你在设置什么位(第1位)。

使用一条指令代替多条指令设置该位有很多好处:

  • 占用较少的代码空间。
  • 它运行得更快。
  • 即使可能会运行一个修改同一寄存器的中断也是安全的,因为读取,修改和写入步骤都发生在一条无法中断的指令中。

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

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

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

https://godbolt.org/g/mkxHc2

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

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