2019/10/23

為什麼 GPIO input 要用 pull-up/pull-down,output 要用 push-pull 或 open-drain?


最近花了點時間研究了 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 的設計後做的猜測,可能是為了解決這些問題才這麼做的。

  1. Input 的波型不是方波的話,怎麼辦 ?
  2. GPIO Pin 腳狀態是 floating 
  3. 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 來做,不過出來的結果不是很理想,不太懂怎麼做比較對。

下面的連結可以看我模擬的結果
http://www.falstad.com/circuit/circuitjs.html?cct=$+1+0.000005+10.20027730826997+50+5+43%0Af+288+160+368+160+33+1.5+0.02%0Af+272+240+368+240+32+1.5+0.02%0Aw+368+176+368+224+0%0Aw+368+144+368+64+0%0Aw+16+176+16+64+0%0Aw+368+256+368+320+0%0Aw+16+240+16+320+0%0Aw+368+336+368+320+0%0Aw+368+176+464+176+0%0Ar+464+176+464+256+0+100%0Ag+464+256+464+288+0%0AR+16+64+16+48+0+0+40+5+0+0+0.5%0Ag+16+320+16+352+0%0Ar+16+176+16+240+0+1000%0As+16+176+160+176+0+0+false%0Ag+368+336+368+352+0%0AR+368+64+368+32+0+0+40+5+0+0+0.5%0AR+592+176+592+64+0+0+40+12+0+0+0.5%0Ar+592+176+496+176+0+200%0Aw+496+176+464+176+0%0AI+208+240+272+240+0+0.5+5%0As+64+96+128+96+0+0+false%0A151+208+160+288+160+0+2+0+5%0Aw+160+176+208+176+0%0Aw+64+96+16+176+0%0Aw+208+240+160+176+0%0Aw+160+144+208+144+0%0Aw+128+96+160+144+0%0Ax+49+56+260+59+4+14+0%5Cs(off):open%5Csdrain,%5Cs1%5Cs(on):push-pull%0Ax+36+239+182+242+4+14+GPIO%5Csout:%5Cs0%5Cs(off),%5Cs1%5Cs(on)%0Ax+492+265+523+268+4+14+Load%0Ab+432+192+504+242+0%0Ab+53+149+125+215+0%0Ab+58+69+130+119+0%0Ao+9+64+0+4099+5+0.05+0+2+9+3%0A