ESP32 怎麼讀 Modbus RTU?RS485 接線、寄存器位址、排錯與 TCP 閘道選擇指南
感測器明明有 A/B 端子,接上 ESP32 卻只看到逾時;交換線之後偶爾有回應,數字又像亂碼。問題通常不在「少裝一套函式庫」,而是電氣、串列參數、Modbus 請求、資料解析四層被混在一起。本文用一台可核對寄存器表的溫濕度變送器,帶你從安全接線、讀出 raw register、判讀錯誤碼,一路做到資料新鮮度與產線檢核。完成後,你會知道下一個該量哪裡、該改哪個參數,以及何時應從 RTU 升級為受管理的 TCP/閘道架構。
三分鐘快速判斷:先辨認手上的介面
| 你看到的標示或文件 | 現在能確定什麼 | 還缺什麼 | 下一個動作 |
|---|---|---|---|
| UART TX/RX | 微控制器邏輯層串列訊號 | 不具備 RS-485 差動驅動能力 | 核對 3.3V 邏輯,加入相容收發器 |
| RS485 A/B | 有差動實體介面 | 未必使用 Modbus | 找精確型號的功能碼、站號與寄存器表 |
| Modbus RTU、9600 8N1 | 協定跑在串列線上;參數可設定 | 未知功能碼、位址基準、縮放 | 把手冊欄位抄入測試紀錄表 |
| 文件寫 30001/40001 | 常見的人類閱讀參考號碼 | 程式參數通常不是直接填該數字 | 確認資料區與 PDU offset(封包位址) |
| IP、TCP 502、Unit ID | 可能是 Modbus TCP server | 不代表可安全跨網際網路 | 在隔離的區域網路核對模式與存取規則 |
| 只有 4–20mA/0–10V | 類比量測輸出 | 沒有可讀的數位寄存器 | 使用合適的類比輸入與訊號調理 |
最快的第一步,是先把設備名稱與通訊手冊對起來。只有「RS485」三個字,沒有功能碼和寄存器表,就沒有足夠資訊寫查詢程式。第一次採購也應買出完整測試閉環:ESP32 開發板、3.3V 邏輯相容的 RS-485 收發器、符合感測器規格的電源、A/B 雙絞線,以及可作交叉驗證的 USB–RS485 轉接器。先用單機短線建立基準,任何擴充都與這份基準逐項比較,故障範圍才不會隨系統規模一起膨脹。
把問題拆成四層,才不會同時亂改
第一層是 MCU 邏輯。 ESP32 的 UART TX/RX 是 3.3V 邏輯訊號,不可接到 RS-485 的 A/B。A/B 是差動匯流排,必須經過相容收發器。常見 5V MAX485 小板的接收輸出可能接近 5V,直接送入 ESP32 RX 有過壓風險。本篇因此排除 MAX485 直連;若另案採用,必須重新設計電平保護、方向控制、偏壓與終端。
第二層是 RS-485 與串列設定。 這裡要對上 A/B、鮑率、資料位元、同位元、停止位元、半雙工收發方向與線路拓樸。A、B、A+、B−、D+、D− 的命名可能因廠商視角不同,不能拿線色或字母當跨品牌通則。
第三層是 Modbus 請求。 ESP32 在本例是 client(舊文件常稱 master),感測器是 server(舊稱 slave)。Client 指定站號、功能碼、起始位址與數量;server 只在請求符合其設定時回覆。串列單播站號可用 1~247,0 是廣播且 server 不回覆,但這個位址空間不代表同一條實體線一定能掛 247 台。
第四層是資料表示。 通訊成功只表示收到了合法回覆,不保證單位正確。你仍要知道 16-bit word 是有號或無號、倍率與 offset、無效值、兩個 word 的順序,以及資料多久後算 stale(過期)。32-bit 整數或浮點數的 word order 沒有一個所有設備共用的答案。

