zigbee 串口不稳定_Zigbee
Zigbee 不完全整
基本概念:
計(jì)算機(jī)網(wǎng)絡(luò)定義:
? 1.用通信鏈路將分散的多臺(tái)計(jì)算機(jī)、終端、外設(shè)等互聯(lián)起來(lái),使之能彼此通信,同時(shí)共享各種硬件、軟件和數(shù)據(jù)資源,整個(gè)系統(tǒng)可稱(chēng)為計(jì)算機(jī)網(wǎng)絡(luò)
? 2.計(jì)算機(jī)網(wǎng)絡(luò)將地理位置不同的具獨(dú)立功能的多臺(tái)主機(jī)、外設(shè)或其它設(shè)備,通過(guò)通信線路進(jìn)行連接,在網(wǎng)絡(luò)操作系統(tǒng)、管理軟件及通信協(xié)議的管理協(xié)調(diào)下,實(shí)現(xiàn)資源共享和信息傳遞的完整系統(tǒng)。
計(jì)算機(jī)網(wǎng)絡(luò)的作用:資源共享、信息交換、協(xié)同處理。
計(jì)算機(jī)網(wǎng)絡(luò)在邏輯上可以分為通訊子網(wǎng)和資源子網(wǎng)。按網(wǎng)絡(luò)傳輸分配可以分為點(diǎn)對(duì)點(diǎn)分類(lèi)和廣播分類(lèi)。按網(wǎng)絡(luò)規(guī)模和覆蓋范圍可以分為局域網(wǎng)、城域網(wǎng)以及廣域網(wǎng)。計(jì)算機(jī)網(wǎng)絡(luò)的作用資源共享、信息交換、協(xié)同處理。
計(jì)算機(jī)網(wǎng)絡(luò)的四個(gè)產(chǎn)生階段:第一階段:分散的多個(gè)終端連接到一臺(tái)中心機(jī)上,典型:美國(guó)飛機(jī)訂票系統(tǒng);第二階段:多主機(jī)通過(guò)通信鏈路互聯(lián),典型:ARPANET;第三階段:互聯(lián)互通階段: 網(wǎng)絡(luò)互連遵循統(tǒng)一的技術(shù)標(biāo)準(zhǔn)(OSI模型和TCP/IP模型),成為第三代網(wǎng)絡(luò)。第四階段:高速網(wǎng)絡(luò)階段:光纖高速網(wǎng)絡(luò)、多媒體網(wǎng)絡(luò)、智能網(wǎng)絡(luò)、無(wú)線網(wǎng)絡(luò),成為第四代網(wǎng)絡(luò)。
網(wǎng)絡(luò)協(xié)議的三要素:語(yǔ)義、語(yǔ)法、定時(shí)。
三網(wǎng)融合:計(jì)算機(jī)網(wǎng)絡(luò)、電信網(wǎng)絡(luò)、廣播電視網(wǎng)絡(luò)。
ZigBee網(wǎng)絡(luò)協(xié)議架構(gòu)通過(guò)分層實(shí)現(xiàn),每一層相當(dāng)于一個(gè)模塊,且為上層提供服務(wù),層與層之間通過(guò)服務(wù)接入點(diǎn)接口進(jìn)行信息交換。
在網(wǎng)狀網(wǎng)絡(luò)中,每個(gè)設(shè)備都可以與在無(wú)線通信范圍內(nèi)的其他設(shè)備進(jìn)行通信。
CC2530是8位單片機(jī),具有兩個(gè)串口、21個(gè)通用I/O端口引腳(19個(gè)4mA、2個(gè)20mA)。芯片具有8KB、16KB、32KB在線可編程的FLASH、同時(shí)具有8KB的數(shù)據(jù)存儲(chǔ)能力(RAM)。具有低功耗模式、2.4GHz IEEE802.15.4兼容的RF收發(fā)器、支持精確鏈路指示、不具備多路DAC轉(zhuǎn)換器。8路輸入且可配置的12位ADC。從芯片CC2530的組成框圖看,三個(gè)模塊中組成CPU及相關(guān)存儲(chǔ)模塊、外設(shè)、時(shí)鐘和電源管理模塊和無(wú)線模塊。
單片機(jī)最小系統(tǒng)包括單片機(jī)、電源引腳、復(fù)位電路和晶振電路組成。
無(wú)線網(wǎng)絡(luò)發(fā)展幾個(gè)階段:
? 第一代(1G)無(wú)線系統(tǒng)是面向語(yǔ)音的模擬無(wú)線系統(tǒng),使用FDMA技術(shù)實(shí)現(xiàn)。 第二代(2G)無(wú)線系統(tǒng)是面向語(yǔ)音的數(shù)字無(wú)線系統(tǒng),使用TDMA或窄帶CDMA技術(shù)實(shí)現(xiàn)。第三代(3G)無(wú)線系統(tǒng)把蜂窩電話、PCS語(yǔ)音業(yè)務(wù)以及移動(dòng)數(shù)據(jù)業(yè)務(wù)用各種分組交換數(shù)據(jù)業(yè)務(wù)綜合在一個(gè)高語(yǔ)音質(zhì)量、高容量、高速率的網(wǎng)絡(luò)系統(tǒng)中。
Zigbee無(wú)線通信技術(shù)的特點(diǎn):Zigbee無(wú)線技術(shù)是一種新興的短距離、低復(fù)雜度、低功耗、低數(shù)據(jù)速率、低成本的技術(shù)。
Zigbee適合傳輸?shù)头磻?yīng)時(shí)間、周期性、間歇性的數(shù)據(jù),不適合傳輸高延遲的數(shù)據(jù)。
所有的ZigBee設(shè)備都具有連接網(wǎng)絡(luò)和斷開(kāi)網(wǎng)絡(luò)的功能。ZIgBee網(wǎng)絡(luò)是一種自組織網(wǎng)絡(luò)、分布式網(wǎng)絡(luò)。 「可能涉及Zigbee如何組網(wǎng)的過(guò)程」
依據(jù)IEEE802.15.4標(biāo)準(zhǔn)建立。可使用的頻段有三個(gè):2.4GHZ、歐洲868MHZ、美國(guó)915MHZ,不同頻段可用的信道分別是16、1、10個(gè)。短地址14位,長(zhǎng)地址64位。Zigbee最多可支持240個(gè)設(shè)備。非開(kāi)源意思是看不見(jiàn)源碼,只提供函數(shù)借口(API)
分層(key):從下到上:物理層 媒體訪問(wèn)控制層(MAC) 「IEEE802.15.4定義」 網(wǎng)絡(luò)層 應(yīng)用層「Zigbee聯(lián)盟定義」
對(duì)各層的基本功能了解:物理層:定義了無(wú)線信道和MAC子層之間的接口,提供了物理層數(shù)據(jù)服務(wù)和管理服務(wù)。「激活和關(guān)閉射頻收發(fā)器/對(duì)當(dāng)前信道進(jìn)行能量檢測(cè)/對(duì)收發(fā)的包進(jìn)行鏈路質(zhì)量指示/收發(fā)數(shù)據(jù)和空閑信道評(píng)估/信道選擇/數(shù)據(jù)單元收發(fā)/向MAC層提供管理服務(wù)接口」
MAC層:MAC層提供網(wǎng)絡(luò)層和物理層之間的接口。「實(shí)現(xiàn)對(duì)從基本物理層數(shù)據(jù)單元中提取MAC層數(shù)據(jù)包的進(jìn)一步處理,并發(fā)送信標(biāo),利用信標(biāo)與父節(jié)點(diǎn)同步,能量檢測(cè),主動(dòng)、被動(dòng)、孤立掃描機(jī)制,關(guān)聯(lián)和退出關(guān)聯(lián),CSMA/CA沖突避免信道訪問(wèn)控制機(jī)制,時(shí)隙劃分, MAC層數(shù)據(jù)傳輸及安全機(jī)制等功能。」
網(wǎng)絡(luò)層(核心層):利用IEEE 802.15.4標(biāo)準(zhǔn)使MAC子層正確工作,并為應(yīng)用層提供服務(wù)接口。「主要負(fù)責(zé)網(wǎng)絡(luò)層協(xié)議數(shù)據(jù)單元收發(fā)、網(wǎng)絡(luò)管理和路由管理。網(wǎng)絡(luò)管理主要包括網(wǎng)絡(luò)啟動(dòng)、設(shè)備請(qǐng)求加入/離開(kāi)網(wǎng)絡(luò)、網(wǎng)絡(luò)發(fā)現(xiàn)、網(wǎng)絡(luò)地址分配等。 路由管理包括鄰居節(jié)點(diǎn)發(fā)現(xiàn)、路由發(fā)現(xiàn)、路由維護(hù)、消息單播、多播、廣播實(shí)現(xiàn)等 」
應(yīng)用層:包括應(yīng)用支持子層(APS)、應(yīng)用框架(AF)、 ZigBee設(shè)備對(duì)象(ZDO)及ZDO管理平臺(tái)。應(yīng)用支持子層(APS),作為應(yīng)用層的一個(gè)組成部分,它提供了網(wǎng)絡(luò)層(NWK)和應(yīng)用層(APL)之間的接口。 「應(yīng)用支持子層負(fù)責(zé)應(yīng)用層協(xié)議數(shù)據(jù)單元數(shù)據(jù)的傳輸、設(shè)備綁定表創(chuàng)建和維護(hù)、組表的管理和維護(hù)、數(shù)據(jù)可靠傳輸?shù)取?yīng)用框架「AF層」主要為方便程序員進(jìn)行開(kāi)發(fā)而在ZigBee設(shè)備中為所實(shí)現(xiàn)的應(yīng)用對(duì)象提供的模板。應(yīng)用對(duì)象就是使用ZigBee聯(lián)盟制定的Profile進(jìn)行開(kāi)發(fā)的,并在協(xié)議棧上運(yùn)行的應(yīng)用程序。安全服務(wù)層安全服務(wù)向NWK層和APS提供了安全服務(wù),主要完成一些加密工作,包括密鑰建立、密鑰傳輸、幀保護(hù)和設(shè)備管理。』
設(shè)備分類(lèi):
? 全功能設(shè)備支持 IEEE802.15.4標(biāo)準(zhǔn)定義的所有功能和特性,并擁有較多的存儲(chǔ)資源、計(jì)算能力。半功能設(shè)備只支持標(biāo)準(zhǔn)定義的一部分,功能簡(jiǎn)單。
? ZigBee 網(wǎng)絡(luò)中的設(shè)備按照各自作用不同可以分為協(xié)調(diào)器節(jié)點(diǎn)、路由器節(jié)點(diǎn)和終端節(jié)點(diǎn)。全功能設(shè)備既可以作為協(xié)調(diào)器、路由器,也可以作為終端;半功能設(shè)備只能作為終端。
協(xié)調(diào)器(key):
? 負(fù)責(zé)網(wǎng)絡(luò)的啟動(dòng),配置網(wǎng)絡(luò)使用的信道和網(wǎng)絡(luò)標(biāo)識(shí)符(PAN ID),完成網(wǎng)絡(luò)成員的地址分配、節(jié)點(diǎn)綁定、建立安全層等任務(wù)。協(xié)調(diào)器是網(wǎng)絡(luò)的第一個(gè)設(shè)備,是整個(gè)網(wǎng)絡(luò)的中心。一個(gè)ZigBee網(wǎng)絡(luò)只有一個(gè)網(wǎng)絡(luò)協(xié)調(diào)器。當(dāng)網(wǎng)絡(luò)建立成功后,協(xié)調(diào)器便充當(dāng)路由器的角色。
路由器(key):
? 主要實(shí)現(xiàn)允許設(shè)備加入網(wǎng)絡(luò)、擴(kuò)展網(wǎng)絡(luò)覆蓋的物理范圍和數(shù)據(jù)包路由的功能。一般處于活躍狀態(tài),由主電源供電 「擴(kuò)展網(wǎng)絡(luò)是指該設(shè)備可以作為網(wǎng)絡(luò)中的潛在父節(jié)點(diǎn),允許更多的路由和終設(shè)備接入網(wǎng)絡(luò)。路由器最為重要的功能是“允許多跳路由”。路由節(jié)點(diǎn)存儲(chǔ)路由表、負(fù)責(zé)尋找、建立及修復(fù)數(shù)據(jù)包路由路徑。」
終端設(shè)備:
? 通過(guò)ZigBee協(xié)調(diào)器或者ZigBee路由器接入到網(wǎng)絡(luò)中,主要負(fù)責(zé)數(shù)據(jù)采集或控制功能,不允許其他節(jié)點(diǎn)通過(guò)它加入到網(wǎng)絡(luò)中。多數(shù)時(shí)間處于休眠狀態(tài),電池供電。
組網(wǎng)過(guò)程:
? 組建網(wǎng)絡(luò):節(jié)點(diǎn)上電,判斷是否是全功能設(shè)備->判斷是否已經(jīng)加入到其他網(wǎng)絡(luò)->信道掃描,選擇合適的信道->設(shè)置PAN-ID和協(xié)調(diào)器短地址,網(wǎng)絡(luò)初始化成功,等待其他節(jié)點(diǎn)加入網(wǎng)絡(luò)。
? 節(jié)點(diǎn)加入網(wǎng)絡(luò):通過(guò)全功能節(jié)點(diǎn)加入網(wǎng)絡(luò)。分為首次加入網(wǎng)絡(luò)和再次入網(wǎng),再次入網(wǎng)采用孤兒掃描。
網(wǎng)狀/樹(shù)形/星形網(wǎng)絡(luò)三者比較:自行擴(kuò)展。
Zigbee相關(guān)技術(shù):
節(jié)點(diǎn):一個(gè)節(jié)點(diǎn)包含一組設(shè)備,并對(duì)應(yīng)一個(gè)無(wú)線信號(hào)收發(fā)器,只能使用一個(gè)無(wú)線通信信道。「一個(gè)節(jié)點(diǎn)對(duì)應(yīng)一個(gè)設(shè)備」
端點(diǎn):應(yīng)用對(duì)象駐留的地方,是協(xié)議棧應(yīng)用層的入口,為實(shí)現(xiàn)一個(gè)設(shè)備描述而定義的一組群集。一個(gè)設(shè)備最多支持240個(gè)用戶(hù)自定義端點(diǎn)。「0分配給ZDO,用與設(shè)備管理,255用于廣播,241-254保留擴(kuò)展」
群集(Cluster):一個(gè)端點(diǎn)可以具有多個(gè)群集,使用群集號(hào)(Cluster ID)分配。分為輸入群集和輸出群集,多個(gè)節(jié)點(diǎn)通過(guò)群集號(hào)位不同端點(diǎn)建立一個(gè)邏輯連接,即綁定(Bonding)「群集是屬性的集合,包含一個(gè)或多個(gè)屬性」簇的含義指設(shè)備或應(yīng)用對(duì)象之間的消息。
規(guī)約(Profile):相同應(yīng)用對(duì)象采用的所有群集的集合稱(chēng)為規(guī)約。目的是為了制定標(biāo)準(zhǔn),兼容不同制造商之間的產(chǎn)品,說(shuō)明了設(shè)備類(lèi)型、接口等。還有一種協(xié)議棧規(guī)約(Zigbee和Zigbee Pro),定義網(wǎng)絡(luò)類(lèi)型、網(wǎng)絡(luò)深度等。
節(jié)點(diǎn)地址:
? 擴(kuò)展地址:IEEE地址,64位,設(shè)備商固化在設(shè)備中。短地址:稱(chēng)為網(wǎng)絡(luò)地址,由協(xié)調(diào)器進(jìn)行分配,通過(guò)端點(diǎn)號(hào)+短地址確定一個(gè)終端。
PANID:網(wǎng)絡(luò)標(biāo)號(hào)。不同PANID代表不同網(wǎng)絡(luò)。PANID16位,PANID為0xFFFF時(shí),協(xié)調(diào)器隨機(jī)選擇一個(gè)PANID作為網(wǎng)絡(luò)標(biāo)號(hào)建立網(wǎng)絡(luò),終端隨機(jī)選擇一個(gè)信號(hào)最強(qiáng)的網(wǎng)絡(luò)加入網(wǎng)絡(luò)。
事件:系統(tǒng)定義事件和用戶(hù)定義事件,16位獨(dú)熱碼。
間接通信/直接通信:間接通信指各個(gè)節(jié)點(diǎn)通關(guān)端點(diǎn)的綁定建立通信關(guān)系。直接通信需要獲取對(duì)方的地址。
綁定:一種多個(gè)應(yīng)用設(shè)備之間信息流的控制機(jī)制。
數(shù)據(jù)傳送方式:單點(diǎn)傳送(Unicast):將素舉報(bào)發(fā)送給一個(gè)已知網(wǎng)絡(luò)地址的設(shè)備。廣播傳送(Indirect):應(yīng)用程序需要將數(shù)據(jù)包發(fā)送給網(wǎng)絡(luò)的每一個(gè)設(shè)備,廣播傳送的目標(biāo)地址:0xFFFF--傳送到網(wǎng)絡(luò)上的所有設(shè)備。0xFFFC--只發(fā)送給協(xié)調(diào)器和路由器, 0xFFFD--數(shù)據(jù)包傳送到網(wǎng)絡(luò)上所有非睡眠設(shè)備。
LQI;鏈路信號(hào)質(zhì)量。最差0x00-最強(qiáng)0xff
RSSI信號(hào)強(qiáng)度,越小越好。
Zigbee協(xié)議棧任何數(shù)據(jù)利用幀格式來(lái)組織,每層都有特定的幀結(jié)構(gòu)。(分為鍵值對(duì)和報(bào)文,報(bào)文適合傳遞數(shù)據(jù)量大的消息,支持任何數(shù)據(jù)傳輸)
Zigbee具有兩種休眠模式:輕度休眠「定時(shí)器休眠」和深度休眠。
應(yīng)用框架(AF)主要為方便程序員進(jìn)行開(kāi)發(fā)而在ZigBee設(shè)備中為所實(shí)現(xiàn)的應(yīng)用對(duì)象提供的模板,由設(shè)備對(duì)應(yīng)的( 端口號(hào)和短地址)兩部分組成。 ZigBee協(xié)議棧的系統(tǒng)輕度休眠模式時(shí)一個(gè)預(yù)定延時(shí)后不能喚醒執(zhí)行任務(wù)。(F) ZigBee協(xié)議棧的系統(tǒng)進(jìn)入深度休眠模式,需要一個(gè)外部觸發(fā)來(lái)喚醒設(shè)備。 ZigBee協(xié)議棧的端點(diǎn),包括任務(wù)號(hào)、端點(diǎn)號(hào)、簡(jiǎn)單描述符、潛藏周期四項(xiàng)。 ZigBee協(xié)議棧中定義的設(shè)備狀態(tài)類(lèi)型devStates_t中,不包含終端節(jié)點(diǎn)狀態(tài)。(F) ZigBee協(xié)議棧的兩種休眠模式:真休眠(定時(shí)器休眠)和假休眠。(F) 在ZigBee協(xié)議中如果一個(gè)消息來(lái)到了節(jié)點(diǎn)上,是通過(guò)( 終端「不是端點(diǎn))來(lái)投遞消息到某一個(gè)具體的應(yīng)用程序?qū)ο?不同的ZigBee協(xié)議棧版本使用不同的地址分配方案,ZigBee 2007使用(隨機(jī)分配地址的方案) 在ZigBee協(xié)議中,(全功能節(jié)點(diǎn))能夠承擔(dān)協(xié)調(diào)器和路由器的功能。 在ZigBee協(xié)議中,(應(yīng)用程序?qū)ο?#xff09;是指針對(duì)目標(biāo)物理量或事件都會(huì)提供控制或測(cè)量功能,實(shí)際的通信實(shí)體 ? 在ZigBee協(xié)議中,事件分為系統(tǒng)級(jí)事件和任務(wù)級(jí)事件,系統(tǒng)級(jí)事件可以(在任務(wù)間傳遞的事件),任務(wù)級(jí)事件在任務(wù)內(nèi)使用的事件。 ZigBee協(xié)議建立路由的原則是(按照需要建立路由),既有優(yōu)點(diǎn)也有缺點(diǎn),優(yōu)點(diǎn)是節(jié)省資源,缺點(diǎn)是實(shí)時(shí)性不好。 在Zigbee中,OSAL指的是操作系統(tǒng)抽象層。 使用ZigBee協(xié)議棧編程,每個(gè)任務(wù)有一個(gè)任務(wù)號(hào),有一個(gè)初始化函數(shù)和一個(gè)事件處理函數(shù),(端口)提供的其他函數(shù)都會(huì)被這兩個(gè)函數(shù)直接或間接地調(diào)用到。 使用ZigBee協(xié)議棧編程,(簇)僅提供一個(gè)消息隊(duì)列及消息處理的功能。 函數(shù)osalInitTasks( void )初始化了事件隊(duì)列。ZigBee協(xié)議中,端點(diǎn)描述符結(jié)構(gòu)體endPointDesc_t的成員變量有端點(diǎn)號(hào)endPoint、簡(jiǎn)單描述符SimpleDescriptionFormat_t、網(wǎng)絡(luò)發(fā)送速度afNetworkLatencyReq_t和(指向任務(wù)ID即Task_ID的指針) 當(dāng)PAN_ID設(shè)置為0x1234時(shí),協(xié)調(diào)器(使用0x1234作為網(wǎng)絡(luò)標(biāo)號(hào),建立網(wǎng)絡(luò))路由器和終端(路由器和終端節(jié)點(diǎn)只能加入網(wǎng)絡(luò)標(biāo)號(hào)為0x1234的網(wǎng)絡(luò)) 鏈接器控制文件所在的文件夾(Tools) !從代碼角度看,一個(gè)任務(wù)是由一個(gè)(初始化函數(shù))和一個(gè)事件處理函數(shù)組成的。 任務(wù)ID,又叫任務(wù)號(hào),每個(gè)任務(wù)都有自己的消息隊(duì)列,任務(wù)號(hào)的作用是(事件發(fā)生時(shí),使用該任務(wù)號(hào)獲取消息)C++跨平臺(tái)調(diào)用
一般用于將C++代碼以標(biāo)準(zhǔn)C形式輸出(即以C的形式被調(diào)用),這是因?yàn)镃++雖然常被認(rèn)為是C的超集,但是C++的編譯器還是與C的編譯器不同的。C中調(diào)用C++中的代碼這樣定義會(huì)是安全的。 #ifdefined(__cplusplus)||defined(c_plusplus) //跨平臺(tái)定義方法extern "C"{#endif簡(jiǎn)單的用在windows下可以如下定義:#ifdef __cplusplusextern "C"{//... 正常的聲明段}#endif協(xié)議棧
APP:應(yīng)用層目錄,這是用戶(hù)創(chuàng)建各種不同工程的區(qū)域,在這個(gè)目錄中包含了應(yīng)用層的內(nèi)容和這個(gè)項(xiàng)目的主要內(nèi)容,在協(xié)議棧里面一般是以操作系統(tǒng)的任務(wù)實(shí)現(xiàn)的。HAL:硬件層目錄,包含有與硬件相關(guān)的配置和驅(qū)動(dòng)及操作函數(shù)。
MAC:MAC 層目錄,包含了MAC 層的參數(shù)配置文件及其MAC 的LIB 庫(kù)的函數(shù)接口文件。
MT: 監(jiān)控調(diào)試層,主要用于調(diào)試目的,即實(shí)現(xiàn)通過(guò)串口調(diào)試各層,與各層進(jìn)行直接交互。
NWK:網(wǎng)絡(luò)層目錄,含網(wǎng)絡(luò)層配置參數(shù)文件及網(wǎng)絡(luò)層庫(kù)的函數(shù)接口文件,APS 層庫(kù)的函數(shù)接口。
OSAL:協(xié)議棧的操作系統(tǒng)。
Profile:AF 層目錄,包含AF 層處理函數(shù)文件。
Security:安全層目錄,安全層處理函數(shù)接口文件,比如加密函數(shù)等。
Services:地址處理函數(shù)目錄,包括著地址模式的定義及地址處理函數(shù)。
Tools:工程配置目錄,包括空間劃分及ZStack 相關(guān)配置信息。
ZDO:ZDO 目錄。
ZMac: MAC 層目錄,包括MAC 層參數(shù)配置及MAC 層LIB 庫(kù)函數(shù)回調(diào)處理函數(shù)。
ZMain:主函數(shù)目錄,包括入口函數(shù)main()及硬件配置文件。
Output:輸出文件目錄,這個(gè)自動(dòng)生成的。
ZMain函數(shù)中,一方面進(jìn)行系統(tǒng)的初始化,一方面對(duì)事件進(jìn)行輪循。
Zstack的工作原理圖
Zstack運(yùn)行流程圖如上。綜上,Zstack最重要的兩個(gè)步驟即事件的初始化以及事件的處理,其余各層的初始化Ti公司基本已經(jīng)為你做完了。
用戶(hù)自定義事件初始化:
Main -> oasl_init_system()
OSAL工作機(jī)制
OSAL任務(wù)初始化
oaslInitTask()函數(shù)中對(duì)任務(wù)進(jìn)行初始化,在此創(chuàng)建任務(wù)表。
void osalInitTasks( void ) {uint8 taskID = 0;tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));macTaskInit( taskID++ );nwk_init( taskID++ );Hal_Init( taskID++ ); #if defined( MT_TASK )MT_TaskInit( taskID++ ); #endifAPS_Init( taskID++ ); #if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ ); #endifZDApp_Init( taskID++ ); #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )//ip沖突和跳頻相關(guān)ZDNwkMgr_Init( taskID++ ); #endif//task_init functionDNUI_SampleApp_Init(taskID); } //任務(wù)初始化函數(shù)如上,更具taskCnt的數(shù)量申請(qǐng)對(duì)應(yīng)的事件表,兩者通過(guò)taskID一一對(duì)應(yīng),然后對(duì)各層定義進(jìn)行初始化,taskID越小,其優(yōu)先級(jí)越高。這個(gè)函數(shù)可用于自定義相關(guān)的任務(wù)。例:DNUI_SampleApp_Init(),對(duì)應(yīng)用戶(hù)自定義的初始化函數(shù),用戶(hù)需要用到的相關(guān)初始化都在其內(nèi)定義。OSAL通過(guò)輪詢(xún)查看任務(wù)表判斷各層有無(wú)事件發(fā)生。OSAL如何處理事件
//操作系統(tǒng)啟動(dòng)函數(shù) void osal_start_system( void ) { #if !defined ( ZBIT ) && !defined ( UBIT )for(;;) // Forever Loop #endif{osal_run_system();} } //可見(jiàn)操作系統(tǒng)通過(guò)for無(wú)限循環(huán)osal_run_system()進(jìn)入oasl_run_system( )一探究竟
//操作系統(tǒng)運(yùn)行函數(shù) void osal_run_system( void ) {uint8 idx = 0; //掃描哪個(gè)時(shí)間被觸發(fā),標(biāo)志位置一//更新定時(shí)器osalTimeUpdate();//查看硬件方法是否有事件發(fā)生Hal_ProcessPoll();//硬件初始化輪詢(xún)調(diào)用//從最高優(yōu)先級(jí)任務(wù)一次判斷每個(gè)任務(wù)是否有事件的觸發(fā),有則跳出循環(huán)do {if (tasksEvents[idx]) // Task is highest priority that is ready.{break;}} while (++idx < tasksCnt);//idx小于任務(wù)數(shù)量,即有時(shí)間發(fā)生//so hard to understandif (idx < tasksCnt){uint16 events;halIntState_t intState;HAL_ENTER_CRITICAL_SECTION(intState);//關(guān)中斷,防止干擾events = tasksEvents[idx];//調(diào)用事件去處理函數(shù),coz taskArr是一個(gè)函數(shù)指針,tasksEvents[idx] = 0; // Clear the Events for this task。表示此類(lèi)任務(wù)事件//執(zhí)行finsih,在事件處理函數(shù)中又調(diào)用消息處理函數(shù)HAL_EXIT_CRITICAL_SECTION(intState);activeTaskID = idx;//設(shè)置activeTaskID的作用?events = (tasksArr[idx])( idx, events );//核心中的核心,taskArr和tasksEvent中的idx相同,返回處理過(guò)事件的eventsactiveTaskID = TASK_NO_TASK;HAL_ENTER_CRITICAL_SECTION(intState);tasksEvents[idx] |= events; // Add back unprocessed events to the current task./將處理過(guò)的events對(duì)應(yīng)的tasksEvents位清0HAL_EXIT_CRITICAL_SECTION(intState);}//定義低功耗,則進(jìn)入低功耗模式 #if defined( POWER_SAVING )else // Complete pass through all task events with no activity?{osal_pwrmgr_powerconserve(); // Put the processor/system into sleep} #endif //定義協(xié)同操作,進(jìn)入?yún)f(xié)同操作/* Yield in case cooperative scheduling is being used. */ #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0){osal_task_yield();} #endif } //函數(shù)設(shè)計(jì)非常巧妙,首先調(diào)用定時(shí)器和硬件初始化輪詢(xún)函數(shù)。 //通過(guò)do...while...循環(huán),對(duì)事件進(jìn)行查看,一旦有事件發(fā)生便跳出循環(huán),進(jìn)行事件處理,把事件存入event中并調(diào)用taskArr[idx](idx,events)進(jìn)行對(duì)應(yīng)事件的函數(shù)處理Hal_ProcessPoll( );poll在linux中相當(dāng)于把文件掛起,此函數(shù)可能有這個(gè)意思;進(jìn)入事件處理函數(shù)TaskArr[].
taskArr是一個(gè)存放各事件處理函數(shù)的指針數(shù)組。存放對(duì)應(yīng)taskid上產(chǎn)生事件的事件處理函數(shù)。const pTaskEventHandlerFn tasksArr[] = {macEventLoop,nwk_event_loop,Hal_ProcessEvent, #if defined( MT_TASK )MT_ProcessEvent, #endifAPS_event_loop, #if defined ( ZIGBEE_FRAGMENTATION )APSF_ProcessEvent, #endifZDApp_event_loop, #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_event_loop, #endifDNUI_SampleApp_ProcessEvent }; //以上定義了各層task的事件處理函數(shù)。其中最后的DNUI_SampleApp_ProcessEvent;調(diào)用的是用戶(hù)自定義的事件處理函數(shù)。用戶(hù)對(duì)于系統(tǒng)或各自定義事件產(chǎn)生的動(dòng)作都在此定義 uint16 DNUI_SampleApp_ProcessEvent( uint8 task_id, uint16 events ) {afIncomingMSGPacket_t *MSGpkt; //定義一個(gè)接受消息的指針if ( events & SYS_EVENT_MSG ){MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id );//將對(duì)應(yīng)taskid上的消息隊(duì)列中的消息取出進(jìn)行處理while ( MSGpkt )//有事件接受{switch ( MSGpkt->hdr.event )//根據(jù)消息頭判斷,如果接收到了無(wú)線數(shù)據(jù){//無(wú)線接受消息,A設(shè)備用AF_DataRequest()發(fā)送消息,b設(shè)備街道消息觸發(fā)此事件case AF_INCOMING_MSG_CMD: //incoming msg type megsif(DNUI_SampleApp_NwkState == DEV_ZB_COORD)//若為協(xié)調(diào)器事件{//--start--協(xié)調(diào)器接收數(shù)據(jù)的處理邏輯 HalUARTWrite(0,MSGpkt->cmd.Data,MSGpkt->cmd.DataLength-1); //--end--協(xié)調(diào)器接收數(shù)據(jù)的處理邏輯 }else if(DNUI_SampleApp_NwkState == DEV_END_DEVICE){//--start--終端設(shè)備接收數(shù)據(jù)的處理邏輯 //--end--終端設(shè)備接收數(shù)據(jù)的處理邏輯 }else if(DNUI_SampleApp_NwkState == DEV_ROUTER){//--start--路由器接收數(shù)據(jù)的處理邏輯 //--end--路由器接收數(shù)據(jù)的處理邏輯 }break; //網(wǎng)絡(luò)狀態(tài)改變case ZDO_STATE_CHANGE: //ZDO has changed the device's network state DNUI_SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);//statusif(DNUI_SampleApp_NwkState == DEV_END_DEVICE){ //--start--終端設(shè)備接收數(shù)據(jù)的處理邏輯 osal_start_timerEx(task_id,DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT,1000); //--end--終端設(shè)備接收數(shù)據(jù)的處理邏輯 } else if(DNUI_SampleApp_NwkState == DEV_ZB_COORD){//--start--協(xié)調(diào)器接收數(shù)據(jù)的處理邏輯 //--end--協(xié)調(diào)器接收數(shù)據(jù)的處理邏輯 }else if(DNUI_SampleApp_NwkState == DEV_ROUTER){//--start--路由器接收數(shù)據(jù)的處理邏輯 //--end--路由器接收數(shù)據(jù)的處理邏輯 } break;default:break;} //消息處理完后,釋放消息所占據(jù)的內(nèi)存空間,在zigbee中接收到的消息放在堆上,//需要用deallocate函數(shù)將其內(nèi)存釋放,否則容易導(dǎo)致內(nèi)存泄露osal_msg_deallocate( (uint8 *)MSGpkt ); //WHY DNUI_sampleAppTaskIDMSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( DNUI_SampleAppTaskID);} return (events ^ SYS_EVENT_MSG);//SYS_EVENT_MSG =0X8000,系統(tǒng)事件//按理解當(dāng)事件處理完畢后將事件對(duì)應(yīng)位清0,解封裝的過(guò)程,有事件的時(shí)候就將對(duì)應(yīng)出置1} //若產(chǎn)生用戶(hù)自定義事件,在此處理if ( events & DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT ) //0x01{ //發(fā)送設(shè)置,數(shù)據(jù)發(fā)送可以使用AF_DataRequest函數(shù)實(shí)現(xiàn),該函數(shù)調(diào)用協(xié)議棧里與硬件相關(guān)的函數(shù)AF_DataRequest( &Coor_Addr, &DNUI_SampleApp_epDesc,DNUI_SAMPLEAPP_DATATEST_CLUSTER_ID,3, //Lab6buf,&DNUI_SampleApp_TransID,//任務(wù)id號(hào)指針AF_DISCV_ROUTE,//有效位掩碼發(fā)送選項(xiàng)AF_DEFAULT_RADIUS );osal_start_timerEx( task_id, DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT,1000); return (events ^ DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT);} return 0; }通過(guò)Osal_set_event(taskid , flag)函數(shù)將相應(yīng)的標(biāo)志位置1,在之后的協(xié)議棧運(yùn)行過(guò)程中就會(huì)根據(jù)需要調(diào)用這個(gè)函數(shù)。此函數(shù)為Osal的核心函數(shù),包含很多重要的結(jié)構(gòu)和函數(shù)。
afIncomingMSGPacket_t *MSGpkt
一個(gè)消息包的結(jié)構(gòu)內(nèi)容typedef struct {osal_event_hdr_t hdr; /* OSAL Message header */uint16 groupId; /* Message's group ID - 0 if not set */uint16 clusterId; /* Message's cluster ID */afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,it's an InterPAN message */uint16 macDestAddr; /* MAC header destination short address */uint8 endPoint; /* destination endpoint */uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */uint8 LinkQuality; /* The link quality of the received data frame */uint8 correlation; /* The raw correlation value of the received data frame */int8 rssi; /* The received RF power in units dBm */uint8 SecurityUse; /* deprecated */uint32 timestamp; /* receipt timestamp from MAC */uint8 nwkSeqNum; /* network header frame sequence number */afMSGCommandFormat_t cmd; /* Application Data */ } afIncomingMSGPacket_t; ---------------------------------------------------------------------- typedef struct {uint8 event;uint8 status; } osal_event_hdr_t;typedef struct {union{uint16 shortAddr;ZLongAddr_t extAddr;} addr;afAddrMode_t addrMode;uint8 endPoint;uint16 panId; // used for the INTER_PAN feature } afAddrType_t;// Generalized MSG Command Format typedef struct {uint8 TransSeqNumber;uint16 DataLength; // Number of bytes in TransDatauint8 *Data; } afMSGCommandFormat_t;AF_DataRequest()
afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,uint16 cID, uint16 len, uint8 *buf, uint8 *transID,uint8 options, uint8 radius ) { }//很重要的一個(gè)APi函數(shù),處理過(guò)程過(guò)于復(fù)雜,只展示參數(shù)。返回值adStatus_t = uint8*dstAddr - Full ZB destination address: Nwk Addr + End Point.全終端節(jié)點(diǎn),網(wǎng)絡(luò)號(hào)和終端號(hào)
*srcEP - Origination (i.e. respond to or ack to) End Point Descr.
//終端節(jié)點(diǎn)的描述符
cID - A valid cluster ID as specified by the Profile.
//有效簇ID
len - Number of bytes of data pointed to by next param.
//發(fā)送數(shù)據(jù)的長(zhǎng)度
*buf - A pointer to the data bytes to send.
//指向發(fā)送數(shù)據(jù)的指針
*transID - A pointer to a byte which can be modified and which will be used as the transaction sequence number of the msg.
options - Valid bit mask of Tx options.
radius - Normally set to AF_DEFAULT_RADIUS.
//跳數(shù),一般為10跳
*transID - Incremented by one if the return value is success.
afStatus_t - See previous definition of afStatus_... types.
關(guān)于osal_msg_receive( )函數(shù)用于從消息隊(duì)列中取出函數(shù)
uint8 *osal_msg_receive( uint8 task_id ) {osal_msg_hdr_t *listHdr;osal_msg_hdr_t *prevHdr = NULL;osal_msg_hdr_t *foundHdr = NULL;halIntState_t intState; //unsigned char// Hold off interruptsHAL_ENTER_CRITICAL_SECTION(intState);// Point to the top of the queuelistHdr = osal_qHead;// Look through the queue for a message that belongs to the asking taskwhile ( listHdr != NULL ){if ( (listHdr - 1)->dest_id == task_id ){if ( foundHdr == NULL ){// Save the first onefoundHdr = listHdr;}else{// Second msg found, stop lookingbreak;}}if ( foundHdr == NULL ){prevHdr = listHdr;}listHdr = OSAL_MSG_NEXT( listHdr );}// Is there more than one?if ( listHdr != NULL ){// Yes, Signal the task that a message is waitingosal_set_event( task_id, SYS_EVENT_MSG );}else{// No moreosal_clear_event( task_id, SYS_EVENT_MSG );}// Did we find a message?if ( foundHdr != NULL ){// Take out of the link listosal_msg_extract( &osal_qHead, foundHdr, prevHdr );}// Release interruptsHAL_EXIT_CRITICAL_SECTION(intState);return ( (uint8*) foundHdr ); }typedef struct {void *next;uint16 len;uint8 dest_id; } osal_msg_hdr_t;typedef struct {uint8 event;uint8 status; } osal_event_hdr_t;由于系統(tǒng)檢測(cè)到相關(guān)事件觸發(fā)此函數(shù),如果觸發(fā)了系統(tǒng)事件,需要通過(guò)oasl_msg_receive()確認(rèn)是否真有事件發(fā)生,如果不止一個(gè)系統(tǒng)事件,通過(guò)setevent函數(shù)進(jìn)行再次設(shè)置。
關(guān)于 osal_start_timerEx()函數(shù),設(shè)置該taskid對(duì)應(yīng)時(shí)間的定時(shí),沒(méi)到一個(gè)定時(shí)時(shí)長(zhǎng)觸發(fā)一次任務(wù)事件。(但是這個(gè)觸發(fā)設(shè)置在哪并沒(méi)有找到對(duì)應(yīng)的函數(shù)。
uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value ) {halIntState_t intState; //unsigned char typeosalTimerRec_t *newTimer;//HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.// Add timernewTimer = osalAddTimer( taskID, event_id, timeout_value );HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL ); }事件的管理
事件管理
事件管理詳見(jiàn)【OSAL如何處理事件】
幾個(gè)系統(tǒng)事件
SYS_EVENT_MSG(0x8000),為系統(tǒng)強(qiáng)制事件,該事件主要用來(lái)發(fā)送全局的系統(tǒng)信息,主要有以下信息:
事件處理首先根據(jù)事件類(lèi)號(hào)判斷是何種事件,根據(jù)任務(wù)號(hào)得到消息指針pMSG,最后更具消息指針內(nèi)的結(jié)構(gòu)pMSG->event 來(lái)處理具體的事件。在ZcomDef.h中定義。AF_DATA_CONFIRM_CMD:數(shù)據(jù)收到確認(rèn)。A設(shè)備發(fā)送數(shù)據(jù),B設(shè)備收到數(shù)據(jù)后返回應(yīng)答Ack觸發(fā)此次事件。AF_INCOMING_MSG_CMD:Incoming MSG type message收到報(bào)文類(lèi)型的消息;A設(shè)備用AF_DataRequest函數(shù)發(fā)出報(bào)文消息,B設(shè)備收到報(bào)文消息將觸發(fā)AF_INCOMING_MSG_CMD事件。
AF_INCOMING_KWP_CMD:收到鍵值對(duì)類(lèi)型的消息。
AF_INCOMING_GRP_KVP_CMD:收到群鍵值對(duì)類(lèi)型的消息KEY_CHANGE:按鍵觸發(fā)事件「Key Events」
ZDO_NEW_DSTADDR:ZDO設(shè)備獲取新地址ZDO_STATE_CHANGE:ZDO網(wǎng)絡(luò)狀態(tài)改變,A設(shè)備的網(wǎng)絡(luò)狀態(tài)發(fā)生改變,就會(huì)觸發(fā)這個(gè)事件
ZDO_MATCH_DESC_RSP_SENT:
ZDO_CB_MSG:收到ZDO反饋消息。
關(guān)于無(wú)線節(jié)點(diǎn)和端點(diǎn)的解釋
一個(gè)節(jié)點(diǎn)可以有多個(gè)端點(diǎn),每個(gè)端點(diǎn)對(duì)應(yīng)一個(gè)taskid ,每增加一個(gè)端點(diǎn),需要為其配置一個(gè)新的任務(wù)id。在zstack協(xié)議棧中,我們采用AF_DataRequest這個(gè)函數(shù)進(jìn)行無(wú)線數(shù)據(jù)包發(fā)送,在AF_DataRequest函數(shù)的參數(shù)中,SampleApp_Periodic_DstAddr目的地址,目的地址中便包含了16位的短地址(協(xié)調(diào)器默認(rèn)為0x0000)以及端點(diǎn)號(hào)endpoint。終端將數(shù)據(jù)包發(fā)出,短地址匹配的協(xié)調(diào)器會(huì)收到這個(gè)消息(短地址匹配不對(duì)則丟棄該包),然后協(xié)議棧底層進(jìn)行解析,將數(shù)據(jù)包發(fā)給協(xié)調(diào)器的對(duì)應(yīng)endpoint(不匹配則丟棄該包)。
簡(jiǎn)單來(lái)說(shuō),endpoint是用來(lái)管理同一個(gè)節(jié)點(diǎn)上不同任務(wù)的工具,相當(dāng)于一個(gè)分類(lèi)箱,將不同功能分別存放在不同任務(wù)上,這樣做的好處是規(guī)范數(shù)據(jù)包,你不用去規(guī)定第幾個(gè)字節(jié)是屬于哪個(gè)模塊信息。
端點(diǎn)的管理:
每個(gè)節(jié)點(diǎn)都有物理地址(MAC)和網(wǎng)絡(luò)地址(短地址),每個(gè)節(jié)點(diǎn)都有241個(gè)端點(diǎn),如果設(shè)備需要綁定,必須在網(wǎng)絡(luò)層注冊(cè)一個(gè)或多個(gè)端點(diǎn),進(jìn)行數(shù)據(jù)的發(fā)送以及綁定表的建立。1、Zigbee節(jié)點(diǎn)(Radio unit) Zigbee本身其實(shí)只是一種協(xié)議規(guī)范,落實(shí)到具體目標(biāo)上無(wú)非就是一個(gè)具有2.4G射頻發(fā)射接收功能和單片機(jī)功能的一塊電路板(TI的2530、2430,意法半導(dǎo)體的STM32W108處理器都在一塊芯片上集成了這兩個(gè)部分,Ember和飛思卡爾也有集成的,也有一些非集成的方案),在這塊電路板上去運(yùn)行Zigbee的協(xié)議,并且按照協(xié)議規(guī)范的射頻頻段和無(wú)線數(shù)據(jù)封包格式來(lái)在多個(gè)這樣的電路板之間實(shí)現(xiàn)無(wú)線通信。這就引出了節(jié)點(diǎn)的概念(英文大致叫做Device,我這里稱(chēng)之為Radio unit吧),理解起來(lái)就是這塊能夠?qū)崿F(xiàn)無(wú)線通信的電路了。如果不是zigbee,而是之前的那些諸如nrf905這樣的射頻芯片,如果其沒(méi)有協(xié)議棧支持,這個(gè)節(jié)點(diǎn)就是通信的全部了。 2、zigbee的EndPoint Endpoint這個(gè)概念在Zigbee中絕對(duì)是非常重要的。因?yàn)樗械腪igbee無(wú)線數(shù)據(jù)包都必須有一個(gè)Endpoint為目標(biāo)。那么什么是Endpoint呢?從理解的層面上來(lái)說(shuō),Endpoint是一個(gè)radio unit上的真正的數(shù)據(jù)目標(biāo)。按照協(xié)議規(guī)范,0號(hào)endpoint是Zigbee device object(ZDO)用的一個(gè)端點(diǎn),255號(hào)是用作廣播用途,我們可以自己設(shè)定的是1~240號(hào),其余的保留。在一個(gè)Radio unit上可以實(shí)現(xiàn)多個(gè)EndPoint。當(dāng)進(jìn)行無(wú)線數(shù)據(jù)收發(fā)的時(shí)候,數(shù)據(jù)包里面就必須包含radio unit信息(設(shè)備的短地址),端點(diǎn)信息(destination endpoint number)。也就是說(shuō)一個(gè)radio unit在接收到一個(gè)數(shù)據(jù)包后,會(huì)在協(xié)議棧的底層進(jìn)行解析,比對(duì)應(yīng)該把這個(gè)數(shù)據(jù)包發(fā)給哪個(gè)endpoint,如果找不到,這個(gè)包將被丟棄。
短地址+端點(diǎn)號(hào)=確定一個(gè)終端節(jié)點(diǎn)
3、例子 下面我舉兩個(gè)例子來(lái)解釋一下endpoint的問(wèn)題 例子一:一個(gè)無(wú)線節(jié)點(diǎn)(radio unit)A上有一個(gè)溫濕度傳感器,有一個(gè)空調(diào)控制系統(tǒng);另外一個(gè)無(wú)線節(jié)點(diǎn)B則負(fù)責(zé)接收A發(fā)回的溫度數(shù)據(jù),并通過(guò)一定的算法來(lái)控制空調(diào)系統(tǒng)。我們不管B如何實(shí)現(xiàn),只研究A如何實(shí)現(xiàn)。這種情況的一個(gè)很規(guī)范的實(shí)現(xiàn)方式是:溫濕度傳感器設(shè)置一個(gè)endpoint,比如為10號(hào);空調(diào)控制系統(tǒng)設(shè)置一個(gè)endpoint,比如為20號(hào)。還要說(shuō)明的是:還應(yīng)該為每一個(gè)endpoint建立一個(gè)任務(wù),這樣在注冊(cè)端點(diǎn)描述符的時(shí)候(調(diào)用afRegister函數(shù)),就會(huì)向協(xié)議棧底層說(shuō)明處理這個(gè)端點(diǎn)數(shù)據(jù)的任務(wù)是誰(shuí)。這樣:當(dāng)B想要獲取溫濕度的時(shí)候,他將會(huì)發(fā)出一個(gè)包含A的短地址和10號(hào)端點(diǎn)的信息,這個(gè)信息到了A,協(xié)議棧會(huì)將這個(gè)消息轉(zhuǎn)給10號(hào)端點(diǎn)所對(duì)應(yīng)的task去處理,管理空調(diào)的20號(hào)端點(diǎn)根本就看不到這個(gè)消息;類(lèi)似地,如果B想要控制空調(diào),他發(fā)出的數(shù)據(jù)包將包含A的短地址和20號(hào)端點(diǎn)信息,A收到消息后會(huì)發(fā)給20號(hào)端點(diǎn)的task去處理。(需要注意的是:在網(wǎng)絡(luò)層面經(jīng)常會(huì)有發(fā)給ZDO的消息,這時(shí)候信息包的端點(diǎn)號(hào)就將是0號(hào))。這種將不同功能分配到不同endpoint上的方法非常有利于任務(wù)的劃分,是一種很正規(guī)的方法。 例子二、一個(gè)無(wú)線節(jié)點(diǎn)(radio uint)A上有4個(gè)LED需要被控制,另外一個(gè)無(wú)線節(jié)點(diǎn)B則有4個(gè)開(kāi)關(guān)用來(lái)控制這4個(gè)LED。這種情形的規(guī)范實(shí)現(xiàn)方式還是要為每一個(gè)LED設(shè)置一個(gè)endpoint(允許的范圍內(nèi)你任意指定,只要不重復(fù)),并為每個(gè)endpoint建立一個(gè)task。這樣處理之后,B可以用同樣的命令來(lái)控制4個(gè)LED,而不是每一個(gè)led 用不同的命令,這種情況在public profile實(shí)際上是必須這么做的。
上面兩個(gè)例子可能很多同學(xué)認(rèn)為太麻煩,完全可以變通。變通的想法就是我所有的被控對(duì)象都落在一個(gè)endpoint上,但是我發(fā)的數(shù)據(jù)包內(nèi)容不同,接收端這個(gè)endpoint通過(guò)解析數(shù)據(jù)包的內(nèi)容來(lái)判斷具體該做什么,這種方式實(shí)際上完全可以實(shí)現(xiàn),不過(guò)需要你自己規(guī)定一下數(shù)據(jù)包的格式,即第幾個(gè)字節(jié)表示什么。。。。。 雖然這可以實(shí)現(xiàn)要求,但是我很不贊成這樣,一方面實(shí)際上是增加了你程序設(shè)計(jì)的復(fù)雜度,另一方面完全沒(méi)有了互聯(lián)的可能,尤其是當(dāng)你用ZCL的時(shí)候,這種方式就行不通了。
source
Osal定時(shí)器組織模式
Osal_start_timer()是如何調(diào)用set_event()函數(shù),整個(gè)協(xié)作的過(guò)程詳見(jiàn)課程參考資料。
通過(guò)定時(shí)器數(shù)據(jù)鏈表將其組織起來(lái),這個(gè)鏈表由osal_timer_update()函數(shù)來(lái)管理,由osalTimerUpdate以ms為單位對(duì)這些“軟定時(shí)器”減計(jì)數(shù),當(dāng)定時(shí)器溢出,即調(diào)用osal_set_event函數(shù)。osal_start_timerEx通過(guò)osalAddTimer向鏈表中添加定時(shí)器,由osalTimerUpdate來(lái)減計(jì)數(shù),當(dāng)這個(gè)定時(shí)器溢出后,則會(huì)對(duì)taskID對(duì)應(yīng)的task設(shè)置一個(gè)event_id,從而讓這個(gè)任務(wù)在后面的主循環(huán)中運(yùn)行到。能夠在主循環(huán)中運(yùn)行到的原因是會(huì)調(diào)用osal_set_event函數(shù)來(lái)實(shí)現(xiàn)主循環(huán)里對(duì)此項(xiàng)任務(wù)的調(diào)用
———————————————— https://blog.csdn.net/Rhiney_97/article/details/89739491

byte osal_start_timerEx( byte taskID, UINT16 event_id, UINT16 timeout_value ) { halIntState_t intState;osalTimerRec_t *newTimer;HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.// Add timernewTimer = osalAddTimer( taskID, event_id, timeout_value );if ( newTimer ){ #ifdef POWER_SAVING// Update timer registersosal_retune_timers();(void)timerActive; #endif// Does the timer need to be started?if ( timerActive == FALSE ){osal_timer_activate( TRUE );}}osal_start_timerEx() ->osal_add_timer()
typedef struct{void *next;uint16 timeout; uint16 event_flag;uint8 task_id;uint16 reloadTimeout;} osalTimerRec_t //定時(shí)器數(shù)據(jù)鏈表結(jié)構(gòu)體數(shù)據(jù)發(fā)送/消息
串口發(fā)送函數(shù)
typedef struct {bool configured; // 配置與否uint8 baudRate; // 波特率bool flowControl; // 流控制uint16 flowControlThreshold; //在RX緩存達(dá)到maxRxBufSize之前還有多少字節(jié)空余。當(dāng)?shù)竭_(dá)maxRxBufSize –flowControlThreshold時(shí)并且流控制打開(kāi)時(shí),會(huì)觸發(fā)相應(yīng)的應(yīng)用事件:HAL_UART_RX_ABOUT_FULLuint8 idleTimeout; // 在idleTimout 時(shí)間內(nèi)RX還沒(méi)有得到新的數(shù)據(jù),將會(huì)觸發(fā)相應(yīng)的事件 HAL_UART_RX_TIMEOUT halUARTBufControl_t rx;// 接收halUARTBufControl_t tx;// 發(fā)送bool intEnable; // 中斷使能uint32 rxChRvdTime; // 接收數(shù)據(jù)時(shí)間halUARTCBack_t callBackFunc; // 回調(diào)函數(shù) }halUARTCfg_t;typedef struct {uint16 bufferHead; //Rx/Tx 緩沖區(qū)中的起始字節(jié)位置的索引uint16 bufferTail; // Rx/Tx 緩沖區(qū)中的末尾字節(jié)位置的索引 uint16 maxBufSize; // Rx/Tx 緩沖區(qū)一次最多接收或發(fā)送的字節(jié)數(shù),當(dāng)接收或者發(fā)送字節(jié)數(shù)到達(dá)該值時(shí),產(chǎn)生HAL_UART_RX_FULL or HAL_UART_TX_FULL事件。uint8 *pBuffer; //指向接收字節(jié)的緩沖區(qū) }halUARTBufControl_t;消息接受
一般來(lái)說(shuō),一個(gè)消息對(duì)應(yīng)一個(gè)事件。if ( events & SYS_EVENT_MSG ){MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );while ( MSGpkt ){switch ( MSGpkt->hdr.event )...}由以上可見(jiàn),消息作為系統(tǒng)事件接受的。消息的使用與事件類(lèi)似,使用byte osal_msg_send(byte destination task ,byte *ptr) 觸發(fā),這個(gè)函數(shù)有兩個(gè)參數(shù)分別為接收事件任務(wù)的ID,另一個(gè)為指向消息的指針,用于向一個(gè)任務(wù)發(fā)送命令或消息數(shù)據(jù)。osal_msg_allocate()
uint8 * osal_msg_allocate( uint16 len) {osal_msg_hdr_t *hdr;if ( len == 0 )return ( NULL );hdr = (osal_msg_hdr_t *) osal_mem_alloc( (short)(len + sizeof( osal_msg_hdr_t )) );if ( hdr ){hdr->next = NULL;hdr->len = len;hdr->dest_id = TASK_NO_TASK;return ( (uint8 *) (hdr + 1) );}elsereturn ( NULL ); }typedef struct {void *next;uint16 len;uint8 dest_id; } osal_msg_hdr_t;由以上可知,消息由兩個(gè)部分組成:消息頭和消息的實(shí)際內(nèi)容。消息頭為協(xié)議棧定義的,消息內(nèi)容我們自己添加的。osal_mag_send()
uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ) {if ( msg_ptr == NULL )return ( INVALID_MSG_POINTER );if ( destination_task >= tasksCnt ){osal_msg_deallocate( msg_ptr );return ( INVALID_TASK );}// Check the message headerif ( OSAL_MSG_NEXT( msg_ptr ) != NULL ||OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ){osal_msg_deallocate( msg_ptr );return ( INVALID_MSG_POINTER );}OSAL_MSG_ID( msg_ptr ) = destination_task;// queue messageosal_msg_enqueue( &osal_qHead, msg_ptr );// Signal the task that a message is waitingosal_set_event( destination_task, SYS_EVENT_MSG );return ( SUCCESS ); }//以上,osal_msg_engueue()為入棧操作,消息是按照隊(duì)列的方式被操作的。 //osal_set_event( destination_task, SYS_EVENT_MSG );這句的定義很重要,在發(fā)送消息后,觸發(fā)系統(tǒng)事件,暗示我們消息處理函數(shù)去哪找。osal_msg_receive
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) {afIncomingMSGPacket_t *MSGpkt;if ( events & SYS_EVENT_MSG ){MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );while ( MSGpkt ){switch ( MSGpkt->hdr.event ){// Received when a key is pressedcase KEY_CHANGE:SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );break;// Received when a messages is received (OTA) for this endpointcase AF_INCOMING_MSG_CMD:SampleApp_MessageMSGCB( MSGpkt );break;...}}} typedef struct {uint8 event;uint8 status; } osal_event_hdr_t;osal_event_hdr_t,包含事件發(fā)生的標(biāo)志和狀態(tài),用來(lái)找到事件對(duì)應(yīng)消息的。然后通過(guò)消息中的Event來(lái)判斷需要進(jìn)行的操作。
相關(guān)消息事件在ZComDef.h中定義
##消息隊(duì)列的維護(hù)
系統(tǒng)事件會(huì)在對(duì)應(yīng)接收到消息后在對(duì)應(yīng)的Event中觸發(fā)。
消息的處理與使用與事件類(lèi)似,使用byte_osal_msg_send(byte destination , byte_*msg_ptr)函數(shù)觸發(fā),指向一個(gè)任務(wù)發(fā)送命令或數(shù)據(jù)消息,同時(shí)出發(fā)系統(tǒng)消息任務(wù)。
消息是按照隊(duì)列的方式進(jìn)行管理的,
重要函數(shù)Collection
ASDU:Zigbee協(xié)議中APS應(yīng)用服務(wù)數(shù)單元AF_DataRequest()
向指定的節(jié)點(diǎn)的端口發(fā)送數(shù)據(jù)。端點(diǎn)借助單項(xiàng)鏈表進(jìn)行管理,用戶(hù)需要使用某個(gè)端點(diǎn)繼續(xù)通訊時(shí),先要調(diào)用afResiger注冊(cè)相應(yīng)的端點(diǎn)向端點(diǎn)管理鏈表添加一條記錄。
端點(diǎn)的接受過(guò)程:afIncomingData函數(shù)提取來(lái)自APS層數(shù)據(jù)包中的目標(biāo)端點(diǎn)號(hào),匹配對(duì)應(yīng)的端點(diǎn)。
//若配置應(yīng)用ID、應(yīng)用配置ID,則數(shù)據(jù)會(huì)被打包, 借助OSAL的消息機(jī)制,最終發(fā)送到相應(yīng)對(duì)點(diǎn)應(yīng)用對(duì)象的消息處理函數(shù)。
Question :
并未找到此函數(shù)在何處調(diào)用。在老師AF_DataRequest()函數(shù)說(shuō)明文檔中標(biāo)注:
發(fā)送數(shù)據(jù)通過(guò)在應(yīng)用層調(diào)用函數(shù)void SampleApp_SendFlashMessage(uint 16 flashTime),其參數(shù)為發(fā)送的數(shù)據(jù)。afStatus_t AF_DataRequest( //afStatus_t == uint 8 afAddrType_t *dstAddr, //*dstAddr 發(fā)送網(wǎng)絡(luò)號(hào)+端點(diǎn)號(hào),即確定一個(gè)事件 endPointDesc_t *srcEP,//終端節(jié)點(diǎn)的描述 uint16 cID, //簇id uint16 len, //發(fā)送數(shù)據(jù)長(zhǎng)度 uint8 *buf, //發(fā)送數(shù)據(jù)緩沖區(qū) uint8 *transID,//任務(wù)ID號(hào)指針 uint8 options, //有效位掩碼發(fā)送選項(xiàng) uint8 radius//傳送跳數(shù),常為AF_DEFAULT_RADIUS,10跳 )Uint 16 cID: 簇ID號(hào),具體應(yīng)用串ID
uint8 options:
? #defineAF_FRAGMENTED 0x01
? #defineAF_ACK_REQUEST 0x10 //需要接收方的確認(rèn)
? #defineAF_DISCV_ROUTE 0x20
? #defineAF_EN_SECURITY 0x40
# defineAF_SKIP_ROUTING 0x80
afAddrType_t
typedef struct { union { uint16 shortAddr; //短地址ZlongAddr_t extAddr;//長(zhǎng)地址 byte ZLongAddr_t[8],8個(gè)8字節(jié),即64位}addr; afAddrMode_t addrMode;//傳送模式 ,廣播/單點(diǎn)/間接...byte endPoint; //端點(diǎn)號(hào) 1-240,區(qū)分不同端點(diǎn)uint panID //網(wǎng)絡(luò)號(hào) 同一節(jié)點(diǎn)的網(wǎng)絡(luò)號(hào)相同 }afAddrType_t;endPointDesc_t 端點(diǎn)描述集群
typedef struct { byte endPoint; //端點(diǎn)號(hào) byte* task_id; //指向任務(wù)的TASK_IDSimpleDescriptionFormat_t *simpleDesc; //簡(jiǎn)單的端點(diǎn)描述 afNetworkLatencyReq_t latencyReq; //網(wǎng)路延遲請(qǐng)求:有noLaencyReqs/fastBeacons/slowBeacons.三種模式 }endPointDesc_t;afAddrMode_t 地址發(fā)送模式
typedef enum//afAddrMode_t數(shù)據(jù)傳送類(lèi)型 { afAddrNotPresent = AddrNotPresent, //間接傳送,直接按照綁定表傳輸。 afAddr16Bit = Addr16Bit,//短地址傳輸,即點(diǎn)對(duì)點(diǎn)傳輸,在傳輸是需要設(shè)置addr.shortAddr為目的節(jié)點(diǎn)的16為地址 adAddr64bit = Addr64bit,//點(diǎn)對(duì)點(diǎn),通過(guò)IEEE地址傳輸 afAddrGroup = AddrGroup,//傳輸在一個(gè)組內(nèi)傳輸。地址模式設(shè)置為afAddGroup,且addr.shortAddr設(shè)置為組id。 afAddrBroadcast = AddrBroadcast //廣播傳送。 } afAddrMode_t;//數(shù)據(jù)傳送類(lèi)型endPointDesc_t. 設(shè)備端點(diǎn)描述符
typedef struct {byte endPoint;byte *task_id; // Pointer to location of the Application task ID.SimpleDescriptionFormat_t *simpleDesc; //設(shè)備簡(jiǎn)單描述符afNetworkLatencyReq_t latencyReq;} endPointDesc_t;//設(shè)備端點(diǎn)描述符SimpleDescriptionFormat_t 簡(jiǎn)單描述符群集
typedef struct{ byte EndPoint; //EP uint16 AppProfId; //應(yīng)用規(guī)范ID uint16 AppDeviceId; //特定規(guī)范ID的設(shè)備類(lèi)型 byte AppDevVer:4; //特定規(guī)范ID的設(shè)備的版本 byte Reserved:4; byte AppNumInClusters;//輸入簇ID的個(gè)數(shù) cId_t *pAppInClusterList;//輸入簇ID的列表的指針byte AppNumOutClusters; //輸出簇ID的個(gè)數(shù) cId_t *pAppOutClusterList;//輸出簇ID的列表 的指針 }SimpleDescriptionFormat_t;afStatus_t
typedef enum {afStatus_SUCCESS,//0x00afStatus_FAILED ,//0x01afStatus_MEM_Error,//0x10afStatus_INVALID_PARAMETER,//0x02afStatus_NO_ROUTE//0xCD } afStatus_t;halUARTCfg_t類(lèi)型 串口設(shè)置
typedef struct {bool configured;//uint8 baudRate;//bool flowControl;//uint16 flowControlThreshold;//uint8 idleTimeout;//如果在idleTimout 時(shí)間內(nèi)RX還沒(méi)//有得到新的數(shù)據(jù),將會(huì)觸發(fā)相應(yīng)的事件HAL_UART_RX_TIMEOUT ,這時(shí)應(yīng)用可以選擇讀出所有RX的值或者一部分。halUARTBufControl_t rx;//用于控制RX緩存halUARTBufControl_t tx;//用于控制TX緩存bool intEnable;//uint32 rxChRvdTime;//halUARTCBack_t callBackFunc;//回調(diào)函數(shù) }halUARTCfg_t;osal_start_timeEx()
(一旦網(wǎng)絡(luò)狀態(tài)變化)進(jìn)行任務(wù)初始化,設(shè)置任務(wù),發(fā)送編號(hào),設(shè)定時(shí)間函數(shù)幫助我們登記任務(wù),設(shè)置編號(hào),設(shè)定定時(shí)器時(shí)間。任務(wù)即確定在哪個(gè)task,編號(hào)則確定觸發(fā)什么事件,定時(shí)器則是間隔多久觸發(fā)這個(gè)事件。
Dev_States_t
網(wǎng)絡(luò)狀態(tài)結(jié)構(gòu)體、定義了節(jié)點(diǎn)各個(gè)網(wǎng)絡(luò)狀態(tài) typedef enum {DEV_HOLD, // Initialized - not started automaticallyDEV_INIT, // Initialized - not connected to anythingDEV_NWK_DISC, // Discovering PAN's to joinDEV_NWK_JOINING, // Joining a PANDEV_NWK_SEC_REJOIN_CURR_CHANNEL, // ReJoining a PAN in secure mode scanning in current channel, only for end devicesDEV_END_DEVICE_UNAUTH, // Joined but not yet authenticated by trust centerDEV_END_DEVICE, // Started as device after authenticationDEV_ROUTER, // Device joined, authenticated and is a routerDEV_COORD_STARTING, // Started as Zigbee CoordinatorDEV_ZB_COORD, // Started as Zigbee CoordinatorDEV_NWK_ORPHAN, // Device has lost information about its parent..DEV_NWK_KA, // Device is sending KeepAlive message to its parentDEV_NWK_BACKOFF, // Device is waiting before trying to rejoinDEV_NWK_SEC_REJOIN_ALL_CHANNEL, // ReJoining a PAN in secure mode scanning in all channels, only for end devicesDEV_NWK_TC_REJOIN_CURR_CHANNEL, // ReJoining a PAN in Trust center mode scanning in current channel, only for end devicesDEV_NWK_TC_REJOIN_ALL_CHANNEL // ReJoining a PAN in Trust center mode scanning in all channels, only for end devices } devStates_t;osalTimerRec_t結(jié)構(gòu)體
typedef struct {void *next;uint16 timeout;uint16 event_flag;uint8 task_id;uint16 reloadTimeout; } osalTimerRec_t;消息的傳輸
afIncomingData()函數(shù)用來(lái)從APS層傳遞一個(gè)ASDU到AF層,中間調(diào)用afBuildMSGIncoming()函數(shù),為APS層建立一個(gè)特定格式的消息包,最后調(diào)用osal_msg_send()把消息傳送到AF層。
處理AF層數(shù)據(jù)包的大致流程: afIncomingData() -> adBuildMSGIncoming()->osal_msg_send()->oasl_set_event()
setevent()
在tasksEvent數(shù)組中對(duì)應(yīng)的taskid位置設(shè)置eventsuint8 osal_set_event( uint8 task_id, uint16 event_flag ) {if ( task_id < tasksCnt ){halIntState_t intState;HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interruptstasksEvents[task_id] |= event_flag; // Stuff the event bit(s)HAL_EXIT_CRITICAL_SECTION(intState); // Release interruptsreturn ( SUCCESS );}else{return ( INVALID_TASK );} }AfIncomingData()
當(dāng)節(jié)點(diǎn)收到數(shù)據(jù)時(shí),會(huì)調(diào)用AfIncomingData()
afIncomingMSGPacket_t
接受發(fā)送的數(shù)據(jù),afIncomingMSGPacket_t結(jié)構(gòu)體為消息的封裝內(nèi)容。 typedef struct {osal_event_hdr_t hdr; /* OSAL Message header */uint16 groupId; /* Message's group ID - 0 if not set */uint16 clusterId; /* Message's cluster ID */afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,it's an InterPAN message */uint16 macDestAddr; /* MAC header destination short address */uint8 endPoint; /* destination endpoint */uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */uint8 LinkQuality; /* The link quality of the received data frame */uint8 correlation; /* The raw correlation value of the received data frame */int8 rssi; /* The received RF power in units dBm */uint8 SecurityUse; /* deprecated */uint32 timestamp; /* receipt timestamp from MAC */afMSGCommandFormat_t cmd; /* Application Data */} afIncomingMSGPacket_t;//afIncomingMSGPacket_t gtwRxFromNode;// Generalized MSG Command Formattypedef struct // afMSGCommandFormat_t; {byte TransSeqNumber;uint16 DataLength; // Number of bytes in TransDatabyte *Data;} afMSGCommandFormat_t;數(shù)據(jù)的發(fā)送和接受
對(duì)接收方需要做的兩件事1)注冊(cè)一個(gè)端點(diǎn),通過(guò)在XXXXApp_Init()函數(shù)里調(diào)用afRegister()來(lái)實(shí)現(xiàn)。如果需要處理ZDO消息和案件消息還得調(diào)用相應(yīng)的注冊(cè)函數(shù)ZDO_RegisterForZDOMsg,RegisterForKeys。
2)注冊(cè)了端點(diǎn)和消息之后,需要寫(xiě)一個(gè)消息處理函數(shù),來(lái)響應(yīng)各種消息,這個(gè)函數(shù)通常叫作XXXXApp_ProcessEvent()。
對(duì)于發(fā)送來(lái)說(shuō),事情就簡(jiǎn)單了,只要調(diào)AF_DataRequest()函數(shù),向指定的節(jié)點(diǎn)的端口發(fā)送數(shù)據(jù)即可。
從AF.C和AF.H可以看到端點(diǎn)是借助單向鏈表來(lái)管理的。用戶(hù)需要使用某個(gè)端點(diǎn)進(jìn)行通訊時(shí),先要調(diào)用afRegister注冊(cè)相應(yīng)的端點(diǎn)向端點(diǎn)管理鏈表添加一條記錄。
端點(diǎn)一 注冊(cè)之后,在接收和發(fā)送兩個(gè)過(guò)程中都會(huì)使用到。
在接收過(guò)程,afIncomingData函數(shù)提取來(lái)自APS層數(shù)據(jù)包中的目標(biāo)端點(diǎn)號(hào),搜索節(jié)點(diǎn)已注冊(cè)的端點(diǎn)號(hào),進(jìn)行匹配。如果端點(diǎn)號(hào)匹配則需要進(jìn)一步匹配應(yīng)用配置ID,應(yīng)用配置ID也匹配的語(yǔ),數(shù)據(jù)包就會(huì)被打包,然后借助OSAL的消息機(jī)制,最終發(fā)送到相應(yīng)端點(diǎn)應(yīng)用對(duì)象的消息處理函數(shù)。
在發(fā)送過(guò)程,端點(diǎn)信息被AF_DataRequest讀取,填寫(xiě)到數(shù)據(jù)包相關(guān)的區(qū)域,如果端點(diǎn)注冊(cè)了回調(diào)函數(shù),回調(diào)函數(shù)將在數(shù)據(jù)發(fā)送前被調(diào)用。
數(shù)據(jù)收發(fā)過(guò)程中雙方必需指定端點(diǎn)號(hào)和網(wǎng)絡(luò)地址,這樣才能在一個(gè)節(jié)點(diǎn)中確定一個(gè)任務(wù)。一個(gè)端點(diǎn)對(duì)應(yīng)一個(gè)任務(wù),一個(gè)任務(wù)可以掛載多個(gè)端點(diǎn)。
端點(diǎn)里可以定義多個(gè)簇,發(fā)送的時(shí)候定義哪個(gè)端點(diǎn)中的哪個(gè)簇。
?Zstack Osal定時(shí)器事件觸發(fā)流程分析
系統(tǒng)事件的幾種類(lèi)型。
系統(tǒng)事件觸發(fā)的條件。
Zstack對(duì)于端點(diǎn)的管理。(單項(xiàng)鏈表)
協(xié)調(diào)器和終端節(jié)點(diǎn)的設(shè)備號(hào)以及端點(diǎn)號(hào)可以都一樣嗎?是不是協(xié)調(diào)器有協(xié)調(diào)器的設(shè)備號(hào)和端點(diǎn)號(hào),終端節(jié)點(diǎn)有終端節(jié)點(diǎn)的。二者不相干:
ProfileID必須一樣
DeviceID可以不一樣
Endpoint也可以不一樣,但是通信的時(shí)候必須要知道目的設(shè)備的Endpoint,負(fù)責(zé)無(wú)法通信上。
Profile ID只是一類(lèi)應(yīng)用的ID號(hào),比方說(shuō)智能家居,無(wú)線開(kāi)關(guān),溫度傳感器,doorlock,窗簾控制器等等,屬于智能家居的產(chǎn)品,那么他們的profile ID都是一樣的。智能家居是0x0104device ID是值一個(gè)profile ID下面,不同設(shè)備的id號(hào),設(shè)置這個(gè)ID號(hào)的目的在于知道ID號(hào),就知道這個(gè)設(shè)備具備哪些功能。
比方說(shuō)一個(gè)on/off Light 和一個(gè)Dimmer Light的device id是不一樣的,功能不同。
總結(jié)
Q:
Zstack控制在代碼一樣的情況下將設(shè)備分別燒成協(xié)調(diào)器、終端,路由器。
流程整理
如果一個(gè)節(jié)點(diǎn)(Radio Unit)有多個(gè)終端設(shè)置,每增加一個(gè)終端節(jié)點(diǎn),設(shè)置對(duì)應(yīng)的taskid,并對(duì)其進(jìn)行注冊(cè),接入鏈表,終端節(jié)點(diǎn)是通過(guò)鏈表進(jìn)行維護(hù)的,通過(guò)端點(diǎn)號(hào)對(duì)其進(jìn)行查找;注冊(cè)完畢,對(duì)其進(jìn)行初始化,然后為每一個(gè)taskid建立一個(gè)任務(wù)處理函數(shù),對(duì)其進(jìn)行操作。
總結(jié)
以上是生活随笔為你收集整理的zigbee 串口不稳定_Zigbee的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果手机怎么查看路由器密码苹果手机如何查
- 下一篇: solidworks无法获得下列许可st