試實(shí)戰(zhàn))
1. 為什么 Pico 的串口值得單獨(dú)寫一篇樹莓派 Pico 這塊小板子很多人買回來第一件事就是點(diǎn)燈第二件事大概是讓板子跑個(gè) MicroPython 然后打印Hello World。但真正到了要跟傳感器通信、接顯示屏、調(diào)試物聯(lián)網(wǎng)設(shè)備甚至做 Server 端聯(lián)調(diào)的時(shí)候繞不開的就是 UART 串口??梢哉f串口是你在 Pico 上做一切“板外交互”的地基。我最初接觸 Pico 的時(shí)候也天真地以為串口就是兩根線、一收一發(fā)能通就行。結(jié)果真上手后發(fā)現(xiàn)硬件引腳怎么復(fù)用得想清楚MicroPython 里UART()的參數(shù)怎么配才不丟數(shù)據(jù)調(diào)試時(shí)是看print還是用邏輯分析儀這中間全是隱形門檻。再加上很多人習(xí)慣拿它跟 Arduino 比Pico 的串口數(shù)量、引腳映射、中斷收發(fā)機(jī)制又不一樣抄 Arduino 的代碼過來大概率直接翻車。這篇文章不打算泛泛講串口理論我會(huì)直接拆成四塊硬件特性是什么、MicroPython 里怎么寫最穩(wěn)、調(diào)試工具有哪些怎么選、以及我實(shí)際踩過的一些坑。適合剛?cè)胧?Pico 的玩家也適合用 Pico 做了幾個(gè)小項(xiàng)目、但想進(jìn)一步提升串口通信穩(wěn)定性的朋友。2. Pico 串口硬件特性盤點(diǎn)2.1 兩顆 UART 到底夠不夠用RP2040 芯片上集成了兩個(gè)硬件 UARTUART0 和 UART1每個(gè)都支持標(biāo)準(zhǔn)的全雙工收發(fā)。全雙工意思就是可以同時(shí)發(fā)送和接收數(shù)據(jù)這對(duì)做控制類場(chǎng)景很重要我們后面講的舵機(jī)控制和讀取傳感器反饋很多時(shí)候需要“邊發(fā)命令邊聽?wèi)?yīng)答”。不過“有 UART0 和 UART1”這件事只是第一步真正的限制在于引腳映射。每個(gè) UART 都有一組默認(rèn)引腳同時(shí)也允許映射到板上其他引腳。對(duì)新手來說熟悉的往往是默認(rèn)那組UART0 TX 默認(rèn) GP0RX 默認(rèn) GP1UART1 TX 默認(rèn) GP4RX 默認(rèn) GP5這兩個(gè)默認(rèn)組合已經(jīng)覆蓋絕大多數(shù)場(chǎng)景比如接 GPS 模塊、接藍(lán)牙模塊、接 ESP8266 透?jìng)?。但如果你做的?xiàng)目里GP0 已經(jīng)被 PWM比如驅(qū)動(dòng)舵機(jī)占了或者 GP1 要留著做按鍵掃描此時(shí)就得用 UART0 的備用引腳映射TX 映射到 GP12RX 映射到 GP13。于是我給新手的第一個(gè)建議拿到板子后不要直接接線先想清楚每個(gè) GPIO 的職責(zé)。引腳復(fù)用是 Pico 做多路串口設(shè)計(jì)的核心思路但也容易讓你布線時(shí)踩進(jìn)沖突的坑里后面我們會(huì)專門講怎么排查這種問題。2.2 電平標(biāo)準(zhǔn)與接線的物理常識(shí)Pico 的 GPIO 電平是 3.3V這決定了它的 UART 引腳不能直接接 5V 的設(shè)備比如舊款 Arduino 的 5V 串口輸出、某些 5V 供電的 GPS 模塊。很多新手在接線時(shí)最大的誤區(qū)是只要 TX 接 RX、RX 接 TX、GND 共地就行忽略了電平匹配。如果對(duì)方設(shè)備標(biāo)明是 5V 邏輯你還需要在通信線上加電平轉(zhuǎn)換模塊。不是所有板子“稍微過壓”都能扛住RP2040 的引腳不是完全耐 5V 的。另外接線長(zhǎng)度也要控制。串口的波特率越高對(duì)線材和布線越敏感。我測(cè)試過在 115200 波特率下用 20 厘米長(zhǎng)的杜邦線連接傳感器基本沒問題一旦把線換成 1 米以上就會(huì)出現(xiàn)偶發(fā)亂碼。所以布線原則是能短則短盡量用雙絞線或者屏蔽線特別是走長(zhǎng)距離通信時(shí)這個(gè)細(xì)節(jié)能省掉很多排查時(shí)間。2.3 從單片機(jī)串口到板級(jí)串口的區(qū)別這里還想做一個(gè)概念上的對(duì)比。當(dāng)我們說“Pico 串口通信”既指 RP2040 芯片引出的 UART 引腳單片機(jī)串口也指板載 USB 轉(zhuǎn)串口MicroPython 的 REPL 終端。兩者是完全不同的鏈路芯片 UART通過 GP0/GP1 等引腳對(duì)外通信接傳感器、接 PC 串口助手需要 USB 轉(zhuǎn) TTL 工具USB 串口Pico 板載的 microUSB 連接到電腦后會(huì)被識(shí)別成一個(gè)虛擬串口設(shè)備MicroPython 的交互式解釋器REPL就走這個(gè)通道很多人剛接觸 Pico 時(shí)會(huì)在 Thonny 的 Shell 窗口里看到 print 輸出就以為那就是串口調(diào)試。嚴(yán)格說這是 USB CDC 虛擬串口并不是芯片 UART 引腳上的數(shù)據(jù)。理解這兩者的區(qū)別是后面進(jìn)行真正串口設(shè)備調(diào)試的基礎(chǔ)。3. MicroPython 串口編程從入門到順手3.1 初始化參數(shù)的“靈魂三問”MicroPython 的machine.UART接口寫起來不復(fù)雜但初始化時(shí)那幾個(gè)參數(shù)如果不理解含義很容易寫出“能跑但是不穩(wěn)定”的代碼。以一個(gè)典型的傳感器交互為例from machine import UART, Pin import time # 使用 UART1默認(rèn)引腳 TXGP4, RXGP5 uart1 UART(1, baudrate9600, txPin(4), rxPin(5), bits8, parityNone, stop1)這里主要解釋兩個(gè)容易被忽略的點(diǎn)。第一是波特率它決定了每秒傳輸多少 bit。9600 和 115200 是嵌入式里最常見的兩個(gè)值傳感器模塊一般默認(rèn) 9600像 ESP8266 AT 固件、多數(shù) GPS 模塊都是這個(gè)值第二是tx和rx引腳參數(shù)在高版本 MicroPython 固件里可以不傳直接走默認(rèn)引腳但如果你希望用備用引腳比如前面提到的 GP12/GP13必須顯式指定。bits8、parityNone、stop1這三個(gè)組合是通用的 8N1 格式絕大多數(shù)串口設(shè)備都認(rèn)這個(gè)格式。除非你明確知道模塊手冊(cè)里寫的是 7 位數(shù)據(jù)位或帶校驗(yàn)位否則不需要改動(dòng)。初始化之后只需注意一點(diǎn)MicroPython 不會(huì)自動(dòng)在初始化時(shí)把 TX 置為高電平。如果你接的設(shè)備對(duì)串口空閑電平有要求比如某些 RS485 模塊可能需要在初始化后手動(dòng)拉高這個(gè)細(xì)節(jié)在調(diào)試中比較隱蔽。3.2 收發(fā)數(shù)據(jù)讀和寫的三種姿勢(shì)寫數(shù)據(jù)這件事MicroPython 提供了兩種常用方法write()和writeinto()。區(qū)別不大實(shí)際項(xiàng)目里用write()最多因?yàn)樗苯咏邮茏址蛘咦止?jié)串uart1.write(bAT\r\n) # 發(fā)送 AT 指令例如接 ESP8266 uart1.write(Hello Pico\n) # 直接傳字符固件會(huì)自動(dòng)編碼推薦在通信時(shí)統(tǒng)一用 bytes 類型也就是前面加b前綴。如果你用字符串傳中文MicroPython 會(huì)用 UTF-8 編碼部分下位機(jī)對(duì)這種編碼不敏感但部分模塊需要的是純 ASCII直接傳字符串可能出亂碼。讀數(shù)據(jù)則有幾種思路。最簡(jiǎn)單的是輪詢式用any()判斷緩沖區(qū)是否有數(shù)據(jù)if uart1.any(): data uart1.read() print(data)這種方式適合測(cè)試腳本邏輯清晰也不容易出錯(cuò)。缺點(diǎn)是如果數(shù)據(jù)不是一次到齊的你讀到的一半可能是個(gè)不完整的協(xié)議幀。更穩(wěn)的做法是把讀數(shù)據(jù)放到while循環(huán)里定義一個(gè)接收緩沖區(qū)先把滾動(dòng)數(shù)據(jù)存起來等收到結(jié)束符或完整幀長(zhǎng)度后再統(tǒng)一解析。MicroPython 也支持 UART 中斷接收通過irq()方法綁定處理函數(shù)def uart_handler(uart): data uart.read() print(rx:, data) uart1.irq(triggerUART.IRQ_RX, handleruart_handler)但這套機(jī)制在 MicroPython 固件版本里支持程度不太一致實(shí)測(cè)在 Pico 上某些固件更新后中斷回調(diào)會(huì)偶發(fā)失效。如果你項(xiàng)目的實(shí)時(shí)性要求很高建議直接用 C/C SDK 寫接收中斷如果只是用 MicroPython 做快速原型驗(yàn)證輪詢加緩沖區(qū)方式其實(shí)足夠穩(wěn)。3.3 發(fā)送十六進(jìn)制數(shù)據(jù)的正確姿勢(shì)很多傳感器模塊的指令是十六進(jìn)制數(shù)組比如“讀取版本號(hào)”對(duì)應(yīng)的指令可能是0xAA 0x55 0x01 0x00。新手容易犯的錯(cuò)誤是直接把字符串AA550100寫進(jìn)uart.write()結(jié)果模塊完全沒反應(yīng)。正確做法是構(gòu)造字節(jié)數(shù)組cmd bytes([0xAA, 0x55, 0x01, 0x00]) uart1.write(cmd)如果你需要?jiǎng)討B(tài)拼包可以這樣cmd bytearray() cmd.append(0xAA) cmd.append(0x55) cmd.append(0x01) cmd.append(0x00) # 計(jì)算校驗(yàn)和 checksum (0xAA 0x55 0x01 0x00) 0xFF cmd.append(checksum) uart1.write(bytes(cmd))要點(diǎn)是模塊要什么格式你就按什么字節(jié)結(jié)構(gòu)給它不要在中途做編碼轉(zhuǎn)換。很多人卡在“模塊沒反應(yīng)”這類問題上最后排查出來就是編碼不對(duì)。3.4 一個(gè)可復(fù)用的串口收發(fā)小框架下面是我整理的一個(gè)通用框架。每次接新模塊時(shí)我習(xí)慣先套這個(gè)框架驗(yàn)證能不能通信再往里面填業(yè)務(wù)邏輯from machine import UART, Pin import time class SerialManager: def __init__(self, uart_id1, tx_pin4, rx_pin5, baud9600): self.uart UART(uart_id, baudratebaud, txPin(tx_pin), rxPin(rx_pin)) self.rx_buffer bytearray() def send_raw(self, data: bytes): self.uart.write(data) def send_str(self, s: str): self.uart.write(s.encode(utf-8)) def read_available(self): while self.uart.any(): self.rx_buffer.extend(self.uart.read()) return bytes(self.rx_buffer) def clear_buffer(self): self.rx_buffer.clear() # 使用示例 ser SerialManager() ser.send_str(AT\r\n) time.sleep(0.1) resp ser.read_available() print(Response:, resp) ser.clear_buffer()這個(gè)框架的好處是把收發(fā)分離你只需要關(guān)心send_*和read_available兩個(gè)接口不用每次都重復(fù)寫any()判斷邏輯。實(shí)測(cè)下來調(diào)試效率提升明顯。4. 串口調(diào)試工具實(shí)戰(zhàn)對(duì)比與選型4.1 五類工具的定位與適用場(chǎng)景串口調(diào)試這件事單靠一個(gè)“串口助手”并不能覆蓋所有場(chǎng)景。我按用途把常用工具分成了五類基礎(chǔ)串口助手用來發(fā)指令、看 ASCII/HEX 返回USB 轉(zhuǎn) TTL 模塊用來把 Pico 的 UART 引腳接到電腦邏輯分析儀用來觀察波形和時(shí)序確認(rèn)數(shù)據(jù)是否真的發(fā)出去了串口監(jiān)聽/分析軟件比如 Python pyserial 腳本、VSPD 虛擬串口顯示器類工具像 Pico 自帶的 REPL 終端Thonny、minicom先區(qū)分一個(gè)基本概念如果你是用 Pico 的 USB 口microUSB連電腦那么在設(shè)備管理器里看到的 COM 口是 USB CDC 虛擬串口只能用于 MicroPython REPL 交互和打印輸出。如果你想跟 Pico 的 UART 引腳通信也就是 GP0/GP1 那一路需要用 USB 轉(zhuǎn) TTL 模塊把 Pico 的 TX/RX 接到電腦。4.2 一些主流工具的使用心得先說說挺常用的 USB 轉(zhuǎn) TTL 模塊。市面上最常見的方案是 CP2102 和 CH340前者穩(wěn)定一點(diǎn)后者便宜大碗。Mac 用戶要注意 CH340 在 macOS 上偶爾掉驅(qū)動(dòng)出現(xiàn)斷連時(shí)先看ls /dev/tty.*有沒有設(shè)備。Windows 上一般裝好驅(qū)動(dòng)后在“設(shè)備管理器”里看 COM 口號(hào)就行。再比如用 PySerial 做壓力測(cè)試是最靈活的組合。普通串口助手手動(dòng)點(diǎn)按鈕發(fā)數(shù)據(jù)效率太低真實(shí)項(xiàng)目里往往要連續(xù)發(fā)幾百條指令驗(yàn)證穩(wěn)定性。我經(jīng)常寫這樣的腳本import serial import time ser serial.Serial(COM10, 115200, timeout1) cmd bytes([0xAA, 0x55, 0x03, 0x00]) ok_count 0 total 200 for i in range(total): ser.write(cmd) resp ser.read(10) if len(resp) 0: ok_count 1 time.sleep(0.02) print(f{ok_count}/{total} received response) ser.close()這對(duì)判斷模塊的響應(yīng)率、丟包率非常直觀。然后是邏輯分析儀。如果你懷疑數(shù)據(jù)根本沒從 Pico 引腳出來或者波形亂七八糟邏輯分析儀是定位問題最快的工具。邏輯分析儀把 TX/RX 信號(hào)按時(shí)間軸顯示成高/低電平序列你可以肉眼看到波特率是否匹配、起始位是否正常。需要強(qiáng)調(diào)的是當(dāng)信號(hào)完全無響應(yīng)時(shí)建議先用邏輯分析儀觀測(cè)硬件波形而不是反復(fù)調(diào)軟件。因?yàn)榇谕ㄐ拧盁o聲無息”的問題多半是物理連接、電平、引腳映射或波特率調(diào)軟件很難定位。4.3 從熱詞中延伸的兩個(gè)經(jīng)典調(diào)試場(chǎng)景我注意到最近搜索“unity pico會(huì)出現(xiàn)indexoutofrangeexception: renderpassindex”以及“宿主機(jī) windows 如何通過串口與 vmware 中 linux 通信”的人越來越多這兩個(gè)其實(shí)都是串口聯(lián)調(diào)的典型例子。先說 Unity 和 Pico。很多人做 VR 項(xiàng)目用 Unity 作為上位機(jī)界面用 Pico 當(dāng)硬件控制器。Unity 通過串口發(fā)數(shù)據(jù)給 PicoPico 解析之后再執(zhí)行動(dòng)作比如開燈或者調(diào)電機(jī)。此時(shí) Unity 里用的 SerialPort 類底層調(diào)用的也是系統(tǒng)串口 API思路和單片機(jī)串口完全一致差異只是解析高頻數(shù)據(jù)時(shí)注意丟包。反正我在 Unity 里串口通信時(shí)第一件事就是設(shè)置較短的 ReadTimeout避免主線程卡死。再說 Windows 宿主機(jī)和 VMware 里 Linux 的串口共享。這個(gè)問題常見于嵌入式開發(fā)編譯和燒錄在 Windows 上完成但運(yùn)行環(huán)境在虛擬機(jī)里的 Linux 上。最簡(jiǎn)單的方式是讓 Windows 和 Linux 共享同一個(gè) COM 口VMware 支持“Connect”這個(gè)串口設(shè)備給虛擬機(jī)但注意物理串口同一時(shí)間只能被一個(gè)系統(tǒng)占用你需要關(guān)閉宿主機(jī)的串口監(jiān)視程序。更穩(wěn)的方案是宿主機(jī)跑一個(gè) TCP 轉(zhuǎn)串口服務(wù)虛擬機(jī)里用 socat 把 TCP 端口映射成虛擬串口。這樣兩邊都能訪問同一個(gè)物理串口不沖突。這個(gè)方案我實(shí)際用下來穩(wěn)定性尚可特別適合需要兩邊同時(shí)觀察日志的場(chǎng)景。5. 串口通信典型應(yīng)用實(shí)戰(zhàn)舵機(jī)控制5.1 通過串口命令控制舵機(jī)的整體思路串口通信的經(jīng)典應(yīng)用之一就是 Pico 作為舵機(jī)控制板接收上位機(jī)PC 或手機(jī)發(fā)來的角度指令然后產(chǎn)生 PWM 信號(hào)控制舵機(jī)。舵機(jī)控制使用的是 50Hz 的 PWM也就是周期 20ms占空比在 2.5%~12.5% 之間對(duì)應(yīng) 0°~180°。RP2040 的 PWM 精度足夠高M(jìn)icroPython 里可以很方便地控制。串口在這套系統(tǒng)里的角色是“指令入口”。上位機(jī)發(fā)來類似S90這樣的文本指令Pico 解析出角度值后映射到 PWM 占空比這就是一個(gè)完整的串口控制鏈路。5.2 從串口指令到 PWM 輸出的完整代碼下面這段代碼實(shí)現(xiàn)了一個(gè)通過 UART 控制舵機(jī)的完整流程。接收串口字符串解析角度值然后設(shè)置 PWM 占空比from machine import UART, Pin, PWM import time # 初始化 UART1TXGP4, RXGP5 uart1 UART(1, baudrate9600, txPin(4), rxPin(5)) # 初始化舵機(jī) PWM 引腳 GP15 servo PWM(Pin(15)) servo.freq(50) # 50Hz 20ms 周期 def angle_to_duty(angle): # 0度 - 2.5%占空比180度 - 12.5%占空比 # 填入 0~65535 的占空比范圍 min_duty int(65535 * 0.025) max_duty int(65535 * 0.125) return int(min_duty (max_duty - min_duty) * angle / 180) buffer b while True: if uart1.any(): data uart1.read() if data: buffer data # 按換行符分割完整指令 if b\n in buffer: lines buffer.split(b\n) for line in lines: line line.strip() if not line: continue try: # 指令形如 S90 if line[0] ord(S): angle int(line[1:]) angle max(0, min(180, angle)) servo.duty_u16(angle_to_duty(angle)) uart1.write(fOK {angle}\n.encode()) except ValueError: uart1.write(bERR\n) buffer b這段代碼雖然借鑒了網(wǎng)上流行思路但我做了一些改進(jìn)用緩沖區(qū)而不是每次收到一個(gè)字節(jié)就執(zhí)行一次用換行符作為指令結(jié)束標(biāo)志比固定長(zhǎng)度解析更健壯增加角度限幅保護(hù)舵機(jī)。接線要注意舵機(jī)信號(hào)線接 GP15電源線接 5V地線接 GND。注意不要直接用 3.3V 給舵機(jī)供電多數(shù)舵機(jī)在負(fù)載狀態(tài)下 3.3V 會(huì)掉壓導(dǎo)致抖動(dòng)。5.3 為什么這種架構(gòu)適合“上位機(jī) 下位機(jī)”模式這種“串口指令 下位機(jī)執(zhí)行”的架構(gòu)在機(jī)器人項(xiàng)目里幾乎是標(biāo)配。上位機(jī)PC、手機(jī)藍(lán)牙串口助手、Unity 程序負(fù)責(zé)復(fù)雜的運(yùn)算和界面交互下位機(jī) Pico 只做實(shí)時(shí)性強(qiáng)的底層層操作比如 PWM 輸出和 IO 控制。我這段時(shí)間把 Pico 接入 Unity也就是用類似方式實(shí)現(xiàn)Unity 端通過SerialPort.Write(S90\n)發(fā)送指令Pico 端解析并控制舵機(jī)。實(shí)測(cè)在 19200 波特率下指令發(fā)送到舵機(jī)轉(zhuǎn)動(dòng)的延遲可以控制在 20ms 以內(nèi)對(duì)大部分交互場(chǎng)景完全夠用。如果你也打算把 Pico 接到 Unity 或者其他上位機(jī)建議在協(xié)議設(shè)計(jì)上加入起始符和結(jié)束符。比如S90\nS是起始符90是數(shù)據(jù)\n是結(jié)束符。這樣即使偶爾出現(xiàn)粘包也能利用起始符分割指令避免錯(cuò)誤執(zhí)行。6. 常見問題與排查技巧6.1 為什么收不到數(shù)據(jù)這是串口調(diào)試?yán)镉龅筋l率最高的問題沒有之一。常見原因按概率排序接線沒共地。UART 是異步串行通信收發(fā)雙方必須共地否則參考電壓不一致。TX 和 RX 接反了。對(duì)調(diào)一下就能解決。波特率不一致。模塊是 9600你這邊 115200收到的全是亂碼或者什么都沒顯示。引腳占用沖突。GP0/GP1 可能已經(jīng)被別的功能占用此時(shí)數(shù)據(jù)自然不會(huì)從你期望的引腳出來。電平不匹配。3.3V 接收方接了 5V 信號(hào)雖說不至于立刻燒毀但可能無法穩(wěn)定識(shí)別。排障順序建議先看硬件接線共地否、TX/RX 是否對(duì)調(diào)再用邏輯分析儀測(cè)波形最后才懷疑代碼。很多新手順序反了代碼改了大半天最后發(fā)現(xiàn)是杜邦線松了。6.2 為什么會(huì)亂碼亂碼幾乎都是波特率不匹配。還有少數(shù)情況是雙方格式不一致你是 8N1對(duì)面模塊是 7E17位偶校驗(yàn)結(jié)果就是每個(gè)字節(jié)都錯(cuò)位。如果你用 USB 轉(zhuǎn) TTL 模塊確認(rèn)模塊上的跳線或撥碼開關(guān)是否配置正確。有些模塊默認(rèn) 5V 模式?jīng)]有跳成 3.3V這也會(huì)導(dǎo)致波形畸變。另一個(gè)冷門但常見的原因是“接地環(huán)路”。如果上位機(jī) PC 和 Pico 兩邊都接了不同的電源適配器且兩個(gè)適配器的地之間存在電壓差串口線上會(huì)有電流流動(dòng)導(dǎo)致信號(hào)畸變。解決方法是只用單邊供電或者用隔離模塊。6.3 為什么打印顯示正常但 UART 引腳沒輸出這個(gè)問題在 Pico 上很典型原因我剛才提過MicroPython 的 print 打印走的是 USB 虛擬串口跟 UART 引腳是兩碼事。很多人寫了幾行 print 發(fā)現(xiàn) Thonny 窗口有輸出就以為串口通了實(shí)際 GP0/GP1 上什么信號(hào)都沒有。想驗(yàn)證 UART 引腳是否在發(fā)數(shù)據(jù)最簡(jiǎn)單的方法是把 TX 引腳接地然后用 USB 轉(zhuǎn) TTL 模塊連接在電腦上用串口助手看有沒有數(shù)據(jù)。如果你手頭有邏輯分析儀把這個(gè)抓手掛上去看波形是更直觀的方案。由于 REPL 默認(rèn)占用 UART0 的引腳你如果初始化 UART0 就會(huì)發(fā)現(xiàn) REPL 沒輸出了。解決辦法是換用 UART1或者調(diào)整 REPL 的映射需要在固件層操作比較麻煩不推薦新手直接上。6.4 串口調(diào)試問題速查表現(xiàn)象最可能原因優(yōu)先排查項(xiàng)完全無輸出接線錯(cuò)誤或未共地檢查 TX/RX/GND 連接收到數(shù)據(jù)全是亂碼波特率不一致兩邊設(shè)成完全相同偶爾丟字節(jié)緩沖不足或線過長(zhǎng)加長(zhǎng)延時(shí)/縮短線纜執(zhí)行了兩次指令上位機(jī)多發(fā)或粘包在指令中加結(jié)束符print 有輸出但引腳沒信號(hào)REPL 和 UART 混為一談檢查是否在 UART 引腳上接設(shè)備引腳電平異常外設(shè)電壓不匹配加電平轉(zhuǎn)換模塊這張表的經(jīng)驗(yàn)來自我實(shí)際調(diào)試過的多個(gè)場(chǎng)景。個(gè)人感覺串口問題看起來五花八門但根因不外乎電平、接線、波特率、引腳沖突四類。先把這四類排除掉再去折騰協(xié)議和代碼能少走一半彎路。6.5 電磁干擾與信號(hào)完整性最后補(bǔ)一個(gè)前面提過但值得專門強(qiáng)調(diào)的點(diǎn)線纜長(zhǎng)度對(duì)高速串口的影響。理論上 UART 在 115200 波特率下幾十厘米線纜都問題不大但如果你用的是面包板加長(zhǎng)杜邦線又跟電機(jī)驅(qū)動(dòng)線走在一起還是會(huì)偶發(fā)干擾。對(duì)策有兩種。一是降低波特率到 9600 或 19200代價(jià)是傳輸速度變慢但穩(wěn)定性顯著提升二是使用帶屏蔽的線纜或者雙絞線減少外部電磁干擾的影響。我在驅(qū)動(dòng)舵機(jī)時(shí)PWM 信號(hào)線和串口線保持了一定距離避免舵機(jī) PWM 對(duì)串口 RX 線產(chǎn)生串?dāng)_。這個(gè)細(xì)節(jié)在電機(jī)類項(xiàng)目中尤其要注意。7. 我的一點(diǎn)體會(huì)與擴(kuò)展建議說實(shí)話Pico 的串口通信并不復(fù)雜但它在整個(gè)嵌入式項(xiàng)目里起到的作用經(jīng)常被低估。串口是你對(duì)外的眼睛也是你給他的命令。學(xué)會(huì)正確配置 UART、理解引腳復(fù)用、掌握收發(fā)邏輯、選對(duì)調(diào)試工具這套組合拳打下來基本能應(yīng)對(duì) 90% 的 Pico 外設(shè)通信需求。我實(shí)際做過的項(xiàng)目里Pico 串口最穩(wěn)的一個(gè)場(chǎng)景是長(zhǎng)期運(yùn)行的環(huán)境監(jiān)測(cè)節(jié)點(diǎn)。節(jié)點(diǎn)通過 UART 接二氧化碳傳感器每 5 秒讀一次數(shù)據(jù)再用板載 WiFi 模塊通過串口把數(shù)據(jù)傳到 MQTT broker。連續(xù)運(yùn)行了兩周串口鏈路沒有丟過一次數(shù)據(jù)。能做到這一點(diǎn)靠的不是運(yùn)氣而是初始化時(shí)把超時(shí)、緩沖區(qū)、電平都處理好。如果你后面打算深入這塊有幾個(gè)方向值得繼續(xù)玩用 Pico 做串口轉(zhuǎn) WiFi 網(wǎng)關(guān)讓老舊傳感器聯(lián)網(wǎng)用兩個(gè) Pico 做全雙工串口通信測(cè)試自己寫一份簡(jiǎn)單的通信協(xié)議或者在 CircuitPython 和 MicroPython 之間切換對(duì)比兩者 UART 行為的差異。串口是不起眼的基礎(chǔ)功但基礎(chǔ)功越扎實(shí)后續(xù)做復(fù)雜項(xiàng)目的翻車概率就越低。