将Arduino代码分解为函数会占用更多空间/资源吗?

时间:2013-04-10 22:39:37

标签: performance arduino firmware

假设我有以下代码:

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的性能并不重要,但是每个时钟周期都很重要(高采样率,循环中的大量数学运算等)。

3 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:7)

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

所以,这基本上会编译为:

  • LOW放入某个寄存器或堆栈
  • 跳转到ledChange()
  • 的位置
  • 从内存中提取led,并将其与LOW某处
  • 一起放置
  • 跳转到digitalWrite()
  • 执行digitalWrite()
  • 中的任何内容
  • 跳回来
  • 跳回来

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

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

  • 从内存中的某处获取ledLOW并将其放在可访问的地方
  • 跳转到ditigalWrite()
  • 执行digitalWrite()
  • 中的任何内容
  • 跳回来

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

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


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

答案 2 :(得分:2)

您可以设置avr-gcc来显示装配输出。检查出来,你可以看到函数的返回类型与代码的大小无关。如果您没有返回任何值,它将不会生成额外的代码。但是,您将收到编译器警告,因此在这种情况下使用void很好。

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

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