兩個語言不通的世界
想像你把一支溫度計交給一台只會用手指頭數數的電腦。溫度計裡的水銀是*連續*上升的——它可以停在 23.4°C、23.47°C,或中間任何一個值,有著無限的細微差別。而電腦的暫存器裡,永遠只能存放整數。在平滑的物理世界與離散的數位世界之間,必然要有一次翻譯。那位翻譯官就是類比數位轉換器(ADC),認識它,正是嵌入式系統從抽象程式碼變成觸摸真實世界的那一刻。
你日後接線會遇到的幾乎每一個感測器,講的都是類比[[voltage|電壓]]這種語言。光電二極體變亮,輸出就從 0.2 V 爬到 2.9 V;麥克風在一個安靜的中點附近抖動幾十毫伏;電位器的旋鈕一轉,滑動端電壓就沿著行程平滑掃過。這些都還不是數字——它們是導線上實實在在的電壓。ADC 的工作,就是盯著那條導線,一遍又一遍回答同一個問題:*相對於一個已知的最大值,這個電壓有多高?*
解析度、參考電壓,與一階的大小
每顆 ADC 上都標著兩個數字,它們決定了精度的一切。第一個是解析度,以位元表示。一顆 *n* 位元轉換器把輸入範圍切成 2ⁿ 階——8 位元 ADC 有 256 階(0…255)、10 位元有 1024 階(0…1023)、12 位元有 4096 階。第二個是參考電壓 V_ref:能讓輸出達到最大碼的那個輸入電壓。輸入 V_ref 你會讀到滿刻度;輸入 0 V 讀到零;中間的一切,則被均勻地切分。
從這兩個數字你能推導出最重要的一個量,就是階距,有時稱為 *LSB 電壓*——能讓輸出碼剛好加一的那個電壓變化量。它就是參考電壓除以階數:
step_size = V_ref / 2^n
Worked example — 10-bit ADC, V_ref = 3.3 V
--------------------------------------------
levels = 2^10 = 1024
step_size = 3.3 V / 1024 = 0.003222 V
≈ 3.2 mV per code
So a voltage on the pin maps to a code:
code = round( V_in / step_size )
= round( V_in * 1024 / 3.3 )
V_in = 1.65 V -> code = round(1.65/0.003222) = 512 (mid-scale)
V_in = 0.10 V -> code = round(0.10/0.003222) = 31
V_in = 3.30 V -> code = 1023 (full-scale)
V_in = 3.40 V -> code = 1023 (clipped! ADC can't see past V_ref)那 ~3.2 mV,就是*這顆轉換器能做出的最細區分*。兩個相差不到 3.2 mV 的電壓,可能會落到同一個碼上——ADC 真的分不出它們。這是你遇到的第一個實際工程限制:若你的感測器只擺動 5 mV 的有用訊號,在 3.3 V 參考下用 10 位元 ADC 只剩下勉勉強強兩個碼的可用範圍,根本沒救。解法不外乎:更多位元、把參考電壓縮小到貼合訊號,或在訊號進入轉換器*之前*用放大器(儀表放大器是經典選擇)把它放大。
量化:無可避免的捨入誤差
因為輸出必須是整數,ADC 被迫把每一個連續輸入*捨入*到最近的刻度。這個捨入動作叫做量化,而真實電壓與該碼所代表的值之間那一點點差距,就是量化誤差。它不是 bug——而是把無限精度的世界塞進有限位元時,根本上、設計上必然的後果。你能做到的極限,就是把這個誤差控制在 ±½ 階之內。
Analog input (smooth ramp) ADC output (staircase) V code | / | ___ | / | _| | / quantize | _| each riser | / ===========> | _| = one step (3.2 mV) | / | _| | / || flat tread = a band of |/_____________ t |____________ inputs that all read alike The vertical gap between the smooth line and the nearest step edge, at any instant, is the quantization error: ≤ ±½ LSB.
精妙之處在這裡。如果我們把那個捨入當作灑在真實訊號上的隨機雜訊,它有一個已知的大小,於是讓我們能用一條著名的經驗法則,預測一顆理想轉換器*所能達到的最佳*品質:每多一位元解析度,大約為你換來 6 dB 的動態範圍。對一顆完美的 *n* 位元 ADC、輸入滿刻度正弦波,完整結果是 SNR ≈ 6.02 n + 1.76 dB。因此 10 位元轉換器上限約 62 dB;16 位元音訊轉換器約 98 dB。沒有任何真實晶片能突破它——這是純粹由「捨入」這個動作所設下的天花板。
取樣:多久測一次,以及測太慢的陷阱
解析度回答的是我們把每個值量得*多細*;取樣回答的則是*多久測一次*。ADC 並非連續盯著訊號——它每隔固定時間拍一張快照,這個頻率就是取樣率 f_s,單位是每秒取樣數(Hz)。讀取緩慢漂移的電池溫度,每秒十次已經奢侈;擷取音訊,你需要好幾萬次;數位化無線電訊號,則要好幾千萬次。你選的速率,幾乎完全取決於訊號能抖得多快。
而且有一條你騙不過去的鐵律。奈奎斯特–香農取樣定理說:你的取樣率必須*高於*訊號中最高頻率的*兩倍*。取樣太慢,快速的波就會偽裝成慢速的波——一個從未真正存在的幽靈。這種贗品叫做混疊(aliasing),是新手毀掉自己資料最常見的一種方式。它和老電影裡馬車輪看起來倒轉是同一個效應:攝影機的影格率對輪輻取樣不足。
True 7 Hz sine, sampled at only 8 Hz (too slow — need > 14 Hz):
real signal: /\ /\ /\ /\ /\ (7 cycles / sec)
sample points: o o o o
what you see: \______/ \______/ a fake ~1 Hz wave!
Rule: f_s > 2 * f_max (Nyquist criterion)
Guard: real systems use an *anti-aliasing* low-pass filter BEFORE
the ADC to kill anything above f_s/2 *before* it can alias.回程:DAC,以及用 PWM 假裝一個 DAC
到目前為止全都是單向的:世界 → 數字。但你常常需要走相反方向——數字 → 世界。要設定馬達的轉速參考、在老式顯示器上畫出某個像素的灰階、或把音訊推送到喇叭,你的程式握著一個數字,卻需要在腳位上得到一個*電壓*。這就是數位類比轉換器(DAC)的工作,等於把 ADC 倒著跑:交給它碼值 512、配 3.3 V 參考,它就把腳位驅動到 1.65 V。
實際的關鍵在這裡:許多便宜的微控制器內建了 ADC,卻完全沒有 DAC。經典的變通辦法——也是第 2 階要你學脈衝寬度調變的原因——就是一支 PWM 腳位加一道簡單的低通濾波器,能假裝得出奇地好。PWM 噴出一個方波,在每個週期裡有一段比例完全導通(即*工作週期*),其餘時間完全關斷。把這個方波對時間取平均,你就得到一個正比於工作週期的穩定直流位準:在 3.3 V 電源上 25% 工作週期,平均下來約 0.825 V。
PWM + RC low-pass filter = a cheap 1-channel DAC
PWM pin o───[ R ]───┬───o V_out (smooth analog level)
│
=== C
│
GND
Duty cycle -> average output voltage
duty = D (0..1), V_out ≈ D * V_supply
25% duty, 3.3 V -> V_out ≈ 0.825 V
50% duty, 3.3 V -> V_out ≈ 1.65 V
75% duty, 3.3 V -> V_out ≈ 2.475 V
Design rule: make the filter's time constant RC much LONGER than the
PWM period (RC >> 1/f_pwm) so the square wave is smoothed to ripple,
but not so long that V_out can't keep up when you change the duty.訊雜比:整條鏈路的品質上限
解析度告訴你轉換器能跨出的*最細一階*,卻沒告訴你那一階是否*有意義*。如果你的接線拾取了 20 mV 的電氣雜訊,那麼在 3.3 V / 10 位元 ADC 上,你最低的*六個碼*全是垃圾——它們是在隨雜訊亂跳,不是訊號。衡量「有用程度」的誠實指標,是訊雜比(SNR):你在意的訊號,相對於墊在它底下的雜訊有多大,幾乎總是以分貝表示。
兩道天花板合起來決定你實際得到的 SNR。第一道是上一節的量化下限(≈ 6.02 n + 1.76 dB)——你永遠不可能做得比位元數所允許的更好。第二道是其他一切:電阻裡的熱雜訊、電源漣波、電路板佈線、吵雜的參考電壓、感測器本身。買了一顆 16 位元 ADC,卻餵給它一個埋在相當於 12 位元雜訊裡的訊號,那是白花錢——決定你真實精度的是雜訊,不是位元。這也是為什麼量測儀器(第 6 階)會對接地、屏蔽與參考品質如此講究。
- 讓參考電壓配合訊號。選擇 V_ref,讓真實訊號填滿輸入範圍的大部分——浪費的範圍就是浪費的位元。
- 先濾波再取樣。在 ADC 前放一道抗混疊低通濾波器,阻止高頻雜物摺疊進你的訊號頻帶。
- 取樣要夠快。讓 f_s 高於你最高真實頻率的兩倍,並為濾波器平緩的滾降留些餘裕。
- 用平均挖出細節。平均 N 個獨立取樣,可把隨機雜訊降低約 √N 倍——是在慢速訊號上找回次-LSB 精度的廉價方法。
- 留意佈線。讓類比輸入走線短、遠離切換與 PWM 線路;一塊乾淨的電路板,價值可抵兩個額外位元。