1. 程式人生 > >ZigBee單播通訊原理、串列埠配置 (對於理解收發資料的過程非常重要)

ZigBee單播通訊原理、串列埠配置 (對於理解收發資料的過程非常重要)


ZigBee網路通訊學習方法:
1,剛開始,我們確實需要藉助官方模板,新增簡單的程式碼實驗,建立感性的認識
2,然後在官方程式碼基本實驗基礎上,瞭解相關概念,掌握通訊過程原理,結合自己的理解,自己動手做一個個性化的實驗
   ,來驗證自己的理解。
  
ZigBee通訊方式:單播、廣播、組播、繫結。


先看一下單播:
單播:在ZigBee網路裡面,模組之間要進行通訊,傳送模組非常明確知道接收模組的網路地址,以這個地址傳送資料給接收模組,叫單播。
  
 
ZigBee模組地址特點:
   模組在入網的時候,父節點隨機分配地址給子節點。但是協調器模組在網路裡面的地址永遠是0x00!!!
   
   

傳送模組:

#define SAMPLEAPP_ENDPOINT           20  //定義端點編號

afAddrType_t     SampleApp_Periodic_DstAddr; //宣告
SampleApp_P2P_DstAddr.addrMode            = (afAddrMode_t)Addr16Bit; //宣告為點播 
SampleApp_P2P_DstAddr.endPoint            = SAMPLEAPP_ENDPOINT; //接收模組的端點
SampleApp_P2P_DstAddr.addr.shortAddr      = 0x0000;            //發給協調器,即協調器地址,協調器網路地址始終為0x0000

endPointDesc_t SampleApp_epDesc;
SampleApp_epDesc.endPoint   = SAMPLEAPP_ENDPOINT;//模組的端點
SampleApp_epDesc.task_id    = &SampleApp_TaskID;//指明資料由接收方的哪一個任務來處理(與應用層的任務繫結)
SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;//更加詳細的描述商戰的情況,就像描述一個房間裡面有多少人一樣
SampleApp_epDesc.latencyReq = noLatencyReqs;

uint8 SampleApp_TransID = 0;
afRegister( &SampleApp_epDesc );//端點必須要到系統裡面註冊繫結
 
uint8 SendBuf[] = "hello world!"; 
AF_DataRequest( &SampleApp_P2P_DstAddr,//接收模組 
                &SampleApp_epDesc,
                SAMPLEAPP_P2P_CLUSTERID,//指明接收模組的簇,相當於指明瞭資料要發到房間裡面的具體的哪一個人 #define SAMPLEAPP_P2P_CLUSTERID 4
                (uint8)osal_strlen(SendBuf)+1,//傳送的位元組大小
                SendBuf,//傳送陣列的首地址
                &SampleApp_TransID,//表示已經成功傳送了多少幀,這裡要傳地址,底層傳送成功以後,會修改這個值
                AF_DISCV_ROUTE,
                AF_DEFAULT_RADIUS);
/* 表示SendBuf資料從傳送方的20號端口出去,發到 協調器的20號埠,並且由協調器的SampleApp_TaskID任務來處理接收到的訊息,且以單播的形式傳送資料 */

AF_DataRequest把SendBuf中的前10個位元組傳送給協調器(協調器的地址一定為0x0000)。     
   
   
接收模組:

在事件處理函式:
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{


  //把收到的資料列印到串列埠
  {
    // uint8 afRxData[30]={0};
    //osal_memcpy(afRxData, pkt->cmd.Data, pkt->cmd.DataLength);
    HalUARTWrite(UART0, pkt->cmd.Data, pkt->cmd.DataLength);
  }
}



afIncomingMSGPacket_t表示無線資料包,資料就放在cmd結構體中。


接收的大概過程:當終端模組傳送資料的時候,協調器模組底層接收到無線資料,會給我們應用層發一個AF_INCOMING_MSG_CMD的訊息
,我們可以在這個訊息裡面處理接收到的資料。


