建立可傳回多個數值(陣列)的Arduino(C語言)自訂函式

C語言自訂函式的return敘述只能傳回一個變數值,若要傳回多個值,可以把資料存入陣列,然後傳回該陣列的起始(第一個元素)的地址。

然而,定義在函式裡的變數通常都是在函式執行時被建立、函式執行完畢之後被拋棄;為了讓函式呼叫敘述能接收到可用的陣列資料,程式必須防止自訂函式裡的區域變數被清除(註:函式的單一傳回值,會直接複製給呼叫方的變數,所以即使區域變數被回收了,數值仍能存在呼叫方的接收變數中)。

因此,可傳回陣列值的自訂函式必須滿足兩個條件:

  • 要傳回陣列的起始位址
  • 保留函式裡的區域變數

使用static關鍵字保留區域變數

在區域變數定義的前面加上static(代表靜態或沒有變動)關鍵字,該變數就能在函式執行之後被保留下來。宣告一個傳回陣列值的自訂函式語法如下:

宣告傳回陣列值的自訂函式語法

可傳回陣列值的Arduino函式範例程式

底下的例子中,自訂函式readSensors()將在每次執行時,在s陣列存入3個隨機數字,最後傳回s陣列的第一個元素位址。關於累進記憶體位址的說明,請參閱《超圖解Arduino互動設計入門》第八章「認識指標」單元(8-41頁)。

傳回陣列值的自訂函式的範例程式碼

編譯並上傳程式到Arduino,每隔一秒,它將在「序列埠監控視窗」顯示存在s陣列裡的3個隨機數字:

序列埠監控視窗

完整的程式碼如下:

byte * readSensors() {
   static byte s[3];
   
   for (byte i=0; i<3; i++) {
     s[i] = random(256);
   }

   return s;
}

void setup() {
   Serial.begin(9600);
}

void loop() {
  byte *pt = readSensors();

  Serial.print("Sensor Data: ");
  for (byte i=0; i<3; i++) {
    Serial.print(*(pt+i));
    Serial.print( "   ");  
  }
  Serial.println("");

  delay(1000);
}
Posts created 468

24 thoughts on “建立可傳回多個數值(陣列)的Arduino(C語言)自訂函式

  1. 老師您好:
    從您的教學文件總能學到一些新奇的東西, 十分感激, 在此有個問題想要請教您:
    就是請問arduino的程式能夠先變成一個二進制rom檔後再燒到arduino裡嗎?
    因為我有個小治具要量產, 但不想將程式公開給廠商或工廠去upload到arduino
    所以想說有沒有機會先變成binary code再傳送給對方去做燒入動作, 麻煩老師, 謝謝

    1. hi kevin:

      選擇Arduino IDE的「草稿碼→匯出已編譯的二進位檔」指令即可。

      thanks,
      jeffrey

  2. 老師您好:
    想請問一下,如果上述的例子中第五行的部分改成 s[i] = (5*i)/3; 的話其他地方要怎改??我在書上找不到方法,
    麻煩老師了
    謝謝

    1. 哦~這個書上有寫啦~你要把陣列的資料類型改成float,請參閱3-18頁「轉換資料類型」。

      thanks,
      jeffrey

  3. 老師您好,我最近在try關於I2C的控制
    我想要將slave端回送給master的數值來使用。
    但我目前卡在
    while (Wire.available()) Serial.print((char) Wire.read());
    ———————————————————————————-
    我預先定義 char a;
    但是該如何將while (Wire.available()) Serial.print((char) Wire.read()); 輸出的值,放在定義的a 中呢?

    1. 老師您好,
      我在slave傳送Wire.write(“188”);
      我在master 寫char c=Wire.read();
      在master端只有收到1,他無法完全收到188。
      想詢問修正呢?

  4. 老師您好
    如果我將s這個矩陣改成 s[5][5]
    然後我在將他移到pt以後, 要用例如下面的方式把它顯示出來
    1a : 1b
    2a : 2b
    3a : 3b
    4a : 4b
    5a : 5b
    如上方法 我該怎麼修改for迴圈的print

  5. 老師你好:
    我想做一個類似pov clock的東西假如我一個360度的圖案然後每一度掃描一次的話,我陣列就要打360個數字嗎?

    1. POV LED顯示效果通常不是用角度來決定,而是圖像的解析度。假設你的「顯示器」有8個LED,那就是高8像素;要呈現90像素寬的圖,你的顯示圖像就是一個90×8的二維陣列:

      const byte POV_IMG[90][8] = {
      // 像素資料…
      };

      然後每延遲一段時間逐一讀取0~89的元素值給LED顯示。

      thanks,
      jeffrey

  6. 老師您好:
    我可以將arduino的副程式集 以二進位形式 全部存在外部eeprom,
    以利後續撰寫人員, 依照文件 隨時調用 使用嗎

  7. 請問 可以用Arduino玩井字遊戲(圈圈叉叉)嗎?
    只用電腦螢幕的那種(不用另外裝螢幕模組的)
    我在網路上都找不到資料

  8. 想請問一下..如何能夠將sensor 量測到的多個數值 存取起來呢.. 並且我想將 這些數值全部相加起來 來做判斷 我現在設了五個變數 但這五個變數的來源都來自同一個sensor 所以print出來的五個值都是一樣的.. 如果有看到能夠請教一下嗎謝謝..!

    1. 如果在同一時間讀取感測值、分別存入不同變數,它們的值當然是相同的;你應該讀取一次、等待一段時間、再讀取一次…

      thanks,
      jeffrey

  9. 老師你好
    1. 請問老師 是否有開arduino相關課訓練 我想報名參加
    2. 有否 關於Arduino 透過rs485 讀取表頭 電壓電流資料 的書籍 我要買
    3. 若都沒有 可否秀個範例 (我搞了好久 從未成功過)
    感謝老師您了

    1. 1. 目前沒有規劃
      2. 沒有,我手邊沒有RS485序列通訊模組,也沒有打算購買。
      3. 拍謝~我沒有東西實做驗證。

      thanks,
      jeffrey

  10. 老師你好,請問這個程式碼,s陣列所產生的隨機數字,下一組數字是直接覆蓋上一組數字而記憶體位置保持不變,還是上一組數字保留住,下一組數字由另一組記憶體位置存放呢?

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top