Arduino Leonardo控制板的數位14~17腳、類比A6~A11腳以及SPI腳位介紹

Arduino Leonardo(李奧納多)採用的Atmega32u4微控器,總共有44個接腳,相較之下,前一代的Arduino UNO和Duemilanove採用的ATmega328微控器則有28隻腳。

也因此,Arduino Leonardo控制器的某些介面腳位定義和UNO/Duemilanove控制器不同。

SPI(Serial Peripheral Interface,序列周邊介面,普遍用於連結SD記憶卡和乙太網路卡)為例,在採用ATmega328微控器的Arduino板子上,它們位在數位10~13腳,同時也和控制板右側的ICSP(In-Circuit Serial Programming,譯作「實體電路串列燒錄」或「線上燒錄」)端子相連:

Arduino UNO的SPI和ICSP接腳

Arduino Leonardo控制器的SPI介面,並不在數位10~13接腳,只位於ICSP端子,而且其中的3個接腳相當於數位14~16腳。微控器預設的周邊選擇線(Slave Select,簡稱SS),則位在板子左側,RX(序列接收)燈號的左上角的一個焊接點,並且與RX的LED相連,它同時也是數位17腳

Arduino Leonardo的SPI和ICSP接腳

圖片上方標示的A6~A11,是Arduino Leonardo控制器新增的類比輸入接腳,和數位腳共用。

Arduino Leonardo控制器的小小改造:連接數位17腳

不知道為何SS(數位17)腳被冷落在一旁,底下是這個接點的正、反面近照:

Arduino Leonardo控制器的數位17(SS)腳

其實我們能把任何數位腳透過程式指定成SS,然而,將一個接腳棄置不顧,似乎有點可惜。我看了原廠的Arduino Leonardo電路圖(PDF格式),位於下側的排插最左邊,是空接的插孔。因此我在SS腳和這個插孔之間,焊接一條導線,將它們連結起來:

改造後的Arduino Leonardo控制器

這樣就能方便運用這個數位17腳了。

此外,在採用ATmega328微控器的Arduino板子上,我們鮮少使用數位0數位1腳,因為它們和板子上的USB序列通訊埠相連,預設用於上傳程式檔,也是和電腦的序列通訊程式溝通的管道。

Arduino Leonardo控制器的數位0和數位1腳,則是獨立的序列埠。和電腦溝通的USB序列埠,程式物件的名稱是Serial,這個新的序列埠的程式物件名稱則是Serial1,除此之外,兩者的宣告方式以及程式庫指令都一樣。

例如,初始化USB序列埠,並傳遞”Hello World!”字串的寫法如下:

Serial.begin(9600);
Serial.println("Hello World!");

採用新的序列埠的寫法則是:

Serial1.begin(9600);
Serial1.println("Hello World!");

當然,我們可以用SoftwareSerial(軟體序列埠)程式庫,把任何接腳模擬成序列埠,所以多了一個序列埠也不是什麼了不起的功能,只是現在可以沒有顧忌地使用數位0和數位1腳。

Arduino Leonardo板的功能比較多,但如果你手上已經有Arduino板,也不需要用到這麼多的接腳,或者不需要模擬USB鍵盤∕滑鼠等功能,那麼,採用ATmega328微控器的Arduino板就很夠用了。

延伸閱讀

Posts created 467

