5

假设我在下面有这段代码:

int led = 13;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  ledChange(HIGH);
  delay(1000);
  ledChange(LOW);
  delay(1000);
}

void ledChange(int pinState)  {
  digitalWrite(led, pinState);
}

转移digitalWrite(led, pinState);到自己的功能会影响处理时间吗?

当然,单个 LED 的性能并不重要,但它可能在每个时钟周期都很重要(高采样率、循环中的大量数学运算等)。

4

3 回答 3

8

定义为 void 的函数只是通知编译器/优化器该函数没有预期的返回值。

因此不会生成用于保存或操作任何返回值的代码。

这不是 Arduino 特有的,它是通用的 C 行为。

于 2013-04-10T22:49:55.237 回答
8

是的,您正在浪费少量的时钟周期。当你写ledChange(LOW)时,它被编译成一个 CALL 类型的指令(它告诉程序计数器寄存器跳转到方法的位置)。

因此,这将基本上编译为:

  • 放入LOW一些寄存器或堆栈
  • 跳转到的位置ledChange()
  • 从内存中获取led,并把它LOW放在某个地方
  • 跳到digitalWrite()
  • 做任何事情digitalWrite()
  • 跳回来
  • 跳回来

请注意,CALL跳转涉及大量堆栈混乱,并且比常规JMP指令花费更长的时间。

另一方面,做只是digitalWrite(led,LOW)会做:

  • 从内存中的某个地方获取ledLOW并将它们放在可以访问的地方
  • 跳到ditigalWrite()
  • 做任何事情digitalWrite()
  • 跳回来

我不完全确定如何在相应的编译代码中传递参数,它可能是调用的一部分。另请注意,编译器各不相同,有些比其他编译器更智能。

您可以看到您对函数的封装使程序每次运行时都会占用更多的时钟周期。但是,这并不值得优化。我看不到这种封装有多少容量可以减慢 Arduino 的速度。此外,就像我提到的,一些编译器会优化这些东西。


这与作为 a 的函数无关void。如果它是一个int函数,它会稍微慢一些,因为在返回之前存储 int 涉及一个MV或堆栈操作(忘了哪个)。

于 2013-04-11T04:55:09.590 回答
2

您可以设置 avr-gcc 以显示程序集输出。检查出来你会发现函数的返回类型与代码的大小无关。如果您不返回任何值,则不会生成额外的代码。但是你会得到编译器警告,所以void在这种情况下使用它很好。

如果你使用函数,你的代码可能会更短,因为你不需要在每次需要时重复函数中的代码(这意味着你需要在函数中有足够的代码来抵消调用和返回指令- 几乎总是如此)。这将使代码稍微变慢,因为它需要执行调用和返回指令,但这很可能会被大小减少和代码维护的改进所抵消。

我希望我足够清楚,这似乎有点令人费解:)

于 2013-04-11T01:24:18.240 回答