TI提供的例子簡介

Zigbee好好研究給的例子的功能,到時候直接簡單修改就能用而不是從新寫

 此文檔在是Zigbee軟件自帶的,翻譯了一些東西

Z-Stack Sample Applications.Pdf文檔學習

文檔是介紹關於SampleApp例子的。下面是一點重點

1.1

1.開發zigbee方法就是利用板子配套的例子在其上就行修改而已這是最快有效的方法

2.例子中的ProfileID是隨機設定的要修改成國標才能通用,

3.系統中每一個應用要對應一個endpoint(類似端口)及相應描述結構,端口號也是隨機選的,要自行修改

4.例子中只有一個應用但是在實際中同一設備中可能包含多個應用進程。不同的應用進程對應不同的應用方面所以profileID是不同的可以參考國標設定或自行選擇但是就不通用了和其他標準

1.2

OSAL系統有源碼。自己可以修改但是用於開發時,沒有太大的必要自己修改源碼而是利用就行。但是源碼必須User自己修改的是系統任務初始化(OSAL Taskinitialization)的函數--osalInitTasks();其中需要User自己定義添加應用函數,完成自己想要的功能。

OSAL_GenericApp.c就是用戶自己編寫的應用功能文件。一般就是用OSAL_XX.c的形式定義名字方便查找。BSP(板級支持包)初始化時調用osalInitTasks();其過程是

Main.c--osal_init_system();--osalInitTasks();--SampleApp_Init(taskID );就會再次定義應用處理函數。有OSAL的運行機理知道,每一個Z-STACk的子系統都是作爲OSAL的一個任務task來運行的(把每個邏輯層歸爲一個task,而每一層不同的操作處理歸爲不同的event)。User必須把自己應用以osal系統任務的形式給出。這需要一下操作:1.osalInitTask()中添加SampleApp_Init( taskID );項做相關的初始化2、在OSAL_XX.c中尋找tasksArr數組後添加XXXApp_ProcessEvent (自己編寫的應用處理函數,應用消息的方式來選擇不同應用事件的)(不同的應用都在一塊麼還是要另寫一個??要找一個多應用的例子看看比較一下)

任務優先級是按照在tasksArr出現的順序依次降低

1.25

應用層的設計:

每次應用對象可以創建一個task或者所有的應用對象服務在一個任務裏。如何選擇有幾個考慮:

1.     一個task包含多個ApplicationObjects

優點:當有一個事件發生時,處理函數被簡化;節省建立多個task的堆棧空間;

缺點:當收到AF信息且信息的確認很複雜時,此時分解多工作機制的任務在一個task中負擔重;通過請求標誌來尋找相應的請求服務的困難度增加

2.     一對一

優點:上述第二個缺點解決了

缺點:堆棧空間浪費;當多個應用使用相同的專用資源的事件發生時,所採取的多個行動之間協調複雜度提高

 

每個OSALtask都有兩個必須的處理,(1)初始化函數2task_event處理函數

1)初始化函數

1.     命名XXX_init

2.     要初始化應用對象的局部變量和該應用對象專用的變量。長時間都運行存在使用的堆棧此時應該分配,這樣可以更加高效管理內存(等到使用時就不需要動態分配了)

