###### tags: `CPP` `Arduino`
# 07 使用自製函式減少重複的程式碼
在上一個教學中, 你可能已經注意到漸亮和漸暗的過程切換亮/熄的程式其實是一樣的, 如果可以減少重複的程式, 就可以讓程式更精簡。要做到這一點, 可以使用自製的函式。
到目前為止, 除了 Arduino 規定的 `setup` 與 `loop` 外, 我們都是使用 Arduino 提供的函式, 接著就來試試將切換亮/熄的程式包裝成函式:
```cpp=
const int total = 200; // 亮/熄切換總次數
const int duration = 100; // 單次亮/熄時長 (us)
const int led_pin = 5; // 內建 LED 腳位
void twinkle(int led_pin, int duration, int duration_on, int total) {
for(int count = 0;count < total; count++) {
digitalWrite(led_pin, LOW);
delayMicroseconds(duration_on);
digitalWrite(led_pin, HIGH);
delayMicroseconds(duration - duration_on);
}
}
void setup() {
pinMode(led_pin, OUTPUT);
}
void loop() {
for(int duration_on = 0; duration_on <= duration; duration_on++) {
twinkle(led_pin, duration, duration_on, total);
}
for(int duration_on = duration; duration_on >= 0; duration_on--) {
twinkle(led_pin, duration, duration_on, total);
}
}
```
第 5~12 就是自訂的函式:
1. 函式名稱前面要註明**傳回值的資料型別**, **`void`** 表示這個函示**沒有運算結果**, **不會傳回值**。如果你的函式是計算圓的面積這樣的功能, 就需要傳回以浮點數表示的面積, 最前面就要標示型別為 [`float`](https://www.arduino.cc/reference/en/language/variables/data-types/float/)。
1. 這個函式名稱為 `twinkle`, 後面的小括號內要註明呼叫這個函式時要**傳入哪些參數**, 參數之間用逗號隔開。此例需要傳入 4 個整數, 分別代表 LED 的腳位編號、單次切換亮/熄的總時長 (單位 us)、亮燈的時長 (單位 us) 以及切換的次數。
1. 7~11 行就跟之前的程式一樣, 不再贅述。
1. 第 20 和 23 行就是呼叫這個自訂函式, 呼叫時就會把傳入的資料一一對應將其內容複製到函式內的參數, 然後執行函式的區塊, 以本例來說, 就是 6~11 行的迴圈, 跳離迴圈後就會結束函式, 回到呼叫位置, 再從下一個敘述接續執行。
透過自訂的函式, 我們就可以讓需要重複使用到的程式碼只出現一次, 並且在需要用到的地方改成呼叫函式, 不但可以讓程式更精簡, 若是為函式**取個好名字**, 還可以讓程式的語意更清楚, 像是本例的 'twinkle' 字義就是閃爍, 你不需要知道函式實際的內容也能猜出它的作用。
:::info
要特別注意的是, 本例中的函式參數名稱雖然都和函式外的變數名稱一樣, 不過函式的參數是獨立專屬於函式的一份變數, 和函式外的變數並不相干, 只是透過呼叫函式將資料傳入。
如果覺得這樣容易混淆, 可以幫參數取不一樣的名字, 或是在名稱前加上 '\_' 做區隔。
:::