44 thoughts on “Arduino Leonardo控制板的數位14~17腳、類比A6~A11腳以及SPI腳位介紹

  1. 您好:

    小弟最近在嘗試Leonardo的SPI通訊,我照著您的建議,試圖將SS焊接到空的插孔,但是發現Leonardo表面好像有防焊?焊錫無法黏著SS的孔,請問您有遇到這樣的問題嗎?

    不知道為何Leonardo提供SPI,卻把SS忽略在一旁??

    1. hi 小李:

      目前的3C產品大多使用無鉛焊錫,熔點比較高,我是用60W烙鐵焊接上去的。

      have fun!
      jeffrey

  2. 您好:
    謝謝您的回答!
    我是使用有鉛的焊錫,65W的焊槍(可調溫度範圍200~480度C),並使用焊油。

    我朋友看過Leonardo板子,他說表面上的確是有防焊處理,就是藍色的這層漆,應該是為了防止時間久了,電路板線路氧化,或是防止某些接點短路,才會做這種處理。所以,他建議必須把焊點周圍表面的防焊處理刮掉,才比較能讓焊錫黏上去。因此我目前暫不採用您的作法,而直接改用Digital Output Pin來當作SS。目前也已經成功了!

    但我只是好奇,不知道您是否有刮掉Leonardo表面的防焊漆? 還是很順利,直接焊接就可以了?

    1. 小李:

      抱歉誤會你的意思,我並沒有刮除防焊漆,因為防焊漆不會流入貫穿孔,所以我是先用一根導線插入SS接孔(底下紅色箭號所指之處),然後替導線上焊錫固定。

      插入PCB貫穿孔的導線

      have fun!
      jeffrey
      ps. 你的焊接設備很專業~

    1. SPI接口的SS,本来就可以用任何digital pin,只要在代码中指定SS接脚的编号即可。

      thanks,
      jeffrey

    1. hi cuue:

      Arduino Leonardo可以使用內建的滑鼠與鍵盤程式庫(這個程式庫底下的Example單元,有數個現成的範例)。我最近比較忙,月底前我再更新一篇相關的文章。

      thanks,
      jeffrey

  3. 你好,請問Leonardo如何用ICSP接SD卡模塊,CS接腳應該如何接?SD庫是否需要修改?望解答!

    1. hi steven:

      SD程式庫的預設CS腳是”4″。

      以其中的Cardinfo(記憶卡資訊)範例而言,程式開頭有一個宣告CS腳位的變數:

      const int chipSelect = 4;

      若有需要,可它改成其他接腳。

      thanks,
      jeffrey

  4. 老師您好:

    請問…關於SD問題…,如果說 我呼叫一個 自己寫的function 後,但結果顯示就怪怪的…,會一直讀取第一個txt檔…,連值都沒有讀到,是因為一直再呼叫function沒有跳出嗎?!

    1. hi kai:

      底下是改寫自Arduino內建的SD記憶卡Datalogger範例程式,寫入SD記憶卡的程式移至write2SD()函式,每個5秒呼叫一次,測試無誤:

      #include <SPI.h>
      #include <SD.h>
      
      const int chipSelect = 4;
      
      unsigned long previousMillis = 0;
      const long interval = 5000;  // 5000ms間隔時間
      
      void setup()
      {
        Serial.begin(9600);
        while (!Serial) {
          ; 
        }
      
        Serial.print("Initializing SD card...");
      
        if (!SD.begin(chipSelect)) {
          Serial.println("Card failed, or not present");
          return;
        }
        Serial.println("card initialized.");
      }
      
      void loop()
      {
        unsigned long currentMillis = millis();
       
        // 每隔5000ms寫入SD資料 
        if(currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis; 
          write2SD();
        }
      }
      
      void write2SD() {
        String dataString = "";
      
        for (int analogPin = 0; analogPin < 3; analogPin++) {
          int sensor = analogRead(analogPin);
          dataString += String(sensor);
          if (analogPin < 2) {
            dataString += ",";
          }
        }
      
        File dataFile = SD.open("datalog.txt", FILE_WRITE);
      
        if (dataFile) {
          dataFile.println(dataString);
          dataFile.close();
          Serial.println(dataString);
        }
        else {
          Serial.println("error opening datalog.txt");
        } 
      }
      

      thanks,
      jeffrey

  5. 老師你好 請問arduino yun的SS腳該怎麼去焊?是不是被SD卡插槽給擋住了?
    如果使用Digital Output Pin 去定義SS
    #define SSPIN 7 <<是這樣定義嗎?

    1. hi joskyo:

      晶片選擇腳可以用任何閒置的數位或類比腳替代,程式庫通常採用SS命名,因此你的程式可以使用CS或其他名稱來命名…常數名稱其不是很重要,只要你的程式本體有正確引用相同的名稱即可,

      thanks,
      jeffrey

    2. 謝謝老師的指導 RFID可以正常運作了,今天碰到了新的2個問題
      1.我想將SD卡的內容讀出 顯示在串列埠視窗
      會出現Connection closed by foreign host

      2.另外想請問在W5100上SD卡可以直接使用FILE_WRITE把資料直接接續著寫入,可是在yun上卻不行會直接重頭寫入,要使用FILE_APPEND才會接續,請問有甚麼差別嗎 我看官網寫的解釋如下都相同
      FILE_WRITE: open the file for reading and writing, starting at the end of the file.
      怎麼用起來不太一樣 是我哪邊有漏掉嗎?

      以下是程式碼,用SD卡的範例下去改的
      #include
      #include

      void setup() {
      Bridge.begin();
      Console.begin();
      FileSystem.begin();
      while(!Console);

      }

      void loop() {
      File dataFile = FileSystem.open(“/mnt/sda1/test.txt”, FILE_APPEND);
      if(dataFile){
      Console.println(“opening test.txt”);
      while(dataFile.available()) {
      Console.println(dataFile.read());
      }
      dataFile.close();
      }
      else{
      Console.println(“error opening test.txt”);
      }

      delay(1000);
      }

    3. 剛剛查閱Arduino Yun的FileIO類別說明,根據這篇Open()方法的說明,它的參數只有FILE_READ和FILE_WRITE兩個參數,我不清楚為何要用FILE_APPEND。

      很抱歉我手邊沒有Yun,無法幫你測試。

      thanks,
      jeffrey

    4. 原本範例檔程式 就是直接使用FILE_APPEND 因為不太曉得它的作用
      剛開始改成FILE_WRITE 才發現資料寫進去都會重頭開始部會接續 , 之後才改回範例檔的這個APPEND來使用。

  6. 老師您好
    您的書(Arduino 互動設計入門 2)是我踏入Arduino的大門

    請問Leonardo與TEENSY差在哪裡?
    我兩款都有買
    查看電路圖
    都差不多
    是個別都有安裝不同BOOTLOADER嗎?
    是否可將Leonardo改成TEENSY

    因為TEENSY可以直接模擬成MIDI裝置
    不像Arduino 需要透過UART轉MIDI的軟體轉換

  7. 老師您好,
    最近我需要使用Arduino leonardo製作SD卡的讀卡機,目前功能都可以正常初始化並寫入檔案,可是其中一項功能是 需要能夠在windows的boot manager中選擇使用SD卡開機,開機時插上接有SD卡的Arduino leonardo進入boot manager時卻沒辦法選擇以SD卡開機,市售的讀卡機卻能讀取到SD卡並選擇SD卡開機,想請問要怎麼把SD卡開機的功能加進去Arduino leonardo?

  8. 老師,關於兼容性我有個問題,如果使用teensy 2.0的hex檔案直接用arduino ide燒進去那麼這樣子能不能使用呢?
    我想法是,如果mcu是一樣的,那麼兩者的區別就是電腦端ide的程式庫不一樣了.
    只是bootloader不同的話,應該不會影響已經生成好的hex使用了吧?
    不知道我這樣的想法正不正確呢?
    謝謝

    1. 嗯,倘使微控器型號和週邊IC配置相同、運作時脈頻率一樣,燒錄另一個bootloader,就變成相容開發板了。

      thanks,
      jeffrey

  9. 不,我的意思是bootloader都不重新燒錄,直接寫入hex檔案.
    例如一個teensy 2.0使用的hex(只是舉例,這樣子就是使用teensy的程式庫生成的hex檔案)
    直接用arduino ide燒錄進去arduino,也就是bootloader還是arduino的沒動過.
    理論上是可以正常使用的?
    因為這個bootloader按道理只是用來下載並不會影響到程序的運行.
    而且teensy自身的程序庫支援的特性也不會受到影響(也就是midi之類)
    周邊IC配置這兩款我感覺好像差不多誒………..

  10. 還有一個問題,arduino真的改成teensy開發板嗎?
    teensy 2.0的bootloader好像並不是開源可以仿製的?………
    謝謝

    1. 我沒有用過teensy板子,如果它不是open source,也沒有釋出bootloader,那恐怕就不能輕易仿製了。

      保留Arduino的bootloader,燒錄teensy的hex檔,我認為不可行,因為程式的起始執行位址可能不同。與其廢心思臆測,你為何不直接燒入看看呢?

      如果你的目的只是為了運用它的程式庫,製作USB裝置,例如,USB MIDI介面…
      其實早就有人嘗試把Teensy的程式庫轉移到Arduino Leonardo控制板了,
      像這個Adafruit公司修改的TeeOnArdu版本

      thanks,
      jeffrey

  11. 又想起來一個問題,如果使用isp燒進去hex檔案應該也是正常使用吧?
    雖然這樣會覆蓋掉bootloader…….而且這樣啟動也可以更快?
    據說脫離bootloader直接以isp方式燒錄也是正常使用的,但沒有嘗試過…….

    1. Arduino的特色之一,就是它的bootloader,你不要用它,改用其他開發工具,用標準的C/C++或組合語言開發、燒入程式,當然可以,只是那個板子就不是Arduino了。

      thanks,
      jeffrey

  12. 因為您說到bootloader和程式庫,又有了一個想法.
    如果是使用teensy的程式庫生成的hex直接使用spi方式燒錄進去不知道能不能正常使用?
    fuse應該讀出來使用原本arduino默認設置就好了吧.
    不知道這樣子行不行?
    謝謝

  13. 楼主您好,我用您的程序下载到leonardo,串口监视器看到的是下面的信息
    error opening datalog.txt
    而我用自带的cardinfo可以读到卡片信息,却都不到文件里面还有一个txt文件

    1. 始终不能读写文件,在nano板子上试着好好的,偏偏到了leonardo就不行了,现在不知道是哪的问题,感觉是否是需要修改库文件?还是其他解决办法谢谢。

  14. 您好,不好意思,是我没讲清楚,我用leonardo与SD卡进行spi通信的时候,用arduino ide里自带的示例程序cardinfo用串口监视器可以看见卡片类型和容量,最后一行的文件信息却读不到(实际上卡里面是有一个txt文件的),如果接线接错了的话我感觉sd卡信息是读不到的。
    换成以下程序,
    串口监视器显示:error opening datalog.txt(而换成nano却可以显示数值并写入一个文本文件)

    #include
    #include

    const int chipSelect = 4;

    unsigned long previousMillis = 0;
    const long interval = 5000; // 5000ms間隔時間

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

    Serial.print(“Initializing SD card…”);

    if (!SD.begin(chipSelect)) {
    Serial.println(“Card failed, or not present”);
    return;
    }
    Serial.println(“card initialized.”);
    }

    void loop()
    {
    unsigned long currentMillis = millis();

    // 每隔5000ms寫入SD資料
    if(currentMillis – previousMillis >= interval) {
    previousMillis = currentMillis;
    write2SD();
    }
    }

    void write2SD() {
    String dataString = “”;

    for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
    dataString += ",";
    }
    }

    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    Serial.println(dataString);
    }
    else {
    Serial.println("error opening datalog.txt");
    }
    }

  15. 我试着打乱接线次序,连信息都读不到。

    感觉应该不是接线的问题(是不是需要改库文件才能让leonardo进行spi通信?)
    示例程序串口返回如下信息

    Initializing SD card…Wiring is correct and a card is present.

    Card type: SD1

    Volume type is FAT32

    Volume size (bytes): 1973420032
    Volume size (Kbytes): 1927168
    Volume size (Mbytes): 1882

    Files found on the card (name, date and size in bytes):

    初始化SD卡…布线正确,有卡存在。

    卡类型:SD1

    卷类型是FAT32

    音量大小(字节):1973420032
    卷的大小(字节):1927168
    卷的大小(MB):1882

    卡片上发现的文件(姓名、日期和大小以字节为单位):

  16. 已经找到问题了,sd卡模块的问题,电阻分压式的设计会让信号失真严重,换了个带电平转换的模块就好了。

    1. 如果你的目的是讀取一般類比感測器的電壓變化,直接連接類比輸入腳即可;若是要監測系統的電源狀態,可以使用”NA219″這個IC模組,它採用I2C介面,有現成的程式庫可用,但我沒用過,請自行搜尋相關資料。

      thanks,
      jeffrey

  17. 关于D17脚,因为它是直接连在RxLED上的,如果我的项目需要用到USB传输但不关心灯的状态,是否能够像使用其他IO一样使用D17脚做输出呢?

發佈留言

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

Related Posts

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

Back To Top