3.     相應應用對象的初始化,通過AF層相應的註冊函數完成註冊(afRegister()

4.     硬件和系統提供的服務的註冊(RegisterForKeys()等)

2task_event處理函數

1、命名XXX_ProcessEvent,一個任務可以定義15event

在此事件處理函數中通過逐一比較查找的方式,在確定是哪個事件的發生

1.27

事件種類:

SYS_EVENT_MSG:有系統消息發給該task(該邏輯層)

osal_start_system()--osal_run_system()(不停循環)查找tasksEvents其實就是哪個邏輯層上有事情需要處理,取出該層的event後進入此事件的處理函數,event比較看是哪個事件發生,找到 SYS_EVENT_MSG發生選項後,會調用取信息函數,得到該task的信息,查看消息根據類型,後做相應的處理

注意系統消息又分爲不同種類,告知應該做什麼事情處理如下,

AF_DATA_CONFIRM_CMD:如果有數據請求就通過調用AF_DataRequest()函數會發出無線請求信息,發射的每一個無線信息成功後返回一個結果指示表明發射成功就是它

AF_INCOMING_MSG_CMD 表明有來自AF層的消息

KEY_CHANGE表明有按鍵按下

ZDO_STATE_CHANGE 表明網絡狀態改變(由於重啓,或拓撲改變等)

ZDO_CB_MSG表明此信息是響應信息,當完成ZDO註冊後會給該應用層發出響應信息,ZDO_CB_MSG就標誌此信息就是該響應信息

通過switch ( MSGpkt->hdr.event)來選擇對應的處理過程。MSGpkt是讀取的系統消息結構體。

各個層之間存在哪些信息,或者說信息是怎麼流動的?及發送不同信息後爲什麼做這樣的處理,各層消息和相關處理的一一對應

1.3


組網

在一個項目中的設備根據硬件分爲全功能設備和受限的設備,全功能一般用作協調器或路由,受限的只能是終端,而協調器路由和終端的區分是從代碼的角度區分的,根據不同的編譯選項區分,查看代碼知道ZCD_NV_CHANLIST處使用zgDefaultChannelList。而此又使用DEFAULT_CHANLIST。協調器會掃描在ZCD_NV_CHANLIST配置參數中設置的所有信道,選擇一個能量最低的頻道最爲建網的頻道,如果多餘一個低能量網,就選擇已存在網絡數最少的頻道加入     ,確定頻道之後協調器使用ZCD_NV_PANID參數決定PAN_ID  ,ZCD_NV_PANID使用zgConfigPANID而此又使用  ZDAPP_CONFIG_PAN_ID,當ZDAPP_CONFIG_PAN_ID爲0xffff時根據IEEE地址來產生隨機數當做PAN_ID,否則PAN_ID是ZDAPP_CONFIG_PAN_ID要是跟周邊環境重複,就自動改變知道產生不同的唯一的爲止(注意此時會出現BUG,因爲當在編碼中設置了路由和終端要加入的頻道和PAN_ID後,如果協調器出現設定的PAN_IN不能用的情況就會出現錯誤了讓路由和終端加入到不該加入的網絡)

如果是路由或終端話就使用ZCD_NV_CHANLIST配置參數,而此數使用 zgDefaultChannelList 而此數又使用 DEFAULT_CHANLIST決定加入的網絡的頻道,然後據當ZCD_NV_PANID。。。。ZDAPP_CONFIG_PAN_ID不爲0xFFFF時加入該網絡,要是0xffff,就??

還是沒懂路由或終端是怎麼加入一個已經處在多個網絡和多個頻道的找到想要的協調器的???

1.3.1網絡組建啓動方式

1、Auto Start---SOFT_START

BSP上電後的初始化後設備會自動的建立或加入網絡(設備的類型決定了操作是加入還是建立網絡)。

2、手動啓動---HOLD_AUTO_START當採取等待一事件發生後才加入或建立網絡的策略時就要定義HOLD_AUTO_START且在等待事件發生後的處理函數中調用ZDOInitDevice(),這就開啓加入或建立網絡了

當一設備(終端路由或協調器)定義了NV_RESTORE and/orNV_INIT.時,由於意外重啓或斷電後就能再次重建或加入之前的網絡(相同的頻道和PAN_ID),原因就是該參數設定後,就會把該類信息存放在斷電不丟的ROM中。要是沒設置相應的參數的話重啓後出現什麼情況??

設備加入或建立一網絡或者自身所處的網絡狀態改變後後會得到一個網絡變化的系統信息爲ZDO_STATE_CHANGE

1.4

綁定和發現

TI的例子講解,當協調器組網完成後設備加入網絡,協調器會有一段特殊的時間(還不清楚什麼時候開啓的)再此時間段內,如果有兩個設備同時按下SW2則會在協調器中建立綁定條目,實現兩個設備的綁定,而如果按下的是SW4,進行的是兩兩綁定,以廣播的形式發現匹配設備。綁定成功後一燈亮,沒有成功的綁定就會燈閃爍不停

1.4.1綁定:

SW2類型的綁定過程中使用ZDApp_SendEndDeviceBindReq()函數。當一個設備按下SW2後調用ZDApp_SendEndDeviceBindReq(),會給reflector(一般由協調器擔當)發送綁定請求,此綁定請求的clustersinputoutput)類型,此時必須有另外一個設備也同時按下SW2調用ZDApp_SendEndDeviceBindReq(),發送clustersoutputinput)類型的綁定請求。就是說綁定clusters必須相反互補,這樣的按鍵操作發送綁定請求必須在APS_DEFAULT_MAXBINDING_TIMEmilliseconds時間內完成,而且在簡單描述結構中的command_ID 必須相同。此類綁定優缺點:

