一個 1 和一個 0 究竟是什麼
在第 1 篇裡,比較器在輸入交越的瞬間,把輸出猛地甩向某一條電源軌;在第 2 篇裡,史密特觸發器給了這個擺動一段死區,讓它乾脆地切換,而不是抖個不停。如今輸出得跟數位晶片對話了——這裡有第一個驚奇:數位輸入並不是在找某一個精確的電壓。它把一整個頻帶的電壓讀成 1、另一個頻帶讀成 0,而把兩者之間的無人地帶當成未定義。
從輸入的角度看,有兩個門檻。任何高於 VIH(輸入高準位門檻)的電壓,保證會被讀成 1;任何低於 VIL(輸入低準位門檻)的,保證是 0。VIL 與 VIH 之間那一段,是禁區——餵一個落在裡頭的電壓,晶片可能往任一邊判讀、可能搖擺、甚至可能振盪。這些頻帶就是我們所說的邏輯準位,而它們正是為什麼一道緩慢、漂移的邊緣很危險:它會在禁區裡逗留,這恰恰是史密特觸發器的遲滯要修好的那個問題。
雜訊容限:每個準位外的護城河
讓數位變得強健的訣竅,是輸出那一側給得超過所需。一個驅動閘承諾它的 1 不會低於 VOH(在 VIH 之上),它的 0 不會高於 VOL(在 VIL 之下)。送出去的,與僅僅被要求的,兩者之間的差距,就是雜訊容限——每個準位外的護城河。寫清楚:高側容限是 NMH = VOH - VIH,低側容限是 NML = VIL - VOL。任何小於這道護城河的雜訊尖峰都會無害地落下;接收端仍讀到正確的位元。
給兩個經典家族套上數字。老式的雙極性 TTL 保證 VOH = 2.4 V、VIH = 2.0 V、VOL = 0.4 V、VIL = 0.8 V,所以兩道護城河都很薄:NMH = 2.4 - 2.0 = 0.4 V、NML = 0.8 - 0.4 = 0.4 V。一個 5 V 的 CMOS 閘幾乎滿幅擺到電源軌:VOH ~= 4.95 V、VIH ~= 3.5 V、VOL ~= 0.05 V、VIL ~= 1.5 V,每一側都給出約 1.45 V 的厚護城河。這個差距在實務上極為巨大:半伏特的接地彈跳或耦合進來的串擾,CMOS 一聳肩就抖落,卻會讓 TTL 閘直接穿過它 0.4 V 的容限而翻轉。
這就是為什麼晶片彼此對話時,家族很重要。CMOS 幾乎不抽靜態輸入電流,又能近乎滿幅地在電源軌間擺動,所以它既省電、雜訊容限又大方;較老的雙極性邏輯會吸進實打實的輸入電流,並且只能將就薄薄的容限。麻煩出在交界處——一個 CMOS 輸出可能滿足不了 TTL 輸入的電流需求,更糟的是,兩個位於不同電源軌上的零件,可能連門檻到底在哪都談不攏。這個不匹配,正是下一個點子存在的全部理由。
在不同電壓世界之間做準位轉換
一塊現代的板子是電源軌的拼布——這裡一個 5 V 感測器、那裡一個 3.3 V 微控制器、更深處一個 1.8 V 的處理器核心。你不能就這樣把它們接在一起。把一個 5 V 訊號驅進一個 3.3 V 的輸入,你可能把它推過它的絕對最大額定,逼著電流倒灌過它晶片上的保護二極體,慢慢地把那支腳煮熟。反過來走,一個 3.3 V 的高,可能連一個 5 V 零件的 VIH 都跨不過。要安全地搭起這些電壓域之間的橋,就是準位轉換。
對於一個往下走(5 V 到 3.3 V)的慢訊號,一個樸素的分壓器就夠了:上面取 R1 = 1 k、對地取 R2 = 2 k,輸出便是 5 times 2/(1+2) = 3.33 V——舒舒服服地是個有效的 3.3 V 高。但分壓器是單向的、會白白漏掉一點電流,而且晶片的輸入電容加上那些電阻會組成一個低通,把快邊緣抹糊。往上走(3.3 V 到 5 V)時分壓器全幫不上忙——你需要主動地把它抬起來。
兩個方向通吃的主力,是單顆 MOSFET 準位轉換器:一顆小小的 N 通道電晶體,閘極接到較低的電源軌(3.3 V),兩側各掛一個對自己電源軌的上拉電阻。當 3.3 V 側被拉低,MOSFET 導通,也把 5 V 側拽低;當 3.3 V 側浮成高,MOSFET 保持關閉,5 V 側的上拉便乾淨地把它抬到 5 V。它是雙向的、對匯流排來說夠快,而且——注意看——它其實就只是一顆只能往下拉的電晶體,加上一個往上拉的電阻。記住這幅畫面;它正是本篇接下來要講的那個電路。
開汲極與上拉電阻
你至今見過的大多數輸出都是推挽(或稱圖騰柱):上面一顆電晶體主動把線拉高、下面一顆主動把線拉低,把兩個方向都牢牢地驅動。一個開汲極輸出丟掉了上面那顆電晶體,只留下下面那顆。它只有兩招:把線硬拉到接地,或完全鬆手讓它浮著。它能驅動一個 0;它永遠驅動不了一個 1。(用雙極性電晶體做的同一個點子叫開集極——第 1 篇那顆 LM393 比較器正是這種輸出,這也是為什麼它的擺動自己一個人時,從來不是一個乾淨的邏輯高。)
缺掉的另一半是你的工作,而它就是一個電阻:一個從線接到你選定電源軌的上拉電阻。每當沒有任何電晶體往下拉,上拉就溫和地把線抬成高。這買到兩件美好的事。第一,你靠選擇上拉的電源軌來選擇那個高電壓——所以一個開汲極輸出就是一個內建的準位轉換器:把一顆 5 V 比較器的開集極輸出,透過上拉接到你的 3.3 V 電源軌,出來的就是一個乾淨的 3.3 V 邏輯高,不必多加零件。第二,它讓好幾個輸出共用一條線——這就是下一招。
+3.3 V (or +5 V -- your choice sets the HIGH level)
|
| | pull-up R (you add this)
| |
shared |
line o----+------+------+------+-----> to logic input(s)
| | |
|/ |/ |/ three open-drain outputs:
----| ---| ---| each is a bottom NMOS that pulls
|> |> |> the line to GND, or floats (off).
| | |
GND GND GND
All transistors OFF -> pull-up R lifts the line HIGH.
ANY one transistor ON -> the line is yanked LOW (wired-OR, active low).決定上拉的尺寸,與線或
把那一個電阻定下尺寸,是一個真正的設計抉擇——一場由它的 RC 時間常數所刻畫的拔河。取得太大,線就升得慢吞吞,因為上拉得透過一個大電阻去對匯流排電容充電;取得太小,當線為低時它會持續燒電流,而且下方那顆電晶體可能吸不下足夠的電流去守住一個有效的 VOL。誠實的設計,在這兩道牆之間行走:
- 從吸入電流定出 R_min。下方電晶體必須在吸收 R 的電流時,把線守在 VOL 以下。在一條 3.3 V 電源軌上,若 VOL = 0.4 V 時的吸入預算是 3 mA,則 R_min = (3.3 - 0.4)/0.003 ~= 1 k——絕不要低於此。
- 從上升時間定出 R_max。線是透過 RC、對抗匯流排電容往上爬的;10 到 90 百分比的上升大約是 2.2 times R times C。當 C = 100 pF、上升預算為 1 us 時,你需要 R 大約低於 4.5 k。
- 在窗口之內挑一個。對一條 100 kHz 的 I2C 匯流排,4.7 k 正好落在裡頭:tau = 4.7 k times 100 pF = 470 ns,上升約 1 us,下拉電流也只有 3.3/4.7k ~= 0.7 mA。對一條 400 kHz 的匯流排,上升預算縮到 300 ns,所以降到約 1.8 k。
- 尊重那個取捨。較小的上拉意味著更快、更抗雜訊的線,但更多電流與更銳利的邊緣;較大的上拉意味著更低的功耗,但更慢、更柔的轉態。沒有單一的正確值——只有對你的速度與功耗預算而言正確的值。
現在來看共用一條線的回報。把好幾個開汲極輸出綁到一個上拉上,只有當每一個電晶體都關閉時線才浮成高;只要任何一個打開的瞬間,它就把整條線拽低。在低態有效的訊號約定下,這讀作『任何裝置都可以宣告這條線』——這就是只用電晶體和一個電阻做成的線或邏輯。共用的中斷線、I2C 或 1-Wire 匯流排,以及許多『資料就緒』訊號,都是這樣運作的。你絕不可能用推挽輸出做到這件事:一個驅動高、另一個驅動低,就是一條從電源軌直通接地的短路——讓兩個驅動器都過熱的匯流排爭用。開汲極讓共用不只可行,而且安全。
為什麼混合訊號真的很難
用一個誠實的音收尾,因為這整個階段存在的全部理由,就是把快速數位擺在敏感類比旁邊、放在同一塊板子上,是困難的。每一道乾淨的邏輯邊緣,都是在一兩個奈秒裡跨出好幾伏特的一步,而這份陡峭本身就是一個雜訊源。快速的 dV/dt 會把電流尖峰驅過每一個雜散電容,而回流路徑裡快速的 di/dt 會在走線電感上掉出電壓——那惡名昭彰的接地彈跳。這些尖峰不會乖乖待著:它們會落在你比較器的參考準位、你 ADC 的輸入、你感測器那細小的毫伏節點上,正落在你最承受不起的地方。
那些防禦是下一個階段的主題,但最重要的習慣很簡單。在每一顆晶片的電源腳旁就近放一個去耦電容——一個本地的水箱,讓晶片在邊緣大口吞電流時,那條長長的電源走線永遠不會塌陷。給板子一個紮實的接地層,並把吵雜的數位回流電流擋在安靜的類比接地之外。把類比與數位區段在實體上分開。而且不要把任何邊緣弄得比它需要的更快——一個仍能滿足時序的慢訊號,就是一個安靜的訊號。