在APP init方法中對串列埠的初始化相關程式碼及變數:

halUARTCfg_t uartConfig;
uartConfig.configured           = TRUE;              // 2x30 don't care - see uart driver.
uartConfig.baudRate             = SERIAL_APP_BAUD;
uartConfig.flowControl          = FALSE;
uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver.
uartConfig.rx.maxBufSize        = SERIAL_APP_RX_SZ;  // 2x30 don't care - see uart driver.
uartConfig.tx.maxBufSize        = SERIAL_APP_TX_SZ;  // 2x30 don't care - see uart driver.
uartConfig.idleTimeout          = SERIAL_APP_IDLE;   // 2x30 don't care - see uart driver.
uartConfig.intEnable            = TRUE;              // 2x30 don't care - see uart driver.
uartConfig.callBackFunc         = SerialApp_CallBack;// 串列埠回撥函式
HalUARTOpen(UART0, &uartConfig);


#define UART0        0x00
#define SERIAL_APP_TX_MAX    20
static uint8  SerialApp_TxBuf[SERIAL_APP_TX_MAX+1];
static uint8  SerialApp_TxLen;
//串列埠回撥函式
static void SerialApp_CallBack(uint8 port, uint8 event)
{
  (void)port;
  if ((event&(HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT))&&!SerialApp_TxLen)
  {
    if (!SerialApp_TxLen && (SerialApp_TxLen = HalUARTRead(UART0, SerialApp_TxBuf, SERIAL_APP_TX_MAX))){
	   
	    for(uint8 index = 1;index<SerialApp_TxLen;index++)
        {
           printf("%X ",SerialApp_TxBuf[index]);
        }
		printf("\r\n");
        
    }
  }
}


重要概念說明:

端點(endPoint):
1,它是一個位元組(8個二進位制位)編號的,是資料接收和傳送的基本單元,在模組通訊的時候,傳送模組必須指定收發雙方的網路地址和端點(針對單播)。
2,端點要使用,必須要和某個模組的任務掛勾定義。因為協調器拿到資料以後,是通過傳送訊息給應用層的,應用層是通過任務來處理的。
(取資料的時候是根據任務來的)
  
 首先每一個端點可以看成是一個位元組數字編號的開有一個門的房間,資料最終的目標是進入到無線資料包指定的目標端點房間,而取無線資料
 這個相關的程式碼是在任務事件的處理函式裡,而TI協議棧有那麼多的任務事件處理函式,所以必須要指定在哪一個任務事件處理函式來取無
 線資料包裡面的資料!

3,一個端點只能掛勾在一個任務上,而一個任務可以掛鉤多個端點,且端點對所有任務是公用的,定義一個就少一個。
  假如一個端點如果掛鉤了兩個任務,那麼接收模組處理任務的時候,這個時候同一個端點有多個任務事件處理函式去處理,不合理!!!
  一個任務掛多個端點,接收模組僅僅是判斷到底該資料投遞到哪個端點。
  
端點就相當於一個房間編號(對應程式碼裡面的結構體),傳送資料的時候,需要指明資料從哪個房間出去(源端點),並將資料投遞哪個房間(目標端點)  

SimpleDescriptionFormat_t:
更加詳細的描述商戰的情況,就像描述一個房間裡面有多少人之類的訊息


端點的繫結最終要等afRegister()方法呼叫完成,才表示繫結完成

所以,資料包傳送出去以後,首先目標協調器模組的網路地址0x0000對上了,協調器可以拿到這個無線資料包在底層的任務,
判斷20號端點已經定義且繫結到了應用層的任務

簇(clusterID):(相當於房間裡面的具體的人)
相當於端點房間裡面的人,是接收最終的目標,這個東西是兩個位元組,在射頻傳送的時候,必須要指明要發到接模組哪個端點(哪個房間)、
哪個端點對應的哪個簇(房間裡的哪一個人),傳送模組不需要指定簇