優點:

1、綁定表存儲在network reflectorRAM中,節省了綁定兩端設備的空間

2、network reflector必須時刻處在RxOnWhenIdle狀態,就是說及時不工作沒有任務處理也不能進入省電而是處在允許接受的空閒狀態,當綁定一端的設備地址改變時,該設備廣播地址改變的信息,network reflector會受到信息並改變綁定條目,而綁定表的另一端的設備哪怕處在睡眠也無所謂,也不會出錯

缺點:

1、當發送端設備綁定了多個接受設備時,如果發送端設備只想給一個或者部分接收端綁定設備時,此時就無能無力了,network reflector是根據綁定表採用逐一單點發送給接收方的

2、發送方使用AF_ACK_REQUESTflag.時也不會接受到接收方的相應信息

3、所有信息傳遞必須經過network reflector,負荷增加,網絡帶寬降低。

優點/缺點:如果一發送終端綁定六個接受終端,發送方在A區域邊緣,接收方在B區域另一邊緣,network reflector在兩區域的中間線上,則通過綁定的方式運行時,發送方發送一條信息給network reflector,在A區域只有一條信息在傳送,之後network reflector發送6條單播信息給接收方,在B區域有六條信息在傳送,而如果不用綁定的話AB區域都會有6條信息在傳送,比較的綁定減少了網絡流量,但是當發送方和接受方在同一區域。但是收發方在臨近且在一區域深處時,通過非綁定的單播形式可以降低此大區域的數據流量,因爲信息傳輸只在一個小區域內,要是綁定的話,整個區域內信息要走一遍,造成大片區域網絡阻塞。

 

1.4.2發現(Auto Find)Match DescriptorRequest

設備A用於發現網絡中相匹配的設備B進行綁定,A是發送發,B是接收方

A設備程序要執行的步驟:

1、 執行ZDO_RegisterForZDOMsg()進行ZDO註冊,用來說明此設備要處理收到的ZDO Match DescriptorResponse類型的信息(ZDO層接受無線信息,此函數就是告知ZDO層把收到的消息匹配,註冊的信息類型就留下並通過一定方式發送給對應的註冊函數,對於沒註冊和不是本設備的信息都扔掉)

 

2、 調用ZDP_MatchDescReq()(本例是以按下SW4啓動此函數),產生一個廣播信息,此信息中含有一個output clusters列表,是本設備可以與之綁定的cluster ID 凡是收到此廣播信息的設備都會把自己的cluster 與此信息的output clusters列表匹配且設備屬性是接受方纔行,符合條件的設備會發送一條單播給發廣播的設備

 

3、 處理收到的ZDO Match Descriptor Response 類型的信息(ZDO_CB_MSG類型) 提取出發送該響應信息的地址,建立綁定標最爲默認的發送信息的地址(查看源碼怎麼處理ZDO_CB_MSG類型的信息的)

優缺點:

優點:

1、收到的相應信息可以不保存,如果建立了很多綁定地址,可以只是用其中的幾個不必同時全部使用

2、當發送方使用AF_ACK_REQUEST標誌發送信息時會得到接受方的相應

