鮑率誤差是怎麼來的?
UART 用一個除數把時脈除下來得到鮑率。以 16 倍取樣為例,鮑率 = 時脈 ÷ (16 × 除數),除數只能是整數,所以實際鮑率常常和目標差一點。例如 16 MHz 要跑 115200:16,000,000 ÷ (16 × 115200) ≈ 8.68,取最接近的 9,實際鮑率是 111,111,誤差 −3.5%。
工具會選最接近的除數,算出實際鮑率和誤差 =(實際 − 目標)÷ 目標。
誤差多少還能用?
接收端在每個位元的中間取樣。8N1 格式一個字元有 10 個位元,到最後的停止位元時,取樣點的偏移不能超過半個位元,所以兩端的誤差加起來理論上要小於約 5%。再扣掉取樣精度和訊號邊緣的影響,實務上常建議每一端不要超過 ±2%。工具的判斷是:1% 以內可以放心用,1% 到 2% 通常可以用,超過 2% 就容易收到亂碼。
鮑率專用的石英振盪器
這些頻率剛好是 1.8432 MHz(115200 × 16)的整數倍,常用鮑率的誤差都是 0%。
| 時脈 | 115200 的除數(16 倍取樣) |
|---|---|
| 1.8432 MHz | 1 |
| 3.6864 MHz | 2 |
| 7.3728 MHz | 4 |
| 11.0592 MHz | 6 |
| 14.7456 MHz | 8 |
| 18.432 MHz | 10 |
5 V 和 3.3 V 的 UART 怎麼接?
5 V 裝置(例如 Arduino Uno)的 TX 直接接到 3.3 V 裝置(例如 ESP32、樹莓派)的 RX,可能會損壞 3.3 V 那端。簡單的做法是在中間加一組分壓電阻,把 5 V 降到 3.3 V 左右:R1 = 1 kΩ、R2 = 2 kΩ 時,RX 收到 5 × 2 ÷ (1 + 2) ≈ 3.33 V。其他組合可以用分壓電阻計算算。
反方向(3.3 V 的 TX 接 5 V 的 RX)通常可以直接接,因為很多 5 V 晶片在 3 V 左右就認得是高電位,但請查 5 V 那端資料手冊的 VIH;不夠的話要改用電位轉換 IC。兩邊的 GND 一定要接在一起。
常見問題
Arduino Uno 用 16 MHz 跑 115200,為什麼還能通?
Arduino 在 115200 時用 8 倍取樣(U2X=1),誤差是 +2.1%。Uno 上負責 USB 轉序列埠的 ATmega16U2 也是 16 MHz,誤差一樣,兩端的偏差剛好抵消。如果接的是時脈準確的 USB 轉 UART 晶片或其他裝置,就可能出錯,可以改用 57600 以下或 250000、500000、1000000 這類整除的鮑率。
STM32 的 BRR 怎麼設定?
16 倍取樣(OVER8=0)時,BRR = 時脈 ÷ 鮑率,四捨五入成整數,小數部分已經包含在 BRR 的低 4 位元裡。例如 72 MHz、115200:72,000,000 ÷ 115200 = 625 = 0x271。時脈要用 USART 所在匯流排的時脈(APB1 或 APB2)。8 倍取樣(OVER8=1)的 BRR 編碼方式不同,工具沒有支援。
AVR 的 UBRR 是什麼?
AVR 的 UBRR 暫存器要填「除數 − 1」。工具在 16 倍和 8 倍取樣的模式下會一起列出 UBRR 的值。