戰(zhàn):Zigbee 3.0開(kāi)發(fā)環(huán)境搭建與組網(wǎng)避坑指南)
前幾天看到ST的官網(wǎng)更新STM32無(wú)線MCU的官方固件正式把Zigbee 3.0協(xié)議棧納入支持范圍。說(shuō)句實(shí)話這個(gè)動(dòng)作對(duì)做智能家居、傳感網(wǎng)絡(luò)、工業(yè)無(wú)線采集的人來(lái)說(shuō)是個(gè)挺實(shí)在的好消息。以前想在STM32上跑Zigbee要么用外掛透?jìng)髂K要么守著老舊的Zigbee協(xié)議棧自己折騰移植既占成本又費(fèi)時(shí)間?,F(xiàn)在STM32WB系列這些自帶2.4GHz射頻的芯片終于能直接在官方工具鏈里把Zigbee 3.0拉起來(lái)用了。這篇文章不打算復(fù)述什么官方發(fā)布說(shuō)明也沒(méi)必要去念release notes。我會(huì)從實(shí)際動(dòng)手折騰過(guò)這塊板子的角度聊聊Zigbee 3.0到底能解決什么問(wèn)題、開(kāi)發(fā)環(huán)境怎么搭、一個(gè)最小網(wǎng)絡(luò)怎么跑通以及調(diào)試時(shí)你大概率會(huì)撞上的那些坑。如果你手上有NUCLEO-WB55RG這類開(kāi)發(fā)板正想用它做Zigbee 3.0節(jié)點(diǎn)這篇內(nèi)容應(yīng)該能幫你少走不少?gòu)澛贰?. Zigbee 3.0 和 STM32 無(wú)線 MCU 是怎么湊到一塊的1.1 Zigbee 3.0 到底是什么為什么開(kāi)發(fā)者都在等它Zigbee 3.0本質(zhì)上不是一個(gè)新協(xié)議而是把過(guò)去分散的ZHAZigbee Home Automation、ZLLZigbee Light Link、ZBOZigbee Building Operations這些profile統(tǒng)一成了一套標(biāo)準(zhǔn)。你可以把它理解為以前的Zigbee世界像是幾家各自為戰(zhàn)的方言區(qū)雖然底層都是802.15.4但設(shè)備之間不一定能互通Zigbee 3.0則強(qiáng)制統(tǒng)一了應(yīng)用層的Cluster定義、設(shè)備描述、入網(wǎng)流程和安全機(jī)制?,F(xiàn)在一個(gè)Zigbee 3.0的燈泡理論上可以跟另一個(gè)廠商Zigbee 3.0的開(kāi)關(guān)無(wú)縫配對(duì)不用再糾結(jié)是不是同一個(gè)生態(tài)。對(duì)開(kāi)發(fā)者來(lái)說(shuō)統(tǒng)一的最大好處是開(kāi)發(fā)和測(cè)試成本下降。以前做Zigbee產(chǎn)品每個(gè)profile都要單獨(dú)適配測(cè)試矩陣鋪得很大?,F(xiàn)在只要基于ZCLZigbee Cluster Library標(biāo)準(zhǔn)Cluster開(kāi)發(fā)設(shè)備天然具備了跨廠商互操作的基礎(chǔ)。另外Zigbee 3.0在安全上也做了加強(qiáng)默認(rèn)支持Secure Join、鏈路層加密、密鑰更新機(jī)制不像早期Zigbee那樣動(dòng)不動(dòng)就裸奔在2.4GHz頻段上。這也是為什么很多智能家居網(wǎng)關(guān)、傳感器網(wǎng)絡(luò)、智能照明項(xiàng)目在協(xié)議選型時(shí)會(huì)優(yōu)先考慮Zigbee 3.0而不是自組私有協(xié)議或Wi-Fi直連——它兼顧了低功耗、低帶寬、大規(guī)模組網(wǎng)和互操作性。1.2 STM32 無(wú)線 MCU 家族的硬件底子夠不夠格ST官方這次說(shuō)的“STM32 Wireless MCUs”主要指STM32WB系列和更新的STM32WBA系列。STM32WB是目前最常用的雙核無(wú)線SoC內(nèi)置一個(gè)Cortex-M4F應(yīng)用內(nèi)核和一個(gè)Cortex-M0網(wǎng)絡(luò)協(xié)處理器同時(shí)集成了2.4GHz射頻收發(fā)器。它既能跑BLE 5.0也能跑Zigbee 3.0、OpenThread和802.15.4 MAC。具體型號(hào)從低端的STM32WB15、STM32WB10到全功能的STM32WB55Flash和SRAM容量差異挺大但射頻底子基本是同一套。STM32WB55最高主頻64MHz的M4F1MB Flash適合做網(wǎng)關(guān)或復(fù)雜節(jié)點(diǎn)STM32WB35中等容量適合做傳感器節(jié)點(diǎn)、燈控模塊STM32WB15低成本小封裝適合做單功能終端設(shè)備STM32WBA52更新的M33內(nèi)核平臺(tái)主頻更高安全特性更強(qiáng)在這幾個(gè)型號(hào)里選型主要看你要跑的應(yīng)用程序有多重。如果只是把Zigbee協(xié)議棧跑起來(lái)然后遙控個(gè)燈、讀個(gè)溫濕度STM32WB15就夠了。如果還要本地跑一些濾波算法、顯示界面、本地日志那得上WB55或者WBA52。芯片本身的Zigbee協(xié)議棧是預(yù)編譯好的庫(kù)運(yùn)行在M0核心上不占用M4的資源這一點(diǎn)對(duì)應(yīng)用開(kāi)發(fā)非常友好。1.3 雙核架構(gòu)協(xié)議棧和應(yīng)用是怎么分工的很多第一次接觸STM32WB的人會(huì)問(wèn)為什么一顆MCU要搞雙核答案就是為了隔離和實(shí)時(shí)性。Zigbee協(xié)議棧對(duì)時(shí)間敏感信標(biāo)、ACK、重傳都有嚴(yán)格的時(shí)序要求。如果和應(yīng)用代碼擠在一個(gè)核上一旦應(yīng)用里出現(xiàn)大循環(huán)或阻塞操作協(xié)議棧分分鐘會(huì)丟包掉線。STM32WB把無(wú)線協(xié)議棧固化在M0核上M0跑協(xié)議棧和射頻調(diào)度M4跑用戶應(yīng)用兩者通過(guò)共享內(nèi)存和Mailbox通信。開(kāi)發(fā)者在M4上寫的業(yè)務(wù)邏輯哪怕里面有個(gè)很耗時(shí)的浮點(diǎn)運(yùn)算也不會(huì)直接影響射頻收發(fā)的時(shí)序。協(xié)議棧和應(yīng)用之間的API由ST封裝好了使用時(shí)主要就是初始化Zigbee協(xié)議棧、注冊(cè)Cluster、發(fā)送和接收Z(yǔ)CL命令。你不太需要關(guān)心底層802.15.4幀細(xì)節(jié)只需要理解Zigbee網(wǎng)絡(luò)層和應(yīng)用層的幾個(gè)概念設(shè)備類型Coordinator、Router、EndDevice、PAN ID、信道、Endpoint、Cluster。理解了這些后面跑通例程就不難。2. 開(kāi)發(fā)環(huán)境準(zhǔn)備工具鏈和固件棧一個(gè)都不能少2.1 裝上這幾個(gè)工具基本就齊活了開(kāi)發(fā)STM32WB的Zigbee 3.0應(yīng)用工具鏈比想象中要長(zhǎng)一點(diǎn)但都是ST官方的東西用起來(lái)比較省心。我建議把這幾個(gè)都裝齊工具作用備注STM32CubeMX圖形化配置引腳、時(shí)鐘、中間件生成工程建議用較新版本兼容Zigbee 3.0STM32CubeIDE編譯、調(diào)試一體化IDE也可用Keil/IAR替代ST官方例程基本都是CubeIDE工程STM32CubeProgrammer燒錄FUS固件、無(wú)線協(xié)議棧、用戶程序燒Zigbee協(xié)議棧必須用它STM32CubeMonitor-RF802.15.4無(wú)線抓包分析排查Zigbee入網(wǎng)問(wèn)題非常有用這些工具在ST官網(wǎng)都能下載。國(guó)內(nèi)下載速度有時(shí)候會(huì)比較感人建議挑個(gè)網(wǎng)絡(luò)空閑時(shí)段或者用官方提供的下載加速方式。還有一點(diǎn)要注意STM32CubeWB固件包通常很大里面包含了協(xié)議棧庫(kù)、例程、文檔下載后不要急著刪后面找例程和API文檔都要用。2.2 用 CubeMX 配置一個(gè)帶 Zigbee 3.0 的工程打開(kāi)STM32CubeMX選擇芯片型號(hào)比如STM32WB55RGV6。在中間的軟件包管理里要確保下載了對(duì)應(yīng)版本的STM32CubeWB固件包。然后在“Middleware and Software Packs”里勾選“Zigbee 3.0”CubeMX會(huì)幫你把協(xié)議棧相關(guān)的組件加進(jìn)來(lái)。接下來(lái)要配置幾個(gè)關(guān)鍵參數(shù)設(shè)備類型Coordinator、Router還是EndDevice。協(xié)調(diào)器負(fù)責(zé)建網(wǎng)一個(gè)Zigbee網(wǎng)絡(luò)里有且只能有一個(gè)協(xié)調(diào)器。PAN ID網(wǎng)絡(luò)ID范圍是0x0000到0xFFFE0xFFFF會(huì)被解釋成廣播網(wǎng)絡(luò)ID不能用作實(shí)際PAN ID。信道2.4GHz下可選11到26信道。家庭環(huán)境中Wi-Fi用的是1、6、11等信道為避免同頻干擾通常建議選15、20、25附近。SecurityZigbee 3.0默認(rèn)開(kāi)啟安全模式配置里一般保持默認(rèn)。這些參數(shù)在CubeMX里配置好之后直接生成代碼。生成的工程里會(huì)有一個(gè)類似MX_ZIGBEE_Init()的調(diào)用但實(shí)際上Zigbee的啟動(dòng)邏輯比普通外設(shè)稍微復(fù)雜一點(diǎn)ST官方例程一般會(huì)單獨(dú)寫一個(gè)APP_Zigbee_Init()在main函數(shù)里初始化外設(shè)后再調(diào)用。我習(xí)慣把串口、LED、按鍵這些基礎(chǔ)外設(shè)也在CubeMX里一起配好這樣后面調(diào)試日志輸出和現(xiàn)象觀察都方便。2.3 FUS 升級(jí)與協(xié)議棧燒錄STM32WB的Flash布局比較特殊不像普通STM32那樣一個(gè)程序燒進(jìn)去就完事。它有三個(gè)分區(qū)用戶應(yīng)用區(qū)、無(wú)線協(xié)議棧區(qū)、FUS區(qū)。FUS全稱是Firmware Upgrade Services負(fù)責(zé)無(wú)線協(xié)議棧的安裝和升級(jí)相當(dāng)于一個(gè)系統(tǒng)引導(dǎo)服務(wù)。新買回來(lái)的芯片出廠時(shí)可能已經(jīng)帶了FUS但版本不一定滿足你的協(xié)議棧要求所以第一步通常是用STM32CubeProgrammer檢查FUS版本必要時(shí)先升級(jí)FUS。燒無(wú)線協(xié)議棧時(shí)要注意這不是用普通全片擦除方式燒錄而是用CubeProgrammer的“Firmware upgrade”功能。選擇STM32CubeWB固件包里的協(xié)議棧文件例如stm32wb5x_Zigbee_3_0_fw.bin工具會(huì)自動(dòng)識(shí)別目標(biāo)地址。這里有幾個(gè)容易踩的坑不要用“Erase All”去擦除整個(gè)芯片否則FUS可能被抹掉后面協(xié)議棧就裝不上了。燒錄完成后再燒用戶應(yīng)用代碼。用戶代碼一般編譯成hex按正常方式下載到0x08000000起始的應(yīng)用區(qū)。如果燒錄過(guò)程中提示FUS操作失敗大概率是FUS版本太老先升級(jí)FUS再燒協(xié)議棧。我第一次接觸這個(gè)流程時(shí)直接把芯片擦了個(gè)干干凈凈然后又花了半天重新恢復(fù)FUS。后面我會(huì)在第五章詳細(xì)講這個(gè)坑。3. 實(shí)操兩臺(tái)開(kāi)發(fā)板組一個(gè)最小的 Zigbee 3.0 網(wǎng)絡(luò)3.1 硬件準(zhǔn)備和板級(jí)連接要做最小驗(yàn)證推薦準(zhǔn)備兩塊NUCLEO-WB55RG板子一塊做協(xié)調(diào)器一塊做路由器或者終端設(shè)備。如果沒(méi)有兩塊板子也可以用STM32WB55 USB Dongle配合一塊開(kāi)發(fā)板Dongle做協(xié)調(diào)器開(kāi)發(fā)板做終端效果類似。接線部分其實(shí)很簡(jiǎn)單NUCLEO板載ST-LINK直接用USB線連電腦就行。串口輸出用板上的虛擬串口通過(guò)ST-LINK的VCP功能在設(shè)備管理器里能看到一個(gè)COM口。我習(xí)慣在CubeMX里把USART1配置成115200-8-N-1并在main函數(shù)里重定向printf到串口這樣Zigbee協(xié)議棧的日志、入網(wǎng)事件、命令收發(fā)信息都可以直接打出來(lái)看。3.2 協(xié)調(diào)器端配置與代碼修改協(xié)調(diào)器端的配置以STM32CubeWB官方例程Zigbee_OnOff_Coordinator為基礎(chǔ)。核心代碼在APP_Zigbee_Init()里真正啟動(dòng)網(wǎng)絡(luò)的配置是一個(gè)ZbStartupConf_t結(jié)構(gòu)體static void APP_Zigbee_Init(void) { ZbStartupConf_t startupConfig {0}; /* 設(shè)備類型協(xié)調(diào)器 */ startupConfig.deviceType ZbCoordinator; /* PAN ID自己定義一個(gè)比如 0x1234 */ startupConfig.panId 0x1234; /* 選用信道 15盡量避免和家用Wi-Fi沖突 */ startupConfig.channel 15; /* Zigbee 3.0 安全模式默認(rèn)開(kāi)啟 */ startupConfig.zigbeeSecurity ZbZigbeeSecurityStandard; /* 初始化協(xié)議棧 */ Zigbee_Init(startupConfig); }啟動(dòng)之后協(xié)調(diào)器會(huì)創(chuàng)建一個(gè)網(wǎng)絡(luò)自己的短地址固定是0x0000。串口日志里會(huì)打印類似“Network started”的信息。接著協(xié)調(diào)器會(huì)等待其他設(shè)備入網(wǎng)一旦有設(shè)備加入事件回調(diào)里會(huì)觸發(fā)ZbZclEventDeviceJoin之類的事件這時(shí)可以在回調(diào)里把入網(wǎng)設(shè)備的短地址、IEEE地址打出來(lái)。需要注意的是Zigbee_Init()只會(huì)把協(xié)議棧初始化真正的事件處理需要你自己注冊(cè)一個(gè)回調(diào)函數(shù)。ST例程里這個(gè)回調(diào)叫APP_Zigbee_EventHandler里面根據(jù)事件類型做分支處理。比如收到On/Off命令時(shí)就控制板載LED翻轉(zhuǎn)。3.3 路由/終端設(shè)備端配置第二塊板子配置成Router或者EndDevice代碼改動(dòng)的核心參數(shù)就兩個(gè)startupConfig.deviceType ZbRouter; /* 或 ZbEndDevice */如果配置成Router它會(huì)主動(dòng)掃描周圍已有的Zigbee網(wǎng)絡(luò)找到PAN ID匹配或者開(kāi)放加入的網(wǎng)絡(luò)后發(fā)送關(guān)聯(lián)請(qǐng)求。如果協(xié)調(diào)器的PAN ID是0x1234Router這邊最好也填0x1234或者在啟動(dòng)配置里允許“加入任何網(wǎng)絡(luò)”否則可能出現(xiàn)找不到網(wǎng)絡(luò)的問(wèn)題。入網(wǎng)成功后Router設(shè)備的串口日志會(huì)打印自己被分配到的短地址這個(gè)地址在Zigbee網(wǎng)絡(luò)里是唯一的。協(xié)調(diào)器那邊也會(huì)同時(shí)打印出該設(shè)備入網(wǎng)的事件??吹絻蛇吶罩径颊Uf(shuō)明一個(gè)最小的Zigbee 3.0網(wǎng)絡(luò)已經(jīng)建起來(lái)了。這個(gè)過(guò)程中如果遇到“網(wǎng)絡(luò)掃描超時(shí)”或者“關(guān)聯(lián)失敗”大概率是信道不一致或者PAN ID不匹配后面第五章會(huì)詳細(xì)說(shuō)排查方法。3.4 聯(lián)調(diào)入網(wǎng)、綁定、無(wú)線點(diǎn)燈網(wǎng)絡(luò)建好之后最經(jīng)典的驗(yàn)證方式就是無(wú)線點(diǎn)燈。Zigbee 3.0標(biāo)準(zhǔn)化了On/Off ClusterCluster ID 0x0006它定義了兩個(gè)基本命令On0x01和Off0x00。協(xié)調(diào)器作為On/Off Client向Router上的On/Off Server發(fā)送命令Router收到后翻轉(zhuǎn)LED。在ST的例程里發(fā)送路由節(jié)點(diǎn)的On/Off命令大概是這樣/* 找到目標(biāo)端點(diǎn)上的 On/Off Client Cluster */ ZbZclCluster_t *clientCluster ZbZclOnOffClientFind(endpoint); /* 目標(biāo)地址路由節(jié)點(diǎn)的短地址入網(wǎng)時(shí)打印出來(lái) */ ZbZclAddrInfo_t dstAddr; dstAddr.type ZB_ZCL_ADDR_TYPE_SHORT; dstAddr.shortAddr routerShortAddress; dstAddr.endpoint 1; /* 發(fā)送 On 命令 */ ZbZclOnOffClientSendCommand(clientCluster, dstAddr, ZCL_ONOFF_COMMAND_ON, TRUE);在Router端注冊(cè)O(shè)n/Off Server后收到On命令就會(huì)執(zhí)行回調(diào)?;卣{(diào)里寫一句HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET)燈的亮滅就跟著無(wú)線命令走了。這整套流程跑通之后你其實(shí)已經(jīng)掌握了大半個(gè)Zigbee 3.0開(kāi)發(fā)套路。后面做傳感器上報(bào)、做群組控制、做場(chǎng)景聯(lián)動(dòng)本質(zhì)上都是圍繞Cluster和Endpoint做文章。4. 結(jié)合真實(shí)項(xiàng)目擴(kuò)展從點(diǎn)燈到傳感器上報(bào)和電機(jī)控制4.1 把 Zigbee 數(shù)據(jù)接到自己的業(yè)務(wù)邏輯里點(diǎn)燈驗(yàn)證沒(méi)問(wèn)題后很多人第一反應(yīng)是我能不能讓節(jié)點(diǎn)上報(bào)溫濕度、控制電機(jī)、讀取電量當(dāng)然可以而且Zigbee 3.0已經(jīng)把這些應(yīng)用場(chǎng)景標(biāo)準(zhǔn)化了。比如傳感器節(jié)點(diǎn)可以用Temperature Measurement ClusterCluster ID 0x0402周期上報(bào)溫度智能臺(tái)燈可以用Level Control ClusterCluster ID 0x0008調(diào)節(jié)明暗窗簾電機(jī)可以用Window Covering ClusterCluster ID 0x0102控制開(kāi)合。使用標(biāo)準(zhǔn)Cluster的好處是你節(jié)點(diǎn)上報(bào)的數(shù)據(jù)別人家的Zigbee 3.0網(wǎng)關(guān)或面板也能直接解析。在實(shí)際項(xiàng)目里我通常會(huì)把Zigbee協(xié)議棧的處理和應(yīng)用邏輯拆開(kāi)。Zigbee事件回調(diào)里只負(fù)責(zé)收數(shù)據(jù)、解析Cluster、設(shè)置標(biāo)志位真正控制執(zhí)行器、處理傳感器數(shù)據(jù)的主循環(huán)放在M4核的while(1)里。這樣分工清晰調(diào)試時(shí)也容易定位是無(wú)線鏈路的問(wèn)題還是業(yè)務(wù)邏輯的問(wèn)題。4.2 傳感器周期上報(bào)和低功耗設(shè)計(jì)如果你做的是電池供電的傳感器節(jié)點(diǎn)那么終端設(shè)備EndDevice模式比路由模式更合適。終端設(shè)備大部分時(shí)間處于休眠狀態(tài)只有采集和上報(bào)時(shí)喚醒功耗能壓得很低。STM32WB在休眠方面支持多種低功耗模式再配合Zigbee協(xié)議棧的休眠管理做溫濕度計(jì)、門窗傳感器、人體紅外檢測(cè)這一類產(chǎn)品是比較理想的。簡(jiǎn)單的上報(bào)流程可以這樣設(shè)計(jì)終端設(shè)備定時(shí)喚醒例如用RTC或LPTIM喚醒后讀取傳感器數(shù)據(jù)重新加入網(wǎng)絡(luò)如果休眠期間掉線會(huì)自動(dòng)重連通過(guò)ZCL的Report Attributes或自定義的Cluster上報(bào)數(shù)據(jù)上報(bào)完成后再次進(jìn)入休眠這里要注意終端設(shè)備不能隨意長(zhǎng)時(shí)間休眠因?yàn)楦腹?jié)點(diǎn)通常是Router或Coordinator需要緩存發(fā)給它的數(shù)據(jù)。如果休眠時(shí)間太長(zhǎng)、緩存溢出數(shù)據(jù)就會(huì)丟。Zigbee 3.0的終端設(shè)備一般會(huì)配置Polling輪詢周期和父節(jié)點(diǎn)保持心跳這個(gè)參數(shù)需要根據(jù)實(shí)際功耗和實(shí)時(shí)性需求去平衡。4.3 場(chǎng)景延伸485伺服、N20減速電機(jī)也能被 Zigbee 管起來(lái)很多做機(jī)電控制的朋友問(wèn)Zigbee能不能用來(lái)遠(yuǎn)程控制伺服電機(jī)、直流減速電機(jī)這類執(zhí)行器。完全可以關(guān)鍵是看你對(duì)實(shí)時(shí)性的要求有多高。如果是開(kāi)關(guān)型控制——比如N20減速電機(jī)驅(qū)動(dòng)一個(gè)窗簾開(kāi)合、一個(gè)門鎖動(dòng)作用On/Off Cluster就夠了。收到On命令電機(jī)正轉(zhuǎn)收到Off命令反轉(zhuǎn)或者停止。這種場(chǎng)景對(duì)延遲不敏感可靠性和低功耗遠(yuǎn)比毫秒級(jí)實(shí)時(shí)性重要。如果是位置型控制比如帶編碼器的伺服電機(jī)要精確轉(zhuǎn)到某個(gè)角度那就需要在應(yīng)用層定義Position Cluster或者擴(kuò)展Level Control Cluster用百分比或者線性數(shù)值代表目標(biāo)位置。如果伺服電機(jī)通過(guò)RS485總線控制那么STM32WB的M4核負(fù)責(zé)Zigbee協(xié)議棧命令解析然后把解析結(jié)果轉(zhuǎn)成Modbus RTU或者自定義485幀通過(guò)USARTRS485收發(fā)器發(fā)給伺服驅(qū)動(dòng)器。這樣一來(lái)整個(gè)無(wú)線控制鏈路由應(yīng)用代碼自己定義Zigbee只負(fù)責(zé)無(wú)線傳輸非常靈活。我自己做過(guò)一個(gè)實(shí)驗(yàn)Zigbee 3.0協(xié)調(diào)器發(fā)送“轉(zhuǎn)到30%”的命令終端設(shè)備收到后通過(guò)485發(fā)送0x01 0x06 0x00 0x00 0x1E 0x00這種Modbus寫寄存器幀給伺服實(shí)測(cè)無(wú)線命令的端到端延遲大概在幾十毫秒量級(jí)用于非高精度的工業(yè)控制場(chǎng)景完全夠用。5. 實(shí)戰(zhàn)避坑我踩過(guò)的幾個(gè) Zigbee 調(diào)試問(wèn)題5.1 協(xié)議棧版本跟 CubeMX 版本不匹配這是最容易遇到的坑。STM32CubeWB固件包更新頻率不低協(xié)議棧庫(kù)也在不斷迭代。如果CubeMX的版本太老生成的代碼可能調(diào)用了一些舊API跟新協(xié)議棧庫(kù)不兼容編譯就會(huì)報(bào)一堆找不到函數(shù)的錯(cuò)誤。反過(guò)來(lái)CubeMX版本太新但固件包沒(méi)更新也可能出現(xiàn)中間件配置界面識(shí)別不到Zigbee 3.0的情況。我的建議是不要一味追求最新而是選擇一套經(jīng)過(guò)驗(yàn)證的組合。比如先固定使用某個(gè)較新的STM32CubeWB固件包然后讓CubeMX自動(dòng)匹配對(duì)應(yīng)的中間件版本?;蛘咧苯影压俜嚼套鳛槠瘘c(diǎn)在自己的代碼里增量開(kāi)發(fā)而不是每次都用CubeMX重新生成這樣能大幅減少配置不一致帶來(lái)的麻煩。5.2 串口日志亂碼和 printf 重映射Zigbee協(xié)議棧自身的調(diào)試信息是通過(guò)底層接口輸出的如果你沒(méi)有正確重定向printf或者串口波特率設(shè)置不一致日志就會(huì)變成亂碼。我自己用過(guò)一種很簡(jiǎn)單的排查方法先寫一個(gè)不帶Zigbee的裸機(jī)點(diǎn)燈工程單獨(dú)測(cè)試串口輸出確認(rèn)硬件鏈路沒(méi)問(wèn)題再打開(kāi)Zigbee工程調(diào)試。這樣能把問(wèn)題域隔離開(kāi)。另外STM32WB的CPU頻率是可以通過(guò)CubeMX配置的一般主頻選64MHzM4/32MHzM0。串口波特率計(jì)算要基于實(shí)際時(shí)鐘頻率如果時(shí)鐘配置改了但CubeMX里的波特率設(shè)置沒(méi)重新計(jì)算也會(huì)導(dǎo)致亂碼。解決方式是確認(rèn)HAL_RCC_ClockConfig返回正常值串口初始化用的波特率參數(shù)和實(shí)際時(shí)鐘匹配。5.3 抓包抓不到或抓包后串口失效Zigbee調(diào)試和BLE調(diào)試類似空中的問(wèn)題很難靠猜抓包工具幾乎是必需品。ST官方推薦的是STM32CubeMonitor-RF配合STM32WB55 USB Dongle或者板載ST-LINK的Sniffer模式使用。這里有個(gè)大坑如果啟用Sniffer模式板載ST-LINK的虛擬串口功能會(huì)被禁用也就是說(shuō)你無(wú)法同時(shí)用這塊板子的串口打印Zigbee日志。所以我的做法比較粗暴準(zhǔn)備兩塊板子一塊專門當(dāng)Sniffer另一塊跑協(xié)調(diào)器或路由器節(jié)點(diǎn)。抓包時(shí)先把Sniffer板切換到Sniffer模式再用STM32CubeMonitor-RF在對(duì)應(yīng)信道抓包觀察入網(wǎng)流程、信標(biāo)請(qǐng)求、關(guān)聯(lián)請(qǐng)求、數(shù)據(jù)確認(rèn)這些802.15.4幀。調(diào)試完再切回正常模式不然串口日志會(huì)一直出不來(lái)。5.4 入網(wǎng)失敗、網(wǎng)絡(luò)不穩(wěn)怎么定位設(shè)備入網(wǎng)失敗是Zigbee開(kāi)發(fā)里最頭疼的問(wèn)題原因往往不止一個(gè)。如果Router或EndDevice啟動(dòng)后一直找不到網(wǎng)絡(luò)按優(yōu)先級(jí)排查這幾個(gè)點(diǎn)PAN ID是否匹配協(xié)調(diào)器的PAN ID和終端設(shè)備配置的PAN ID是否一致或者終端是否配置為允許加入任何網(wǎng)絡(luò)。信道是否一致協(xié)調(diào)器和終端必須在同一個(gè)信道上??梢杂肧niffer抓包確認(rèn)協(xié)調(diào)器是不是在設(shè)定的信道廣播信標(biāo)。安全密鑰是否一致Zigbee 3.0支持預(yù)配置鏈路密鑰如果兩邊密鑰不同關(guān)聯(lián)請(qǐng)求會(huì)失敗。射頻硬件是否正常有些STM32WB開(kāi)發(fā)板需要正確連接天線或焊上匹配網(wǎng)絡(luò)否則射頻功率很低近距離都搜不到。給板子外接天線時(shí)要確保板載天線跳線帽選對(duì)了位置。網(wǎng)絡(luò)不穩(wěn)定、掉線頻繁的情況優(yōu)先懷疑射頻干擾。2.4GHz頻段被Wi-Fi、藍(lán)牙、微波爐這些設(shè)備擠得滿滿當(dāng)當(dāng)可以嘗試換一個(gè)干凈一點(diǎn)的信道。Zigbee 3.0的信道個(gè)數(shù)不多但選擇合適信道能顯著提升穩(wěn)定性。我在實(shí)驗(yàn)室里調(diào)試時(shí)周圍Wi-Fi路由器很多最后鎖定信道25基本沒(méi)有再出現(xiàn)過(guò)批量掉線的問(wèn)題。5.5 Flash 燒錄順序和地址的坑回到前面提到的FUS和協(xié)議棧燒錄問(wèn)題這里必須再?gòu)?qiáng)調(diào)一遍STM32WB的燒錄順序不能亂。正確的流程是檢查FUS版本升級(jí)FUS燒無(wú)線協(xié)議棧固件最后燒用戶應(yīng)用代碼。特別是從官方例程環(huán)境克隆出來(lái)的新板子很多都是出廠固件狀態(tài)不一定帶最新的協(xié)議棧。用STM32CubeProgrammer燒協(xié)議棧時(shí)選擇“Firmware upgrade”模式后它會(huì)自動(dòng)識(shí)別協(xié)議棧文件的類型和目標(biāo)地址。這里不要自作聰明去改地址否則協(xié)議棧會(huì)寫到錯(cuò)誤的Flash區(qū)域M0核根本加載不了。燒完后可以在CubeProgrammer里檢查協(xié)議棧版本信息確保燒錄成功。如果燒錄中途斷電或者連接斷開(kāi)協(xié)議棧區(qū)域可能處于半寫狀態(tài)這時(shí)候重新燒一次通常就能恢復(fù)不必太慌張。最后再分享一點(diǎn)個(gè)人體會(huì)STM32無(wú)線MCU對(duì)Zigbee 3.0的支持補(bǔ)齊了STM32生態(tài)在Mesh類和低功耗傳感網(wǎng)絡(luò)上的短板。實(shí)際用下來(lái)我的感受是協(xié)議棧穩(wěn)定性比預(yù)想的好ST封裝出來(lái)的API也比某些第三方SDK干凈不少但學(xué)習(xí)曲線還是有的尤其是FUS燒錄、雙核通信、ZCL規(guī)范這些概念第一次接觸會(huì)覺(jué)得信息量很大。我的建議是別急著直接上手自己項(xiàng)目先把官方協(xié)調(diào)器路由器的On/Off例程跑通把入網(wǎng)流程和串口日志看清楚再去動(dòng)手改業(yè)務(wù)邏輯。一個(gè)能穩(wěn)定入網(wǎng)、能互相通信的最小閉環(huán)比什么都重要。等你把這個(gè)閉環(huán)跑通了后面無(wú)論是做智能臺(tái)燈、傳感器上報(bào)還是用485去控制伺服電機(jī)其實(shí)都在這個(gè)框架內(nèi)擴(kuò)展而已。