3、信息可以被投放到最好的路由處,保存網絡帶寬

 

 

缺點:

1、綁定表建立在終端出,佔用RAM甚至可能是ROM用於備份,當斷電時地址的恢復

2、發送端要時刻處於RxOnWhenIdle狀態不能休眠保存電力,以用來監測接收方可能的地址的變化

 

優缺點:如果一發送終端綁定六個接受終端,發送方在A區域邊緣,接收方在B區域另一邊緣,則通過此綁定的方式運行時,發送方發送六條信息通過A區域到達並經過B區域後6條單播信息給接收方,增大了整個區域的數據流量,但是當發送方和接受方在同一區域時信息的流通侷限在一個小區域,降低大區域的數據流量

 

1.6程序流程

GenericApp_TaskID =task_id;有一個全局變量保存了任務號

系統採用爲每個任務建立時鐘定時,設置事件標誌,自己給自己傳送個消息等方式爲的是把一個複雜的系統處理過程分治爲多個小的模塊,可以再小週期內依次輪流處理各個事務,防止在一個事務上花太多的時間

GenericApp_NwkState= DEV_INIT;

設備上電時默認的網絡的狀態是沒有連接或稱爲DEV_INIT,當電源啓動過程中及啓動完成後,系統都不會接受到網絡默認狀態改變的信息,所以網絡的狀態必須本地初始化,應該是自己調用函數接受無線信息進行相關網絡狀態初始化。初始化完後系統會得到ZDO_STATE_CHANGE的信息。當系統使用NV_RESTORE選項後就會使系統自動保存網絡狀態信息到ROM中斷電不丟失,當再次斷電重啓過程中就會使用保存的網絡狀態進行恢復,在電源開啓過程中就得到ZDO_STATE_CHANGE的信息。

GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;

GenericApp_DstAddr.endPoint = 0;

GenericApp_DstAddr.addr.shortAddr = 0;

系統開啓後默認的發送信息目的地址的設置如上,採用的是保存的綁定表的地址,要是沒有則按上述設置後的結果是信息被丟棄,因爲找不到目的地址

GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;

GenericApp_epDesc.task_id = &GenericApp_TaskID;

GenericApp_epDesc.simpleDesc =

SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;

GenericApp_epDesc.latencyReq = noLatencyReqs;

// Register the endpoint description with the AF

afRegister(&GenericApp_epDesc );

在AF層註冊端點

GenericApp Application Object自己定義的應用對象通過上述進行具體實例化,註冊的作用就是建立目的地址查找表,告知AF層對於進入到AF層的信息通過profile和endpoint進行路由找到接收方。當AF層發送OSAL SYS_EVENT_MSG-message(AF_INCOMING_MSG_CMD)給相應的taskID時就需要上述的task的註冊

RegisterForKeys( GenericApp_TaskID );

特定的按鍵註冊函數

比較afRegister(&GenericApp_epDesc );和RegisterForKeys(GenericApp_TaskID );

兩個註冊函數區別

搞懂信息是怎麼傳到AF層的又怎麼通過註冊傳到task的????

 

 

 

1.6.2事件處理

當應用層的事件發生時就會標記相應的event位,在事務循環過程中查到到後就進入相應的事件處理函數中當有多個事件發生時推薦一個循環查找之處理一個事件,且是時間最緊迫的優先處理,通過先後順序決定優先級,因爲OSAL機制就是爲了達到在一小段時間內處理一個小事務而不是大量事件處理一整個過程,當時在處理if ( events & SYS_EVENT_MSG )時也建議將不同的信息處理放在一塊分類處理而不是分開處理。

按鍵事件處理--KEY_CHANGEmessage.

1、系統任務要註冊,RegisterForKeys(GenericApp_TaskID );這樣按鍵發生時GenericApp_TaskID就會得到按鍵相關的消息

2、按鍵按下後系統會通過輪詢或者中斷的方式得到此事件的發生

3、HAL OSAL task檢測到按鍵狀態的改變,調用相應層-HAL層的處理函數