圖中的關鍵安全資訊也要用文字記住:設備電源不得接進 ESP32 GPIO;終端只設在幹線的兩個物理端點;跨電源域、長線或高雜訊現場應把隔離與保護納入一開始的設計。
先讀通一台:ESP32-S3、DFR0845 與 XY-MD04
主範例使用三個可精確辨識的項目:
- ESP32-S3-DevKitC-1 N8R2 執行 Arduino 程式並擔任 RTU client。GPIO16/17 是本文配置,不代表每塊 ESP32 板都採相同腳位。
- DFRobot Gravity DFR0845 主動式隔離 RS485 轉 UART 模組 負責 UART 與 A/B 的實體層轉換。其 UART 邏輯側支援 3.3~5V,收發方向由模組內部處理;它本身不解析 Modbus。
- XY-MD04 SHT40 RS485 Modbus RTU 溫濕度變送器 是本次 server,另以符合其 5~28V 規格的電源供電。
斷電接線順序
先拔除 USB 與感測器電源。ESP32-S3 的 GPIO17(TX)接 DFR0845 的 R;GPIO16(RX)接 DFR0845 的 T。換句話說,是 ESP32 TX → DFR R,ESP32 RX ← DFR T。VCC 與 GND 依模組 UART 側標示接妥。DFR0845 的 A/B 再接到感測器 A/B,感測器使用自己的合規 DC 電源。
這個模組沒有提供給主控操作的 DE/RE 腳位,因此程式只呼叫 mb.begin(&RS485)。若在這條接線上多寫一個 DE/RE GPIO,不是「多一層保險」,而是虛構硬體介面。
DFR0845 有終端開關,但只有當它位於匯流排實體端點,且線路設計需要時才啟用。第一次桌上測試只接一台、使用短線、採已知 9600 8N1。若沒有回應,記錄目前 A/B 對應後只交換一次,避免反覆亂試而失去判斷依據。
通電前先填一張測試紀錄
不要讓設定只存在某位工程師的記憶裡。每次測試建立一列,寫下設備完整型號、外殼或電路板批次、通訊文件版本、供電電壓與限流值、站號、鮑率、資料格式、A/B 對應、功能碼、起始位址、數量與解析規則。再加上測試日期、程式版本和接線照片編號。日後如果同名設備換批次後讀不到,這張表能快速指出差異發生在硬體、設定或寄存器表。
第一次通電可採三段驗證。第一段只開感測器電源,量測端子電壓與極性,確認沒有把 12V 或 24V 帶到 UART 側。第二段用 USB–RS485 工具發出已知 request,保存送出與回覆的十六進位 frame。第三段才換成 ESP32,使用相同站號、serial format、FC、位址與數量。若第二段成功、第三段失敗,範圍便縮到 ESP32 腳位、UART 設定、收發模組接法或程式;若第二段也失敗,就先處理設備、供電、A/B 與現場設定。
此處也要分清楚「隔離」的邊界。DFR0845 將 UART 邏輯側與 RS-485 現場側隔開,但感測器仍需自己的合規電源與正確接地設計。模組的隔離電源能力若要拿來供外部設備,必須核對設備啟動電流、峰值與降額,不能只比較平時功耗。量測前先確認哪一側是 USB/ESP32 地,哪一側是現場電源地,避免用示波器地夾意外跨接隔離。
本例唯一可套用的寄存器表
依這個精確商品隨附的通訊協議,本例用功能碼 FC04 讀 Input Register:
| 欄位 | 本例設定 |
|---|---|
| Server ID | 1(可能已被現場修改) |
| Serial format | 9600、8N1 |
| 功能碼 | FC04,讀取 Input Register |
| 起始 PDU 位址 | 0x0001 |
| 數量 | 2 個連續 register |
0x0001 | 溫度,signed 16-bit,除以 10 得 °C |
0x0002 | 濕度,unsigned 16-bit,除以 10 得 %RH |
站號 1 的請求可表示為 01 04 00 01 00 02 20 0B。這份 mapping 只適用本文所指的精確 SKU 與相符批次文件,不能套到所有外觀相似或同樣使用 SHT40 的 RS-485 感測器。本輪未連接實體硬體進行讀值測試;以下是依已核實協議製作並通過編譯的實作候選,部署前仍要以 USB–RS485 工具和實機做交叉驗證。
可編譯的非阻塞輪詢程式
使用 Arduino Library Manager 的 modbus-esp8266 4.1.0。名稱雖含 ESP8266,該函式庫也支援 ESP32 的 RTU/TCP、client/server 與非阻塞 callback。4.1.0 的設定檔會先建立預設 RTU timeout,因此本例先載入 ModbusSettings.h,再於 ModbusRTU.h 前重設毫秒與微秒兩個巨集,讓 800 ms 真正生效;mb.task() 則要在每次 loop() 持續執行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | /* ESP32-S3-DevKitC-1 N8R2 + DFRobot DFR0845 + XY-MD04 DFR0845 UART side (cross-connect per the module's official wiring view): ESP32 GPIO17 (TX) -> DFR0845 R ESP32 GPIO16 (RX) <- DFR0845 T ESP32 3V3/GND -> DFR0845 VCC/GND DFR0845 performs direction switching internally and exposes no DE/RE pin, therefore ModbusRTU::begin() receives only the HardwareSerial object. XY-MD04 settings used by this exact example: server ID 1, 9600 8N1. FC04 reads input registers 0x0001..0x0002. Verify those settings and the A/B naming against the exact device/batch documentation before wiring. */ // modbus-esp8266 4.1.0 defines this value unconditionally in // ModbusSettings.h. Include settings once, then override both derived macros // before ModbusRTU.h so the requested 800 ms timeout is effective. #include <ModbusSettings.h> #undef MODBUSRTU_TIMEOUT #undef MODBUSRTU_TIMEOUT_US #define MODBUSRTU_TIMEOUT 800 #define MODBUSRTU_TIMEOUT_US (1000UL * MODBUSRTU_TIMEOUT) #include <ModbusRTU.h> HardwareSerial RS485(1); ModbusRTU mb; constexpr uint8_t SERVER_ID = 1; constexpr uint32_t POLL_INTERVAL_MS = 1000; constexpr uint32_t STALE_AFTER_MS = 3000; uint16_t rawWords[2] = {0, 0}; bool transactionPending = false; bool hasSuccessfulSample = false; uint32_t nextPollMs = 0; uint32_t lastSuccessMs = 0; bool sampleIsStale(uint32_t now) { return !hasSuccessfulSample || (now - lastSuccessMs > STALE_AFTER_MS); } void printFreshness(uint32_t now) { const bool stale = sampleIsStale(now); Serial.print("last_success_ms="); if (hasSuccessfulSample) { Serial.print(lastSuccessMs); } else { Serial.print("never"); } Serial.print(" stale="); Serial.println(stale ? "yes" : "no"); } bool onReadComplete(Modbus::ResultCode event, uint16_t transactionId, void *data) { (void)data; transactionPending = false; const uint32_t now = millis(); if (event == Modbus::EX_SUCCESS) { const int16_t rawTemperature = static_cast<int16_t>(rawWords[0]); const float temperatureC = rawTemperature / 10.0f; const float humidityRh = rawWords[1] / 10.0f; hasSuccessfulSample = true; lastSuccessMs = now; Serial.printf( "FC04 ok tid=%u raw[0]=0x%04X (%d) raw[1]=0x%04X (%u) " "temperature=%.1f C humidity=%.1f %%RH\n", transactionId, rawWords[0], rawTemperature, rawWords[1], rawWords[1], temperatureC, humidityRh); } else { // Includes Modbus exception responses and library-local errors such as // EX_TIMEOUT (0xE4). A failed read never turns into a numeric zero sample. Serial.printf("FC04 error tid=%u code=0x%02X\n", transactionId, static_cast<unsigned>(event)); } printFreshness(now); return true; } void setup() { Serial.begin(115200); RS485.begin(9600, SERIAL_8N1, 16, 17); // DFR0845 has automatic direction control: do not pass a DE/RE GPIO. mb.begin(&RS485); mb.client(); Serial.println("XY-MD04 FC04 polling started (ID=1, start=0x0001, count=2)"); } void loop() { // Non-blocking protocol processing must run as often as possible. mb.task(); const uint32_t now = millis(); if (!transactionPending && static_cast<int32_t>(now - nextPollMs) >= 0) { nextPollMs = now + POLL_INTERVAL_MS; transactionPending = mb.readIreg( SERVER_ID, 0x0001, rawWords, 2, onReadComplete); if (!transactionPending) { Serial.println("FC04 request was not queued (client busy or invalid request)"); printFreshness(now); } } } |
此程式不把逾時轉成 0,也不會用失敗回合覆蓋最後成功時間。raw=[...] 保留原始 word,方便跟電腦工具比對;溫度先轉為 int16_t,因此負溫可正確解析。callback 只保存結果,主迴圈才印出與換算,能避免阻塞通訊狀態機。800ms 是本例明確 timeout,不是所有 Modbus 設備的通則。
上線前至少做四個測試:正常回覆;錯功能碼得到例外 01;錯位址得到例外 02;拔除 A 或 B 後在 800ms 附近得到 0xE4。接回線後,程式應無須重開機便恢復。最後將 raw、縮放值、設備顯示與 USB–RS485 工具結果放在同一張紀錄表比較。
地址與資料解析:先翻譯,再寫程式
Modbus 有 Coil、Discrete Input、Input Register、Holding Register 四種主要資料物件。困難往往不是背名稱,而是文件的「30001」或「40001」與封包地址不同。PDU 中的資料位址是 0~65535;不少手冊的參考號碼由 1 起算,函式庫 API 卻收 zero-based offset。常見換算是資料模型編號減一,但仍要以精確手冊的封包範例確認。

