換詳解:從UART到DB9串口通信)
之前在做一塊 STM32 控制板的時(shí)候調(diào)試上位機(jī)通信時(shí)發(fā)現(xiàn)一個(gè)很典型的現(xiàn)象用 USB 轉(zhuǎn) TTL 線連接一切正常換成電腦主板自帶的 DB9 串口后卻完全收不到數(shù)據(jù)甚至把主板串口芯片燒掉過(guò)一次。排查到最后問(wèn)題根源就在 RS232 電平 和 TTL 電平 的轉(zhuǎn)換上。很多剛接觸嵌入式的朋友對(duì) RS232、TTL、UART、串口這幾個(gè)詞往往是一頭霧水。實(shí)際上它們描述的是不同維度的問(wèn)題UART 是一種通信時(shí)序協(xié)議TTL 是數(shù)字芯片內(nèi)部使用的邏輯電平標(biāo)準(zhǔn)而 RS232 則是一套完整的串行通信電氣標(biāo)準(zhǔn)。本文就從這里開(kāi)始把 RS232 電平、RS232 串口接線、常用電平轉(zhuǎn)換電路、調(diào)試方法和工程坑點(diǎn)一次講透幫助大家少走彎路。1. RS232 是什么先理清 UART、RS232、TTL 的關(guān)系1.1 為什么初學(xué)者經(jīng)常被這三個(gè)詞搞混我先說(shuō)一個(gè)常見(jiàn)場(chǎng)景你在淘寶上買(mǎi)了一塊“USB 轉(zhuǎn) RS232”小板然后在設(shè)備管理器中看到的是 CH340 或者 FTDI 芯片插上電腦后出現(xiàn)的是 COM 口。于是你自然地以為這個(gè) COM 口輸出的一定就是 RS232 電平。但實(shí)際拆開(kāi)外殼你會(huì)發(fā)現(xiàn)很多“USB 轉(zhuǎn) RS232”小板其實(shí)只是 USB 轉(zhuǎn) TTL只是把 DB9 接頭做成了 RS232 的外形內(nèi)部是否有真正的 RS232 電平轉(zhuǎn)換電路是看不出來(lái)的。另外你去查閱單片機(jī)串口外設(shè)時(shí)又看到大量關(guān)于“UART”的講解它和 RS232 好像講的是同一件事可電平又不完全一致。這種混亂的根源在于UART、RS232、TTL 分別是協(xié)議層、電氣標(biāo)準(zhǔn)層、邏輯電平層的概念它們?cè)谠O(shè)備中層層疊疊但并不是等價(jià)替換關(guān)系。1.2 三者的定義區(qū)分UART 是通用異步收發(fā)器它規(guī)定了數(shù)據(jù)按幀傳輸?shù)臅r(shí)序一個(gè)起始位、5/6/7/8 個(gè)數(shù)據(jù)位、一個(gè)可選的校驗(yàn)位、一個(gè)或多個(gè)停止位。它不關(guān)心信號(hào)電壓到底是多少伏只關(guān)心高低電平變化是否符合時(shí)序。RS232 串口通信中最常采用的底層協(xié)議就是 UART。TTL 電平是數(shù)字芯片內(nèi)部使用的邏輯電平標(biāo)準(zhǔn)。常見(jiàn)的 5V TTL 系統(tǒng)中高電平為 2V 到 5V低電平為 0V 到 0.8V3.3V 系統(tǒng)中高電平則最高到 3.3V。它使用正邏輯用高電平表示邏輯 1低電平表示邏輯 0。RS232是 EIA美國(guó)電子工業(yè)協(xié)會(huì)制定的一套串行通信電氣標(biāo)準(zhǔn)全稱是 RS-232C 或 EIA-232。它除了定義電平范圍還定義了接口引腳、時(shí)序關(guān)系、機(jī)械連接方式等內(nèi)容是 20 世紀(jì)中后期電腦與 Modem、鼠標(biāo)、工業(yè)設(shè)備之間最常用的串行接口之一。簡(jiǎn)單來(lái)說(shuō)單片機(jī)內(nèi)部通過(guò) UART 外設(shè)把并行數(shù)據(jù)變成串行數(shù)據(jù)然后以 TTL 電平輸出如果要把信號(hào)發(fā)送到 RS232 標(biāo)準(zhǔn)的 DB9 接口就必須經(jīng)過(guò)電平轉(zhuǎn)換芯片把 TTL 電平變換成 RS232 電平同時(shí)還要把 TX、RX 方向上的信號(hào)分別做邏輯反向。1.3 RS232 的典型應(yīng)用場(chǎng)景現(xiàn)在雖然新電腦已經(jīng)很少直接帶 DB9 串口但 RS232 在工業(yè)控制、儀器儀表、通信設(shè)備等領(lǐng)域依然活躍典型場(chǎng)景包括工控觸摸屏與 PLC、單片機(jī)控制器通信例如維綸通、昆侖通態(tài)觸摸屏的 COM 口?;魇?KV 系列 PLC 與上位機(jī)通信。迪文串口屏、組態(tài)屏與主控板之間進(jìn)行指令交互。老式數(shù)控機(jī)床、稱重儀表、UPS 監(jiān)控接口。銀行 POS 機(jī)、醫(yī)療設(shè)備等對(duì)穩(wěn)定性要求高的低速通信場(chǎng)合。在這些場(chǎng)景里RS232 電平標(biāo)準(zhǔn)仍然被作為工業(yè)設(shè)備之間的“通用語(yǔ)言”所以掌握 RS232 串口的電平定義、引腳含義和轉(zhuǎn)換電路是做嵌入式開(kāi)發(fā)和工業(yè)通信調(diào)試的基礎(chǔ)功。2. RS232 電平到底是多少伏2.1 RS232 電平的電壓范圍標(biāo)準(zhǔn)RS232 標(biāo)準(zhǔn)規(guī)定的電平范圍如下信號(hào)邏輯狀態(tài)電壓范圍典型電壓發(fā)送端邏輯 0數(shù)據(jù) 05V ~ 15V12V發(fā)送端邏輯 1數(shù)據(jù) 1-5V ~ -15V-12V接收端邏輯 03V ~ 15V—接收端邏輯 1-3V ~ -15V—未定義區(qū)域—-3V ~ 3V—注意兩個(gè)關(guān)鍵點(diǎn)第一RS232 使用的是負(fù)邏輯。這和 TTL 恰好相反TTL 中高電平代表邏輯 1低電平代表邏輯 0而在 RS232 中正電壓12V 附近代表邏輯 0負(fù)電壓-12V 附近代表邏輯 1。第二RS232 接收端允許的電壓范圍比發(fā)送端寬從 3V 到 15V 都可以識(shí)別為邏輯 0從 -3V 到 -15V 都可以識(shí)別為邏輯 1。也就是說(shuō)接收端有 2V 左右的噪聲容限這比 TTL 的噪聲容限大不少因此 RS232 在較長(zhǎng)距離的工業(yè)通信中比裸 TTL 抗干擾能力更強(qiáng)。2.2 TTL 電平標(biāo)準(zhǔn)與 3.3V/5V 系統(tǒng)常見(jiàn)的 TTL 電平分為兩類5V TTL 系統(tǒng)邏輯 1高電平2V ~ 5V通常在輸出端約為 5V。邏輯 0低電平0V ~ 0.8V。3.3V CMOS/LVTTL 系統(tǒng)邏輯 1高電平2V ~ 3.3V。邏輯 0低電平0V ~ 0.8V。有了上面的對(duì)比你就會(huì)明白為什么單片機(jī)的 TX/RX 引腳不能直接接到 RS232 DB9 接口上RS232 空閑時(shí)輸出為 -12V 左右的邏輯 1而單片機(jī)引腳如果輸入負(fù)壓輕則導(dǎo)致內(nèi)部 ESD 保護(hù)二極管導(dǎo)通重則燒毀引腳。RS232 的數(shù)據(jù) 0 是 12V 左右遠(yuǎn)超 3.3V 或 5V 單片機(jī)引腳耐壓范圍直接連接可能損壞單片機(jī)。反過(guò)來(lái)單片機(jī)輸出的 TTL 高電平一般只有 3.3V 或 5V正電壓幅度達(dá)不到 RS232 接收端要求的 3V 以上倒還好但 TTL 低電平是 0VRS232 接收端會(huì)把它當(dāng)成“未定義區(qū)域”不能可靠識(shí)別。所以在任何需要連接真實(shí) RS232 設(shè)備的電路中電平轉(zhuǎn)換電路都是必須的而不是可選項(xiàng)。2.3 那 -12V 是從哪里來(lái)的很多初學(xué)者會(huì)問(wèn)一個(gè)問(wèn)題電腦主板上的串口怎么會(huì)有 -12V難道是主板上還有一個(gè) -12V 電源嗎確實(shí)有。PC 主板的 PCI/ISA 電源總線上會(huì)提供 -12V 這一路電源但它的驅(qū)動(dòng)能力非常弱電流一般只有幾百毫安甚至更小。而 RS232 需要的正是這種“正負(fù)雙電源”的環(huán)境。單獨(dú)靠單片機(jī)控制板上的 3.3V 或 5V 單電源是沒(méi)有負(fù)壓來(lái)源的所以才會(huì)用 MAX232 這類電荷泵芯片來(lái)產(chǎn)生 -12V 左右的電壓這也就是很多電平轉(zhuǎn)換芯片內(nèi)部都內(nèi)置“電荷泵”的原因。3. RS232 串口接口與引腳定義3.1 DB9 引腳的定義提到 RS232 串口很多人第一反應(yīng)是那個(gè)梯形 DB9 插頭。DB9 分為公頭帶針和母頭帶孔兩種常見(jiàn)引腳定義如下引腳號(hào)信號(hào)名稱作用說(shuō)明方向以 DTE 為準(zhǔn)1DCDCarrier Detect 載波檢測(cè)輸入2RXDReceive Data 接收數(shù)據(jù)輸入3TXDTransmit Data 發(fā)送數(shù)據(jù)輸出4DTRData Terminal Ready 數(shù)據(jù)終端就緒輸出5GNDSignal Ground 信號(hào)地—6DSRData Set Ready 數(shù)據(jù)設(shè)備就緒輸入7RTSRequest To Send 請(qǐng)求發(fā)送輸出8CTSClear To Send 允許發(fā)送輸入9RIRing Indicator 振鈴指示輸入這 9 個(gè)引腳中真正用于最基本數(shù)據(jù)通信的只有 2RXD、3TXD、5GND三根。其他引腳用于 Modem 撥號(hào)、流控和鏈路檢測(cè)等擴(kuò)展功能我們做普通的 RS232 串口通信時(shí)不一定全部要用。這里有個(gè)容易混淆的點(diǎn)DB9 公頭 2 腳是 RXD、3 腳是 TXD這是針對(duì) DTE 設(shè)備例如電腦而言的。很多 DB9 面板上標(biāo)注的 TXD 是指這個(gè)設(shè)備自己的發(fā)送腳而不是對(duì)面設(shè)備的發(fā)送腳。所以實(shí)際的串口調(diào)試中不要只看公頭還是母頭要看當(dāng)前板上信號(hào)的功能定義。3.2 最簡(jiǎn)單通信最少需要哪幾根線在設(shè)計(jì) RS232 通信電路時(shí)如果只是收發(fā)數(shù)據(jù)不做硬件流控那么三線制接法就夠了設(shè)備 A 的 TXD 接設(shè)備 B 的 RXD。設(shè)備 A 的 RXD 接設(shè)備 B 的 TXD。兩邊的 GND 接 GND。也就是說(shuō)信號(hào)線需要交叉連接。很多新手把兩塊開(kāi)發(fā)板用“TXD 接 TXD、RXD 接 RXD”的排線直接連結(jié)果兩邊都收不到數(shù)據(jù)。這本質(zhì)上就是因?yàn)闆](méi)有理解發(fā)送端必須連接對(duì)端的接收端。如果是兩個(gè)串口設(shè)備之間通過(guò) DB9 直連通常要做成交叉線即“2 對(duì) 3、3 對(duì) 2、5 對(duì) 5”。市面上某些成品 DB9 線是直通線用于連接電腦與 Modem 這類 DTE-DCE 組合而用于電腦與單片機(jī)調(diào)試板如果單片機(jī)板子模擬 DTE時(shí)多半需要交叉線買(mǎi)線材時(shí)要特別留意。3.3 如何判斷你手上的串口是 TTL 還是 RS232拿到一塊板子或者一個(gè)轉(zhuǎn)接器時(shí)最穩(wěn)妥的方法不是看絲印而是直接用萬(wàn)用表測(cè)量串口的空閑狀態(tài)電壓如果 TXD/RXD 空閑時(shí)測(cè)量到 -5V ~ -12V 左右說(shuō)明這是 RS232 電平。如果 TXD/RXD 空閑時(shí)測(cè)量到 3.3V 或 5V說(shuō)明這是 TTL 電平。如果 TXD 上測(cè)量到 0V 且 RXD 上有 3.3V 之類的電壓要檢查芯片是否已經(jīng)進(jìn)入發(fā)送狀態(tài)或電路是否正常。一個(gè) RS232 收發(fā)器在空閑時(shí)TXD 輸出端應(yīng)該保持邏輯 1也就是負(fù)電壓。假如你測(cè)量 USB 轉(zhuǎn) RS232 線的 TXD 在空閑時(shí)是 5V 或 3.3V那么這根線大概率只是 USB 轉(zhuǎn) TTL并不能直接連接標(biāo)準(zhǔn)的 RS232 設(shè)備。4. 電平轉(zhuǎn)換電路TTL 和 RS232 之間到底怎么轉(zhuǎn)4.1 為什么不能直接連接我們已經(jīng)知道TTL 高電平是 3.3V/5V低電平是 0VRS232 的邏輯 1 是負(fù)電壓邏輯 0 是正電壓。從數(shù)學(xué)上看TTL 高電平對(duì)應(yīng) RS232 邏輯 0正電壓TTL 低電平對(duì)應(yīng) RS232 邏輯 1負(fù)電平所以電平轉(zhuǎn)換不僅要做電平幅度的搬移還要做一個(gè)邏輯反向。如果用一句話描述電平轉(zhuǎn)換電路的作用就是把單片機(jī)的“3.3V/5V 正邏輯串口”變換為“±12V 負(fù)邏輯串口”同時(shí)保護(hù)兩端芯片不被對(duì)方的高壓或負(fù)壓損壞。4.2 方案一使用 MAX232/SP3232 專用收發(fā)芯片這是最推薦、也最穩(wěn)定的方案。MAX232 系列芯片內(nèi)置電荷泵只需要單電源供電就能產(chǎn)生正負(fù)兩路 RS232 電源電壓內(nèi)部還集成了兩路發(fā)送器和兩路接收器可以同時(shí)處理 TX、RX 兩路信號(hào)。SP3232 是 MAX232 的低功耗替代型號(hào)兼容 3.3V 和 5V 供電也常用于便攜式設(shè)備。典型接線思路如下MAX232 引腳連接對(duì)象VCC5V部分型號(hào)支持 3.3V按芯片手冊(cè)GND電源地C1、C1-、C2、C2-4 只 0.1uF 電荷泵電容V電荷泵輸出正電壓通常接 0.1uF 電容到地V-電荷泵輸出負(fù)電壓通常接 0.1uF 電容到地T1IN單片機(jī) TXDTTL 輸入T1OUTRS232 TXD 發(fā)送輸出R1INRS232 RXD 接收輸入R1OUT單片機(jī) RXDTTL 輸出用 C 語(yǔ)言偽代碼描述一遍連接后的初始化流程// 單片機(jī) UART 初始化示意以 STM32 HAL 庫(kù)為例具體參數(shù)按芯片型號(hào)調(diào)整 UART_HandleTypeDef huart1; void MX_USART1_UART_Init(void) { huart1.Instance USART1; huart1.Init.BaudRate 9600; huart1.Init.WordLength UART_WORDLENGTH_8B; huart1.Init.StopBits UART_STOPBITS_1; huart1.Init.Parity UART_PARITY_NONE; huart1.Init.Mode UART_MODE_TX_RX; huart1.Init.HwFlowCtl UART_HWCONTROL_NONE; huart1.Init.OverSampling UART_OVERSAMPLING_16; if (HAL_UART_Init(huart1) ! HAL_OK) { Error_Handler(); } }在這個(gè)例子中單片機(jī)這一側(cè)的 USART1_TX 就會(huì)輸出 TTL 電平的串口數(shù)據(jù)把它接到 MAX232 的 T1INMAX232 的 T1OUT 就輸出了 RS232 電平的串行數(shù)據(jù)可以連接外部 RS232 設(shè)備的 RXD。4.3 方案二三極管分立電平轉(zhuǎn)換電路在某些低成本、對(duì)功耗不敏感的板卡上也會(huì)看到用三極管實(shí)現(xiàn)電平轉(zhuǎn)換的電路。不過(guò)需要先說(shuō)明三極管分立轉(zhuǎn)換電路要做到真正符合 RS232 標(biāo)準(zhǔn)的 ±12V 輸出必須有正負(fù)雙電源否則輸出往往只是“0V 到 5V”或“0V 到 12V”的單極性信號(hào)無(wú)法達(dá)到標(biāo)準(zhǔn) RS232 接收端的負(fù)電平要求。一種常見(jiàn)思路是采用 NPN PNP 對(duì)管做發(fā)送端。以 TTL 輸入信號(hào)為例TTL 輸入為高電平時(shí)NPN 管導(dǎo)通、PNP 管截止輸出端被拉到接近負(fù)電源電壓。TTL 輸入為低電平時(shí)NPN 管截止、PNP 管導(dǎo)通輸出端被拉到接近正電源電壓。這個(gè)電路本質(zhì)上是一個(gè)推挽反相器。它能實(shí)現(xiàn) TTL 到 RS232 的邏輯反向和電平搬移前提是你手頭有 12V 和 -12V 兩路電源。實(shí)際產(chǎn)品如果想省掉 -12V 電源也可以用電荷泵產(chǎn)生負(fù)壓但那本質(zhì)上又回到了 MAX232 的內(nèi)部原理。我個(gè)人的建議是如果只是做實(shí)驗(yàn)、學(xué)原理三極管電路可以幫助你理解電平轉(zhuǎn)換的本質(zhì)但如果做產(chǎn)品或者調(diào)試穩(wěn)定性要求較高的工業(yè)設(shè)備直接選 MAX232/SP3232/MAX3232 這類集成芯片外圍元器件少、一致性好、故障率低。4.4 方案三使用 USB 轉(zhuǎn)串口小板調(diào)試在開(kāi)發(fā)階段最常用的是 USB 轉(zhuǎn)串口調(diào)試方案。這里要區(qū)分兩類產(chǎn)品一類是“USB 轉(zhuǎn) TTL”常見(jiàn)主控是 CH340、CH341、CP2102、FT232。它輸出的是 TTL 電平不能直接連接 RS232 設(shè)備只能連接單片機(jī)或 TTL 接口外圍模塊。另一類是“USB 轉(zhuǎn) RS232”常見(jiàn)做法是在 USB 轉(zhuǎn) TTL 芯片后面再加一個(gè) MAX232 之類的 RS232 收發(fā)器最終輸出到 DB9 座子。這類產(chǎn)品的 TXD 在空閑時(shí)測(cè)出來(lái)才是負(fù)電壓。很多調(diào)試器品牌還支持免驅(qū)動(dòng)或自動(dòng)安裝驅(qū)動(dòng)但如果你使用 CH340/CH341 芯片第一次接上電腦后如果驅(qū)動(dòng)沒(méi)自動(dòng)裝上可以考慮到芯片官網(wǎng)下載對(duì)應(yīng)系統(tǒng)的驅(qū)動(dòng)FTDI 芯片也在官網(wǎng)提供全平臺(tái)驅(qū)動(dòng)。Windows 下確認(rèn)設(shè)備管理器中能看到 COM 口號(hào)后再用串口助手打開(kāi)。5. RS232 通信過(guò)程與典型調(diào)試驗(yàn)證5.1 一幀數(shù)據(jù)到底長(zhǎng)什么樣RS232 串口通信采用異步幀格式常見(jiàn)配置是 8 個(gè)數(shù)據(jù)位、無(wú)校驗(yàn)位、1 個(gè)停止位也就是常說(shuō)的 8N1。一幀數(shù)據(jù)包括以下部分空閑狀態(tài)線路處于邏輯 1對(duì)應(yīng) RS232 電平就是負(fù)電壓。起始位線路跳變到邏輯 0對(duì)應(yīng)正電壓表示一幀數(shù)據(jù)的開(kāi)始。數(shù)據(jù)位從最低位 LSB 開(kāi)始發(fā)送依次發(fā)送 8 個(gè)數(shù)據(jù)位。停止位線路回到邏輯 1持續(xù) 1 位時(shí)間表示一幀結(jié)束。你可以把 9600 波特率下的每一位時(shí)間估算為約 104us而 115200 波特率下每一位時(shí)間約為 8.68us。波特率越高每一位時(shí)間越短對(duì)線纜電容和收發(fā)器驅(qū)動(dòng)能力的要求也越高。發(fā)送一個(gè) ASCII 字符A十六進(jìn)制 0x41二進(jìn)制 01000001時(shí)線路上的電平變化順序?yàn)槠鹗嘉?0) - 數(shù)據(jù)位:1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 停止位(1)注意數(shù)據(jù)位是從 LSB 開(kāi)始發(fā)送所以0x41的最低位 1 最先出現(xiàn)在線上最高位 0 最后出現(xiàn)在線上。5.2 用示波器觀察 RS232 電平調(diào)試 RS232 電平是否正常強(qiáng)烈建議用示波器或者邏輯分析儀直接觀察 TXD 波形。下面是使用示波器時(shí)的判斷要點(diǎn)空閑時(shí)RS232 的 TXD 應(yīng)該是 -3V 到 -15V 之間的負(fù)電壓。發(fā)送數(shù)據(jù)時(shí)起始位會(huì)跳變到 3V 到 15V 之間的正電壓。數(shù)據(jù)位中每一位正負(fù)電平持續(xù)時(shí)間應(yīng)與波特率吻合。例如讓串口持續(xù)發(fā)送 0x55二進(jìn)制 01010101示波器上應(yīng)該看到方波頻率等于波特率的一半。如果發(fā)送 0x01則可以看到單個(gè)低電平脈沖后回到高電平的波形。如果示波器顯示 TXD 空閑時(shí)為 0V或者發(fā)送時(shí)最高只有 3.3V、最低只有 0V說(shuō)明你的轉(zhuǎn)換電路并沒(méi)有真實(shí)輸出 RS232 電平標(biāo)準(zhǔn)基本可以判斷是 TTL 電平不是 RS232 電平。5.3 用 Python 腳本驗(yàn)證串口收發(fā)在沒(méi)有邏輯分析儀的情況下也可以直接讓 PC 和單片機(jī)對(duì)發(fā)數(shù)據(jù)來(lái)驗(yàn)證鏈路。下面是使用 Python PySerial 庫(kù)讀取串口數(shù)據(jù)的示例。# 文件路徑read_serial.py # 在電腦上執(zhí)行前先安裝 pyserialpip install pyserial import serial import time # 根據(jù)實(shí)際設(shè)備管理器中的 COM 口號(hào)修改 ser serial.Serial( portCOM3, # Windows 示例Linux 下可能是 /dev/ttyUSB0 baudrate9600, bytesizeserial.EIGHTBITS, parityserial.PARITY_NONE, stopbitsserial.STOPBITS_ONE, timeout1 ) if ser.is_open: print(f串口 {ser.name} 已打開(kāi)) # 發(fā)送一幀測(cè)試數(shù)據(jù) ser.write(bHello RS232\r\n) # 讀取來(lái)自對(duì)端的數(shù)據(jù) time.sleep(0.1) data ser.read(64) if data: print(收到數(shù)據(jù):, data) else: print(未收到數(shù)據(jù)請(qǐng)檢查接線和電平轉(zhuǎn)換電路) ser.close()Linux 系統(tǒng)下也可以直接用命令行測(cè)試# 查看 USB 轉(zhuǎn)串口設(shè)備節(jié)點(diǎn) ls /dev/ttyUSB* # 設(shè)置串口參數(shù)并發(fā)送數(shù)據(jù) stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb echo -en Hello RS232\r\n /dev/ttyUSB0 # 讀取串口數(shù)據(jù)按 CtrlC 退出 cat /dev/ttyUSB0在 Windows 上則推薦使用常見(jiàn)的串口調(diào)試助手比如 SSCOM 工具。打開(kāi)串口調(diào)試助手時(shí)需要注意以下幾點(diǎn)波特率、數(shù)據(jù)位、停止位、校驗(yàn)位要和設(shè)備端完全一致。勾選“發(fā)送新行”時(shí)很多工具會(huì)在發(fā)送內(nèi)容的最后自動(dòng)添加\r\n也就是回車(chē)換行如果設(shè)備需要以回車(chē)作為命令結(jié)束標(biāo)志這個(gè)功能很重要。接收區(qū)設(shè)置為文本顯示還是 Hex 顯示要根據(jù)設(shè)備協(xié)議決定如果收到的是非 ASCII 字節(jié)建議切換成 Hex 顯示更直觀。6. RS232 串口常見(jiàn)問(wèn)題與排查思路本章整理我在調(diào)試 RS232 串口時(shí)遇到的高頻問(wèn)題按“現(xiàn)象 - 原因 - 解決思路”的順序給出方便有經(jīng)驗(yàn)的開(kāi)發(fā)者快速對(duì)照。問(wèn)題現(xiàn)象常見(jiàn)原因解決思路電腦無(wú)法識(shí)別 USB 轉(zhuǎn)串口設(shè)備CH340/CH341/FTDI 等驅(qū)動(dòng)未安裝或驅(qū)動(dòng)版本不兼容進(jìn)入設(shè)備管理器查看是否出現(xiàn)未知設(shè)備或黃色感嘆號(hào)到芯片官網(wǎng)下載對(duì)應(yīng)系統(tǒng)驅(qū)動(dòng)打開(kāi)串口提示“端口被占用”或“無(wú)法打開(kāi)”串口被其他軟件占用或者串口工具未關(guān)閉關(guān)閉正在使用該串口的軟件重新插拔轉(zhuǎn)接器必要時(shí)重啟電腦收發(fā)雙方波特率設(shè)置不同上位機(jī)與設(shè)備波特率不一致確認(rèn)兩邊的波特率、數(shù)據(jù)位、停止位、校驗(yàn)位完全一致包括是否有回車(chē)換行收不到任何數(shù)據(jù)TXD 和 RXD 接反沒(méi)有共地或沒(méi)有完成 TTL/RS232 電平轉(zhuǎn)換用交叉方式重新連接 TTL 信號(hào)檢查 MAX232 供電和電荷泵電容用萬(wàn)用表確認(rèn) RS232 端空閑電壓為負(fù)電平收到亂碼波特率不匹配、接地不可靠、線纜過(guò)長(zhǎng)、主時(shí)鐘偏差大降低波特率選擇更好的 USB 轉(zhuǎn) TTL 芯片檢查雙方 GND 連接縮短線纜長(zhǎng)度電平轉(zhuǎn)換芯片發(fā)燙電源接反、引腳短路、信號(hào)端口被高壓串入斷電后用萬(wàn)用表測(cè)量 VCC 和 GND 是否短路檢查外部 RS232 線是否帶電反插設(shè)備剛連接時(shí)正常長(zhǎng)時(shí)間運(yùn)行后死機(jī)RS232 線路受外部干擾或地電位差影響產(chǎn)生過(guò)壓或浪涌增加 TVS 二極管使用屏蔽線保證通信地可靠必要時(shí)在 RS232 收發(fā)器前端增加隔離方案單片機(jī) 3.3V 與 5V 電平互連收不到數(shù)據(jù)邏輯電平不兼容例如 3.3V 芯片輸出高電平為 3.3V低于 5V TTL 高電平閾值使用電平轉(zhuǎn)換芯片或雙向電平轉(zhuǎn)換模塊完成 3.3V/5V 電壓匹配與某些工業(yè)觸摸屏/PLC 通信不穩(wěn)定偶發(fā)超時(shí)只接了 TX、RX、GND但現(xiàn)場(chǎng)干擾大或設(shè)備要求硬件流控根據(jù)設(shè)備手冊(cè)確認(rèn)是否需要 RTS/CTS 或 DTR/DSR嘗試波特率降到 9600檢查接線端子是否松動(dòng)在排查 RS232 問(wèn)題時(shí)建議遵循一個(gè)固定的順序先檢查電平是否真的是 RS232 電平再檢查 TX 與 RX 是否交叉接著確認(rèn)參數(shù)是否一致最后才懷疑協(xié)議格式和程序邏輯。如果上來(lái)就懷疑代碼很容易在錯(cuò)誤的方向上浪費(fèi)時(shí)間。7. 接口防護(hù)與工程布線建議RS232 在電路板上看似簡(jiǎn)單但一個(gè)沒(méi)有防護(hù)的 RS232 接口在工廠現(xiàn)場(chǎng)非常容易被浪涌打壞。下面給出幾條實(shí)用的工程建議。7.1 常用防護(hù)電路怎么加在 RS232 收發(fā)器芯片和 DB9 座子之間可以增加簡(jiǎn)單的防護(hù)電路常見(jiàn)做法是在發(fā)送和接收線上分別串聯(lián)小阻值電阻例如 1kΩ 或 10Ω用于限制瞬間大電流具體阻值需要根據(jù)信號(hào)速率和芯片驅(qū)動(dòng)能力折算。在信號(hào)線對(duì)地之間放置 TVS 二極管把浪涌電壓鉗位在芯片能承受的范圍內(nèi)。在 DB9 外殼和信號(hào)地之間增加高壓電容或放電管減小靜電放電對(duì)內(nèi)部電路的影響。注意很多 RS232 收發(fā)器芯片內(nèi)部已經(jīng)集成了 ESD 保護(hù)如果你的產(chǎn)品使用環(huán)境相對(duì)干凈比如實(shí)驗(yàn)室、辦公設(shè)備就不需要額外做太多防護(hù)如果應(yīng)用在電機(jī)、變頻器等工業(yè)現(xiàn)場(chǎng)還是建議增加 TVS 和良好的接地設(shè)計(jì)。7.2 線纜長(zhǎng)度與布線選擇RS232 標(biāo)準(zhǔn)早期規(guī)定最大傳輸距離約 15 米左右這是在低波特率、良好接地和低噪聲環(huán)境下的參考值。實(shí)際應(yīng)用中如果使用帶屏蔽的線纜并把屏蔽層單端接地在 9600 波特率下跑 15 米以內(nèi)通常問(wèn)題不大如果提高到 115200 波特率傳輸距離應(yīng)大幅縮短否則會(huì)出現(xiàn)誤碼。布線時(shí)需要優(yōu)先級(jí)最高的幾點(diǎn)兩設(shè)備之間的 GND 一定要連通這是所有電壓判斷的參考點(diǎn)。長(zhǎng)距離布線應(yīng)采用屏蔽雙絞線屏蔽層建議單端接地防止形成地環(huán)路。盡可能讓 RS232 信號(hào)線遠(yuǎn)離電機(jī)驅(qū)動(dòng)線、變頻器輸出線、大電流電纜。在 PCB 上RS232 收發(fā)器盡量靠近 DB9 座子保持 RS232 電平的走線盡量短。8. 最佳實(shí)踐與開(kāi)發(fā)建議做過(guò)多塊帶 RS232 接口的板子之后我總結(jié)出下面幾條對(duì)實(shí)際開(kāi)發(fā)最有用的實(shí)踐建議。第一設(shè)計(jì)板卡時(shí)把 TTL 測(cè)試點(diǎn)引出來(lái)。即使產(chǎn)品外殼上是 DB9 座也最好在 PCB 上預(yù)留 MAX232 前端的 TTL 信號(hào)測(cè)試點(diǎn)方便開(kāi)發(fā)階段用邏輯分析儀直接抓取單片機(jī)發(fā)出的原始數(shù)據(jù)。如果通信異常先確認(rèn)單片機(jī)側(cè) TTL 數(shù)據(jù)是否正常再檢查 RS232 轉(zhuǎn)換后的信號(hào)就能快速判定問(wèn)題出在哪一側(cè)。第二RS232 收發(fā)器芯片的電源去耦電容不要省。MAX232 類芯片內(nèi)部電荷泵正常工作需要干凈的電源建議在 VCC 引腳附近放置 0.1uF 陶瓷電容并靠近芯片引腳布置。電荷泵電容的容值和耐壓也需要按芯片手冊(cè)選擇不要隨手把任意電容插上去。第三通信參數(shù)盡量做成可配置項(xiàng)。工業(yè)觸摸屏、PLC 或儀表設(shè)備往往要求不同的波特率或者校驗(yàn)方式把波特率、數(shù)據(jù)位、校驗(yàn)位寫(xiě)死在程序里會(huì)給后續(xù)調(diào)試帶來(lái)很大麻煩。建議使用配置文件或參數(shù)存儲(chǔ)區(qū)保存通信參數(shù)方便現(xiàn)場(chǎng)修改。第四不要盲目追求高速率。RS232 主要用于可靠性優(yōu)先的低速場(chǎng)景常見(jiàn)的 9600、19200 波特率適用于大多數(shù)工業(yè)設(shè)備。如果數(shù)據(jù)量很大、要求高吞吐不如改用 RS485 或者以太網(wǎng)方案。第五對(duì)收發(fā)數(shù)據(jù)要做超時(shí)處理。串口接收程序不能無(wú)限等待否則一旦對(duì)端掉線整個(gè)系統(tǒng)會(huì)卡在接收函數(shù)里。工業(yè)場(chǎng)景建議使用接收超時(shí)機(jī)制超時(shí)后主動(dòng)重發(fā)或者上報(bào)鏈路異常。最后要特別注意供電問(wèn)題。很多 RS232 轉(zhuǎn)接小板直接從 USB 口取電USB 口的 5V 電壓在長(zhǎng)線或帶載能力不足時(shí)會(huì)出現(xiàn)跌落導(dǎo)致 MAX232 輸出幅度不足。調(diào)試時(shí)如果發(fā)現(xiàn)輸出電平比正常低可以換一個(gè)電源質(zhì)量更好的 USB 口或者給轉(zhuǎn)接器單獨(dú)供電測(cè)試。9. 總結(jié)與下一步學(xué)習(xí)方向?qū)懙竭@里RS232 電平、RS232 串口接口、TTL 與 RS232 的轉(zhuǎn)換電路、調(diào)試方法和工程注意事項(xiàng)已經(jīng)全部梳理了一遍。重要的是要記住一個(gè)核心結(jié)論RS232 是一套完整的電氣標(biāo)準(zhǔn)它最大的特點(diǎn)就是負(fù)邏輯、正負(fù)雙極性電壓而單片機(jī)的 UART 默認(rèn)輸出的是 TTL 電平兩者之間必須通過(guò) MAX232 類芯片或獨(dú)立轉(zhuǎn)換電路完成電平搬移和邏輯反向。下一步可以從三個(gè)方向繼續(xù)深入如果做的是板級(jí)通信建議學(xué)習(xí) RS485 與 RS232 的區(qū)別了解差分信號(hào)為什么更適合長(zhǎng)距離、多節(jié)點(diǎn)通信。如果做的是工業(yè)設(shè)備互聯(lián)可以研究 Modbus RTU 協(xié)議在 RS232/RS485 上的應(yīng)用這是工控領(lǐng)域最主流的串口協(xié)議之一。如果做的是單片機(jī)開(kāi)發(fā)可以繼續(xù)學(xué)習(xí) DMA 空閑中斷接收不定長(zhǎng)數(shù)據(jù)把串口通信從輪詢收數(shù)升級(jí)為高效中斷驅(qū)動(dòng)模式。RS232 雖然古老但掌握它的電平標(biāo)準(zhǔn)、通信時(shí)序和排查思路能幫助你在面對(duì)各種帶“串口”字樣的設(shè)備和模塊時(shí)少踩很多坑。當(dāng)你下次在示波器上看到 TXD 空閑時(shí)穩(wěn)穩(wěn)停在負(fù)電壓附近就能一眼確認(rèn)這才是真正工作在 RS232 電平下的通信鏈路。