4、調用的HAL處理函數時就會發送狀態改變的消息到之前註冊的函數中去

 

case AF_DATA_CONFIRM_CMD:

// The status is of ZStatus_t type [defined in ZComDef.h]

// The message fields are defined in AF.h

//此處是說明該應用系統消息,取出該消息之後,判斷消息類型爲AF_DATA_CONFIRM_CMD

//之後做如下處理

afDataConfirm = (afDataConfirm_t *)MSGpkt;   //讀取得系統信息

sentEP = afDataConfirm->endpoint;              

sentStatus = afDataConfirm->hdr.status;    //解釋3

sentTransID = afDataConfirm->transID;      //解釋1

 

 

當收發方不同時:

每次調用AF_DataRequest()要是沒有AF_ACK_REQUEST看代碼知道不會產生AF_DATA_CONFIRM_CMD的事件要處理,只是把信息傳送到網絡層的數據緩衝區(原來信息空間在此釋放了?)但是要是設置了怎會在得到接受方的ACK信息後產生AF_DATA_CONFIRM_CMD的事件

當收發方相同時會看到無論設置與否都會有AF_DATA_CONFIRM_CMD,對於此類信息不會到達網絡層的數據緩衝區,估計是掛在到系統消息隊列中並進行事件標記了

在哪裏釋放此信息的空間ne????

如果此函數返回值是success分兩種情況,

要是第七個參數沒有AF_ACK_REQUEST選項表示只是把信息發到下一層(網絡層),網絡層會後續處理該信息。而此時沒有要是有也只是起到作用是作爲MAC層ACK;如果第七個參數包含AF_ACK_REQUEST且返回success表示信息被目的地成功接收,此時AF_DATA_CONFIRM_CMD的事件的作用是作爲APS 的ACK,如果地址是綁定形式的則意味着信息發到the network reflector成功。

解釋1:sentTransID是一種確認信息的方式。在同一cluster上的不同的endpoint甚至是不同cluster的每個endpoint保存一個單獨的Transaction Id,爲的是信息確認重傳解析和重裝信息。當每次成功調用AF_DataRequest()後transaction ID 狀態變量被增加,說明transaction ID是個應用指針而不是值。(*transID)++

解釋3:當AF_DataRequest()函數第七個參數沒有設置AF_ACK_REQUEST則返回成功意味着信息已經被網絡層接受,網絡層接受後把信息發到MAC層,之後MAC層把信息通過無線發送出去。無線發送的結果狀態是用sentStatus標誌的,sentStatus成功表示這信息被髮送到網絡中的下一跳設備上,在代碼中sentStatus和AF_DataRequest()的同一值都是APSDE_DataReq()返回值

如果AF_DataRequest()調用時第七個參數設置爲AF_ACK_REQUEST,則返回的成功意味着目的地址已經成功接受到此信息,

 


對於非廣播消息,有兩種基本的消息重試類型:端到端的確認(APS ACK)和單級確認(single hop acknowledgement)(MAC ACK)。MAC ACK默認情況下是一直打開的,通常能夠充分保證網絡的高可靠性。爲了提供附加的可靠性,同時使發送設備能夠得到數據包已經被髮送到目的地的確認,可以使用APS ACK。

APS acknowledgement在APS層完成,是從目標設備到源設備的一個消息確認系統。源設備將保留這個消息知道目標設備發送一個APS ACK消息表明它已經收到了消息。對於每個發出的消息可以通過調用函數AF_DataRequest()的選項來使能/禁止來禁止這個功能。這個選項區域是一個位映射選項,對於將要發送的消息的選項區域或上(OR)AF_ACK_REQUEST就可以使能APS ACK。消息重試(如果APSACK消息沒有收到)的次數和重試之間的時間間隔的配置項在f8wConfig.cfg文件中。APSC_MAX_FRAME_RETRIES是APS層在放棄發送數據之前,沒有收到APS ACK確認重新發送消息的次數。APSC_ACK_WAIT_DURATION_POLLED是重新發送之間的時間間隔。