每新增一種設備,就填一張「地址翻譯單」:
- 資料位於哪一區,對應 FC01、02、03 或 04?
- 手冊列的是參考號碼、PDU offset,還是已完整寫出的 request frame?
- 起算方式是 0-based 還是 1-based?
- 一筆值占一個或兩個 16-bit word?
- 是 signed、unsigned、BCD 或 IEEE 754?倍率、offset 與單位是什麼?
- 兩個 word 的排列是高字在前或低字在前?byte swap 是否另有規定?
- 哪些值代表斷線、感測器故障或超量程?資料多久後失效?
以本例來說,答案不是把「30002」填進 API,而是依協議用 FC04 從 0x0001 一次讀兩個 word。第一個轉 int16_t 再除以 10,第二個維持無號再除以 10。換一個型號、韌體或批次,這些答案都可能改變。
排錯順序:每回合只改一件事

| 現象 | 優先檢查 | 一次只做的測試 |
|---|---|---|
| 完全逾時 | 供電、A/B、站號、鮑率與同位元 | 用同參數的 USB–RS485 工具讀同一台設備 |
| 每次 CRC/亂碼 | Serial format、雜訊、參考地、收發切換 | 回到短線單機、停高雜訊負載,再觀察 UART |
| 例外 01 | 功能碼不受支援 | 按手冊改為正確 FC,不掃描寫入功能 |
| 例外 02 | 起始位址或數量錯誤 | 對照封包範例,只讀一段已知合法範圍 |
| 回覆成功但數值離譜 | signed、倍率、word/byte order | 先印 raw,再逐步解析並與參考工具比較 |
| 單台正常,多台失敗 | 重複站號、分支、終端、偏壓或輪詢過密 | 回到一台,再逐台加入並記錄錯誤率 |
| 馬達啟動時才失敗 | EMI、共模、接地、供電壓降 | 將故障時間與電源/波形/設備事件對齊 |
若完全逾時,先確認感測器端實際有合規電壓,不要先改 register。若收到例外碼,實體層多半已能往返,此時集中檢查功能碼與位址。若收到合法值但單位錯,保留線路與 baud,回到資料解析。這種分層法能把每次改動變成有證據的實驗。
善用觀測點,不用猜封包
序列監控只能看到應用層結果,必要時應增加觀測點。先在 ESP32 UART 側用邏輯分析儀確認 TX 確實送出,RX 是否收到資料,解碼設定也必須與 9600 8N1 一致。UART 有 request、A/B 卻沒有活動,優先檢查收發模組供電與接線;A/B 有回覆、UART RX 沒資料,則回頭看 DFR0845 的 T 線與邏輯側供電。量 RS-485 差動訊號要用合適的差動探棒或隔離量測方法,不能隨意把接地式示波器探棒跨到未知電位的現場線。
保存一組正常 frame,日後故障時逐欄比對站號、FC、起始位址、數量、CRC 與回覆長度。CRC 通常由成熟函式庫產生與驗證;應用程式的工作是保留錯誤碼與事件時間,而不是在已正確運作的函式庫外再包一套互相矛盾的 CRC。若錯誤只在特定負載啟動時出現,將 frame 錯誤時間與馬達、繼電器、變頻器及電源最低點對齊,往往比反覆換函式庫更快找到根因。
從偶爾成功到可長期運轉
一條半雙工 RTU bus 同時只能有一個請求。每台設備應保存 next_due、最後成功時間、連續失敗數與 round-trip time。輪詢週期先看設備的資料更新速度,再用現場實測留餘裕。發生 timeout 時可做一次短重試;連續失敗後採 1、2、5 秒等有上限的退避,避免故障設備塞滿整條 bus。
「有上次數值」和「現在有有效數值」是兩回事。程式中的 lastGoodAt 與 STALE_AFTER_MS 就是最小實作。監看畫面應分別顯示 valid、stale、offline;控制邏輯遇到 stale 應進入預先定義的 fail-safe,而不是沿用舊溫度,更不能把 timeout 當成 0°C 或 0%RH。
配線擴充時採 trunk/daisy-chain,支線保持短。終端只位於幹線兩個物理端點,阻值與是否啟用依線材阻抗、速率、收發器和設備文件決定;不是每台都打開 120Ω。偏壓/fail-safe 網路也由整條 bus 統一管理,先盤點模組是否內建,避免多組電阻並聯造成過重負載。
先定義可接受的服務品質
「穩定」要能量化。環境監測可以先定義每台設備的目標更新週期、允許逾時率、最大連續失敗次數與 freshness deadline。例如畫面每秒更新一次,並不代表每 10ms 輪詢一次;一秒一次 request 已足夠時,多出的流量只會壓縮其他站點的回應空間。若某設備本身每半秒才更新內部量測,更快讀取通常只會得到重複值。
多站排程不要用一串固定 delay()。為每台 server 保存下一次到期時間,讓快速控制資料與慢速環境資料分組。每回合只排入一筆 transaction,完成或逾時後才排下一筆。記錄每台的回應時間分布,而不只平均值;timeout 應高於正常高分位延遲並留合理餘裕,但也不能長到故障站長時間霸占輪詢表。
告警同樣要分層。單次 CRC 或 timeout 可記錄為通訊事件,不必立刻宣告設備故障。連續多次失敗後才轉為 offline,能降低瞬態雜訊造成的告警風暴。恢復時可要求連續兩次成功再回到 healthy,並保留故障開始、恢復、累積次數與當時設備事件。這些規則應可設定、有預設值,而且在畫面上看得見。
資料消費端還要認得品質旗標。送往 MQTT、資料庫或 SCADA 時,除了溫度和濕度,也帶上量測時間、接收時間、站號、map 版本與 quality。若值已 stale,保留最後數字可以協助診斷,但 quality 必須明確標示失效;自動控制只能取用符合新鮮度與範圍檢查的資料。如此一來,通訊中斷不會被誤解成製程真的變成零值。
隔離耐壓、TVS 與 ESD 數字只描述特定保護能力,不等於整機已通過 EMC、EFT、surge、溫度、IP 或安規認證。跨盤、戶外、不同接地系統與變頻器附近,需另做屏蔽、接地、浪湧、隔離電源與長時間壓力測試。開發板桌上讀得到,是功能證明;不是產線放行證明。
何時繼續 RTU,何時轉 TCP 或閘道器
同一機台或控制箱內只有幾台儀表,隔離 RS-485 加 RTU 通常容易維護。多個遠端盤體已有受管理 Ethernet 時,可讓每盤保留短 RTU bus,再以真正的協定閘道器轉成 Modbus TCP。閘道器必須處理 RTU frame 與 TCP 的 MBAP header、Unit Identifier 和連線管理,並提供清楚的映射文件。
透明串列隧道只是把收到的 bytes 搬進 TCP socket。它可能傳送 RTU-over-TCP,卻不會因此成為 Modbus TCP gateway。尤其常見的 Waveshare RS485 TO ETH 透明傳輸模組,官方明示不支援 Modbus TCP;不要因商品名稱或網路埠就把兩者畫上等號。
| 現場需求 | 優先架構 | 主要條件 |
|---|---|---|
| 單一控制箱內數台設備 | ESP32+隔離 RS-485+RTU | 管好站號、終端、電源與維護介面 |
| 多盤體且已有 OT Ethernet | 每盤 RTU+協定閘道器+TCP | 文件化 Unit ID、映射、連線容量與故障行為 |
| Wi-Fi 只用來上傳監測值 | RTU client 與 HTTPS/MQTT 應用分層 | 不必對外提供 Modbus TCP |
| SCADA 在受管 OT LAN 輪詢 | Modbus TCP server/gateway | 固定資產清冊、VLAN、ACL 與允許清單 |
| 跨網際網路維護 | VPN/受控跳板後再進 OT 區 | TCP 502 不得直接 port-forward 到公網 |
Modbus TCP 使用 MBAP header 加 PDU,標準連接埠為 502,不使用 RTU CRC,也沒有 A/B、baud 或串列終端。一般 Modbus TCP 不提供應用期待的身分驗證與加密。需要更完整的協定安全時,可評估以 TLS 和憑證為基礎、使用 802 埠的 Modbus Security;無論哪條路,都仍要有網路分區、allowlist firewall/ACL、日誌、更新與撤權流程。
選閘道器時至少問六件事:它是 protocol gateway 還是 transparent tunnel;可同時維持多少 TCP connection;多個 client 如何分享一條 RTU bus;Unit ID 如何映射到 serial server ID;逾時、例外與斷線如何回報;設定檔能否匯出、版本控管與快速還原。若 SCADA 同時快速輪詢,而閘道器又允許多個維護工具連線,排程不清楚就可能把原本穩定的 RTU 線塞滿。
切換架構前先畫資料所有權。現場閉迴路控制應能在上層網路中斷時維持安全狀態;監測與歷史資料可延遲補送;遠端寫入則要有更嚴格的角色、範圍與稽核。測試不只驗證「允許的人連得上」,也要從辦公網、訪客網及未列入清冊的主機確認連不上。遠端帳號撤權、憑證過期、閘道重開與時間不同步,也都應列入驗收。
進產線前的放行清單
- [ ] BOM 寫到精確開發板/模組、收發器、隔離電源、保護元件、端子與替代料,不只寫「ESP32+485」。
- [ ] 每個設備 SKU、批次與韌體都有版本化 register map;功能碼、PDU 位址、signed、倍率與 word order 可追溯。
- [ ] 每台 server 站號唯一,baud、parity、stop bits 與設定方式已記錄;變更後是否要重新上電也完成批次驗證。
- [ ] 做過斷線、A/B 反接、重複站號、錯 baud、例外碼、CRC 錯誤、設備斷電與 bus stuck 測試。
- [ ] 定義 timeout、重試、退避、stale、offline、fail-safe 與通訊恢復行為;恢復時輸出不突跳。
- [ ] 日誌至少包含時間、站號、FC、起始位址、數量、結果碼、往返時間、連續失敗與最後成功時間。
- [ ] 寫入功能預設關閉;確有需求時才加入權限、範圍檢查、稽核與 read-back。
- [ ] 完成供電擾動、溫度、EMI/ESD/EFT、線長、接地與長時間 soak 測試;保護元件規格不冒充整機認證。
- [ ] TCP/Wi-Fi 僅開放給清冊中的 client;辦公網與訪客網的負測試必須連不上 502。
- [ ] 沒有硬編碼密碼、私鑰或預設憑證;停用遠端帳號後重新連線必須失敗。
- [ ] 維護介面能看見韌體、register map 版本、錯誤率、last-good 與 stale 狀態。
- [ ] 批量採購前,用預計線材、電源、閘道與至少一個實際批次完成交叉驗證,並保留合格樣品。
第一台的成功標準不是「序列監控出現一個看似合理的數字」,而是能重現 request、核對 raw、說明每一步轉換,且斷線後進入可預測狀態。把測試紀錄、接線版本、程式版號與合格 raw frame 一起交接,下一位維護者才能分辨設定被改動、設備換批或線路劣化,而不必從交換 A/B 重新開始。先把這條閉環做紮實,再逐台擴充。當維護範圍跨盤、跨網段或進入 SCADA,才升級為有映射、有存取控制、有故障定義的閘道架構。這樣從開發板到產線,每一次升級都有清楚的技術理由,而不是靠換線與重開機碰運氣。

發佈留言
很抱歉,必須登入網站才能發佈留言。