從電阻分壓講起
下圖是個簡單的電阻分壓電路,R1 與 R2 的比例是 9:1,所以晶片(Chip)端的 Input 腳位電壓是電源的 1/10,這個計算式在下方,有學過電路學的人應該都會算。
如果你用手指去觸碰 Input 端,Input 會感應到高高低低的電壓,當然口說無憑,要證明這件事情,需要一些小眉角,那也就是為何我會刻意選 9M 與 1M ohm 電阻的原因。
因為這個分壓電路的 1M ohm 就是示波器的輸入阻抗,9M ohm 的部分就是示波器探棒的電阻,也就是所謂的 10X 探棒,只要在探棒接頭與示波器輸入端之間,利用 T 型轉接頭做橋接,就有辦法將 Input 端的接點用導線接出來。
直接來看實例,我拿了一個探棒先接上 T 型 BNC 接頭,再接進示波器。這個 T 型接頭方便我們做實驗,而探棒的探針與 GND 則刻意短路,也就是 V1=0,所以示波器應該要看到一條直線,實際上也是如此,如下圖:
你可以看到 CH2 的旋鈕上我掛了一捲焊錫,這是要拿來當對照組用的,因為接下來我要把焊錫插入 T 型接頭內。如下圖,在焊錫插入 T 型接頭中心導體的瞬間,螢幕出現弦波的擾動,主頻率是 60 Hz,目前每格是 20 mV,其實震幅很小。由於我現在是要測量的對象是示波器的 input,所以即便我用的是 10X 的探棒,示波器的倍數我開的仍然是 1.00:1,也就是 1X。
當然這種振福只有 10 mV 的波形,相信你也看不上眼,可能只當它是雜訊而已,但如果你用手指去碰焊錫,那結果完全不同,如下圖示波器直接破表給你看,我刻意不調整 Scale,這樣視覺效果比較強烈,實際上這是個振福大約 7 V 的 60 Hz 弦波。
7 V 的振幅上下就跨了 14 V,你再也無法忽略它,可能你還會想要消除這種現象,最有效的方法就是在輸入電阻 R2 的 1M ohm 上再並聯一個相對小的電阻,例如並上一個 1K、10K 甚至 100K ohm 的電阻,如此這種雜訊馬上就會消失了。
當然你也可以把探棒 R1 電阻換掉,改串接一個相對小的電阻,一樣能讓雜訊消失,所以 R1 與 R2 的電阻越小,越能讓雜訊變小。
浮接 Floating
延續上面的示範電路, 所謂浮接就是輸入端空接,也就是 R1 的阻值無窮大,所以輸入端不受 V1 影響,此時影響 R2 電壓的因素只剩下兩個:
Input 接出來的導線長度
輸入阻抗R2的大小
導線長度越長,受環境磁場變化的程度越高,感應電動勢 EMF 推動的電荷的力量就越大,同時搭配輸入阻抗 R2 越大,由 EMF 推入的電荷產生的電壓差就越大,反之若 R2 越小,流入的感應電荷在 R2 兩端形成的電壓就越小。
高阻抗容易變成天線
所以如果 Input 空接,剛好輸入端又是高阻抗,那麼你那空接的 pin 腳就很容易受到外界磁場擾動的影響,換句話說它變成天線了。前面有一張圖是用手觸碰示波器輸入端,造成非常大的擾動,就是因為人體擔任了天線的角色。
這個磁場擾動通常來自台電的 60 Hz 電流,如果你是在歐洲那就會是 50 Hz,磁場變化讓導線感應出微小的電流,當電流通過 R2 的 1M ohm 阻抗時,便轉換成了電壓,因而顯示在示波器螢幕上,這個 Input 端的導線其實就是一條天線。
當 R2 輸入阻抗越高,或 Input 接出來的導體面積越大,導線長度越長,這個接在 Input 上的導線對環境就越敏感,一點點磁場的風吹草動,例如隔壁開個電風扇,可能就會讓你的示波器出現劇烈的變化。
那為什麼當 R1、R2 換成如 1K、10K ohm 等級的電阻時,不會有這種現象?其實它並不是沒有電磁感應的現象,而是它的感應小到你無法察覺,所以你忽略它了;有人說 IC 的腳這麼短,會有影響嗎?我的經驗是不一定,但為了電路的穩定,一定不要讓 Input 空接。
浮接造成誤動作
雖然擾動的能量很小,但是電晶體的導通臨界電壓,一如它的單位「電壓」所示,它是認電壓的,電壓只要到了臨界值它就作動了,只是這感應來的電壓可能忽高忽低,會讓你的電晶體有時 ON 有時OFF。
這個意思就是說,原本沒有要讓電晶體作動的 V1,現在因為外界的擾動反而讓電晶體產生作動,這就是誤動作,你沒有要它動但它卻動了,十足像個靈異現象,而一旦發生誤動作,事情可大可小,小則電燈該亮不亮,大則鐵捲門壓到人或車,所以工程師絕對不能讓自己設計的產品產生誤動作。
輸入腳位不能浮接
為了避免誤動作,IC 的輸入腳位絕不能空接或說浮接,一定要串接一個電阻到 Vcc 或是 GND,我們稱為 Pull High 或 Pull Low。
如此一來,如果沒有訊號接入,Input 腳位仍會有個預設值,Pull High 的腳位預設準位就變成 High,若輸入訊號是 Low,Input 仍然會收到 Low,因為中間有個 pull high 電阻會形成壓降,頂多只是裡面有電流,多消耗了一些功率就是了。
不過現在的晶片越來越有彈性,很多腳位都是所謂的泛用型輸入輸出 GPIO(General Purpose Input/Output),你必須寫程式將它設置成為 Input 它才會是 Input,這種情況就會變成你一開始就要先規劃好哪些腳位要當 Input,把 Pull High/Low 電阻設計到 layout上。
到底是誰的問題?
通常計畫趕不上變化,做案子總會有半途變更規劃的時候,這時就很容易忘記要把 Pull High 電阻加上去,如果你是一人包案那可能還好處理,如果是軟硬體分開兩個 team 處理,當軟體變更設定需要硬體來配合,但硬體修改設計需要時間,如果時程拖到又要被責怪的話,就會經常上演「為什麼是我被罵」的戲碼。
通常做案子基本上就是這樣,會在吵吵鬧鬧中進行,酸甜苦辣都有,這時溝通就很重要,如果你的合作夥伴和你很有默契,那你應該上輩子有燒好香,好好惜福吧。
為什麼會當機?
記得十多年前助教正在一個新平台上做開發,由於是下一代延伸產品,所以理論上只要 CPU 沒變,記憶體也裝得下程式,這個平台應該就能順利開機,無奈事與願違,開機 10 次大概會有 3~4 次當機的機會,心想這比例也太高了吧!
妙的是前一天完全沒有這種現象,程式沒有拿錯版本,電路板也是同一塊,這就怪了,讓你猜猜這到底是怎麼回事。
於是我把程式的 Debug flag 打開,執行程式後 UART 開始跳出開機過程的訊息,很明顯當機的地方位於 UART 初始化這一步,因為板子上有 2 組 UART,第一組就是我目前正在用的 Debug Port,但是第二組還沒使用,就是它造成當機,推測是有什麼訊號送到第二組 UART 去,讓它誤動作了。
於是我拿了示波器接上 UART2 的接收腳位 RX,觀察看看是否有怪訊號跑進去,說奇怪,示波器接上後,居然每次都能順利開機,真是見鬼了!這種情況我心裡大概有譜,可能是 RX 浮接、或是電容值不夠之類的,因為探棒本身有電阻 10M ohm,也有電容約 30p 左右,只要探棒掛上測點,它與待測電路自然會產生排除雜訊的效果。
於是我開始檢查線路圖,果然發現 UART 的 RX 腳位真的是浮接 Floating 的,於是拿了個電阻將它 Pull high,就完全正常了。
但為什麼這樣會當機?經過一連串的程式碼追蹤,原來是因為當 UART RX 浮接時,如前面所說電壓會有時 H 有時 L,而 L 訊號便會觸發 UART 的中斷,因為 RX 的「資料開始 Start」訊號是以 L 準位作為識別,當 RX 收到第一個 L,便會觸發 UART 的中斷訊號,接著就會開始執行中斷服務函式 ISR(Interrupt Service Routine) 。
只是目前正在開機中,而中斷向量還要再過幾行程式才會掛進來,或是說 ISR 的指標還沒有寫入中斷向量表,那裡面都還是初始值或亂數,如果現在發生中斷,CPU 就會亂跳到某個記憶體,並將它視為 ISR 來執行,想當然爾就當機了。
那為什麼前一天都沒事?這只有天曉得,浮接 Floating 的電壓對於環境有很高的敏感度,天線周遭的東西擺放位置與材質,都會影響電壓的高低,所以只要遇到Floating,就是未知數。
當機的解法
所以這種當機的解法,分為兩方面。軟體的部分,在 ISR 掛進來之前,中斷功能不可以開啟 Enable,這其實是寫韌體的人該有的 Sense,通常是新手才會犯的錯誤,但系統大、軟體的 Call Stack 又深、人手少,有時候就會犯這種錯;硬體的解法,就是在 UART RX 端加上 Pull High 電阻,讓輸入電壓不再浮動。
雖然軟體或硬體只要有一邊修改就可以克服這個狀況,但我認為兩邊一起修改才是上策,距離潛在的 Bug 才會遠一點,總之別讓 Input 浮接,不然你將來會有忙不完的事情。