最近花了點時間研究了 GPIO 為什麼有那麼多的設定要選,有 pull-up / pull-down,還有 push-pull。上網一查,發現相關的心得文章超多,代表了有很多的人都跟我一樣,時間和精神去了解,然後覺得有點價值,值得寫文章記錄下來。
目前看了幾篇文章覺得很有參考價值的有下面幾篇。
Open Drain Output vs. Push-Pull Output
單片機IO口科普:推輓輸出、開漏輸出詳解
Demystifying Microcontroller GPIO Settings
電路常見問題小記之IO口漏電(leakage)
我自己的理解是這樣的。
GPIO 從名稱就能知道,最重要的功能就是用來和外界做 Input 和 Output。從軟體的角度看,就像是 Chip 出了一個 pin 腳,外界只要接上那根 pin 就能跟 Chip 溝通了。
在軟體人的想像中,我想只要有線路接到 register 就夠了吧 ! 在想的仔細一點,加上軟體操作用的 register 好了。
可惜事情不是這麼簡單,現實的物理之壁很快就讓人認清現實。這麼做會有幾個問題要解決。這些問題是看著 GPIO 的設計後做的猜測,可能是為了解決這些問題才這麼做的。
- Input 的波型不是方波的話,怎麼辦 ?
- GPIO Pin 腳狀態是 floating
- output 如何提供足夠的電流輸出到外面的設備 ?
Input 的波型不是方波的話,怎麼辦 ?
用 schmitt trigger 來解。
GPIO Pin 腳狀態是 floating
GPIO 有三種狀態,High impedance,High (voltage),Low (voltage)。
High 代表 digital 1, Low 代表 digital 0。根據 chip 的設計,通常 3.3V = High,0V = Low 。
'High impedance' 也可以寫成 'Hi-Z',代表不上不下,這時的 GPIO pin 可能為 1 也可能為 0,看當下的使用環境而定。這個用途是,當跟其他設備共用一條線時,不影響正在輸出 High / Low 的設備。當沒有共用時,就需要給他一個確定的狀態,避免誤動作。為什麼 floating 會造成誤動作,詳細請看下面的連結,講得很清楚。
浮接 Floating 是甚麼? 電路的不確定因素
回到 GPIO,這個問題就用 pull-up/pull-down 來處理。pull-up 表示預設為 high,pull-down 表示預設為 Low。對應的外部設備動作,pull-up 隱含設備有動作時會拉 Low,pull-down 隱含設備動作時會拉 high。
output 如何提供足夠的電流輸出到外面的設備 ?
這個問題是我想像出來的,目前還沒找到使用 push-pull 的原因,看到的都是在講說 push-pull 的原理,但沒有講是用來解決甚麼問題。
目前看到的 GPIO 有兩種設計來提供電流給外部設備用,一種是 Chip 內的電流,一種是外部的電流。兩種都由 GPIO 來控制供給的時間點。
使用 Chip 內電流的方式稱為 push-pull。外部電流稱為 open-drain (或 open-collector)。
Push-pull
我這邊會加個 inverter 是因為,光只有 PMOS 和 NMOS 的組合,得到的會是一個 inverter。這跟我想要的,GPIO output 1 時輸出電流,output 0 時輸入電流的預期不合,所以才在把他反過來。可以看這一篇 https://en.wikipedia.org/wiki/Inverter_(logic_gate) 提到的 inverter 作法。
Open-drain
Open-drain 由外部提供電流,所以一定要接一個外面的電源。接法就像是 pull-up。
最後,有些 Chip 很聰明,可以讓使用者選擇要用 push-pull 或是 open-drain,有些就不行。這邊我想了一下,覺得可以加一個 NAND 來做,不過出來的結果不是很理想,不太懂怎麼做比較對。
下面的連結可以看我模擬的結果