APS ACK數據確認命令在應用層event-loop函數中,通過AF_DATA_CONFIRM_CMD進行處理,原始AF層函數爲afDataConfirm(uint8 endPoint, uint8 transID, ZStatus_t status )

 

GenericApp_SendTheMessage()->AF_DataRequest()->

case ZDO_STATE_CHANGE:

GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);

if ( (GenericApp_NwkState == DEV_ZB_COORD)

||(GenericApp_NwkState == DEV_ROUTER)

||(GenericApp_NwkState == DEV_END_DEVICE) )

{

// Start sending "the" message in a regular interval.

osal_start_timer( GENERICAPP_SEND_MSG_EVT,

GENERICAPP_SEND_MSG_TIMEOUT );

}

break;

當網絡狀態改變的時候所有的task都會收到ZDO_STATE_CHANGE.的信息事件

osal_msg_deallocate( (uint8 *)MSGpkt );

收到信息的task要做信息空間釋放的工作

可以嘗試一次task循環讀取多個該任務的系統消息

1.7信息流程

當發送一個auto find ZDO匹配請求是要注意對於受到的相應信息要判斷其地址模式必須是afAddr16Bit纔行其他類型的都過濾掉,在響應信息中可得到匹配的地址和端口

當收發方不同時,調用AF_DataRequest()函數只是把信息放到了網絡層的數據緩衝區至於空間怎麼管理的不知道,進入網絡層後不會立即進入MAC層並無線發送,而是等到下一個taskLOOP是出現MAC層事件才處理信息從網絡層到MAC層及無線發送,當時當MAC原本就有信息時也不會立即處理新信息而是先發送MAC層原有信息後再處理把信息從網絡層移到MAC層。AF_DataRequest()的調用失敗大多是因爲因爲網絡層沒有足夠空間接納新的信息。

信息經過無線發送,路由,到達目的地後要根據信息的內容決定目的端口,後做準備工作告知應該此工作不知道哪個層做的??目的應用對象會通過SYS_EVENT_MSG   信息  AF_INCOMING_MSG_CMD被告知自己有信息到來

case AF_INCOMING_MSG_CMD:

GenericApp_MessageMSGCB( MSGpkt );

break;

當某一task有信息到來後調用該task的信息處理函數GenericApp_MessageMSGCB()

 

 

The GenericAppSample Application 介紹

本例中每5秒發送一個信息,設備一旦加入網路,就會開啓一個時鐘,此時信息不會發出,直到找到目的地址或建立了綁定

當設備加入到一個網絡後ZDO_STATE_CHANGE信息就會在各個task中收到,所以可以再自己的task中的ZDO_STATE_CHANGE項中自己寫相應的處理函數。每一此定時器到了之後,處理函數就是設置相應的事件本例是設備發送信息的事件GENERICAPP_SEND_MSG_EVT對應的event位,然後再taskloop中處理該事件就是發送信息

 

The SerialAppSample Application解釋

本例介紹的PC與PC通過ZIgbee模塊進行通訊,PC與zigbee設備之間用串口聯繫。

 

爲了使用串口一些初始化設置



HAL層通過輪訓或者中斷方式得到串口上的數據,等到了flowControlThresold或者idleTimeout時間纔會讀串口數據 這兩個時間在HalUARTOpen()設置,調用rxCB()處理該數據

通過HalUARTWrite().發送串口數據

 

 

The TransmitAppSample Application

 

本例是演示無線發送數據的最大吞吐量會顯示平均速率和總髮送數據量

 

 

The HomeAutomation Profile

 

 


64位的地址 沒有在AF_DataRequest()出現或者說沒有此種模式(16位組播廣播和NOpresant的綁定)

不會出現64位但是能否使用呢,

當想給以設備發送數據是需要16位地址要是不知道但是如果知道對方64位可以通過函數獲得16位,但是如何獲得的?發送函數時怎樣的用的64位?那麼此處爲什麼不能用64位,還費勁找16位幹什麼,或者不知道對方64位通過廣播匹配方式得到16位地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章