【配套源码、文档、软件、硬件等资源,入口见文末】
上一节中我们讲述了如何对ZigBee网络进行基本的网络参数设置,以及无线自组网。自组网完成后,ZigBee网络就算是形成了。此时,我们就可以开始无线通信了!
本节中,我们将从以下2部分详细讲述第一种最基本也是最重要的无线通信方式,即单播通信的第一种方式——16位地址模式。
一、无线通信方式简介
二、16位地址单播通信
一、无线通信方式简介
在AF.h文件中,有如下一段定义:
可见,无线通信的地址模式总共有5种,分别解释如下:typedef enum { afAddrNotPresent = AddrNotPresent, afAddr16Bit = Addr16Bit, afAddr64Bit = Addr64Bit, afAddrGroup = AddrGroup, afAddrBroadcast = AddrBroadcast } afAddrMode_t;
AddrNotPresent——绑定通信
Addr16Bit——单播通信(16位地址方式)
Addr64Bit——单播通信(64位地址方式)
AddrGroup——组播通信
AddrBroadcast——广播通信
后面,我们将按难易顺序依次讲解并实验验证:单播、广播、组播和绑定。
二、单播通信(16位地址方式)
为了实现无线通信,我们需要增加目标地址(ProjectApp_DstAddr)、无线数据包计数器(ProjectApp_TransID)、单播发送函数、无线数据包解析函数:
1、16位地址单播发送函数,定义如下:...... afAddrType_t ProjectApp_DstAddr; byte ProjectApp_TransID; // This is the unique message ID (counter) ...... static void ProjectApp_SendUnicast16( void ); static void ProjectApp_MessageMSGCB( afIncomingMSGPacket_t *pckt ); ......
发送函数中 最重要的是 目的地址(ProjectApp_DstAddr)和 发送的数据(theMessageData[ ]),尤其是目的地址这个 结构体 ,必须指定代码中所示的三个参数:第一个参数指定无线发送模式;第二个参数指定目的端点;第三个参数指定目的设备的短地址;然后就可以调用Z-Stack中AF层的库函数AF_DataRequest( )进行无线发送了!static void ProjectApp_SendUnicast16( void ) { char theMessageData[ ] = "Unicast data 16\r\n"; ProjectApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; ProjectApp_DstAddr.endPoint = PROJECTAPP_ENDPOINT; ProjectApp_DstAddr.addr.shortAddr = NWK_PAN_COORD_ADDR;//NWK_BROADCAST_SHORTADDR_DEVALL; AF_DataRequest( &ProjectApp_DstAddr, &ProjectApp_epDesc, PROJECTAPP_CLUSTERID, (byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &ProjectApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); }
2、无线数据包解析函数,定义如下:
这边着重关心一下ProjectApp_MessageMSGCB( )函数的参数——afIncomingMSGPacket_t结构体类型的指针,该结构体的定义如下:static void ProjectApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { switch ( pkt->clusterId ) { case PROJECTAPP_CLUSTERID: HalLedSet(HAL_LED_1,HAL_LED_MODE_TOGGLE); printf("%s",pkt->cmd.Data); break; } }
该结构体的最后一个元素便是无线接收到的数据包,也是结构体类型,其定义如下: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 TransSeqNumber; uint16 DataLength; // Number of bytes in TransData uint8 *Data; } afMSGCommandFormat_t;
所以我们无线数据包解析函数ProjectApp_MessageMSGCB( )中的下面这一行代码,就可以实现将收到的无线数据打印出来!printf("%s",pkt->cmd.Data);
3、实验验证
无线发送函数和无线接收解析函数都编写好了,最后需要做的就是在对应位置调用这两个函数即可;
何时调用无线发送呢?我们可以通过按键触发,也可以通过串口指令触发,这边我们就选择一个简单的方式,用按键来触发;
具体实现功能:一个ZigBee设备上按键按下,另一个ZigBee上面上的LED1状态取反,同时串口打印出接收到的无线数据包;
(1)调用单播发送函数
static void ProjectApp_HandleKeys( uint8 shift, uint8 keys ) { ...... if ( keys & HAL_KEY_SW_1 ) { // HalLedSet(HAL_LED_1,HAL_LED_MODE_TOGGLE); ProjectApp_SendUnicast16(); } ...... }
(2)调用无线数据包解析函数
uint16 ProjectApp_ProcessEvent( uint8 task_id, uint16 events ) { ...... if ( events & SYS_EVENT_MSG ) { ...... switch ( MSGpkt->hdr.event ) { case AF_INCOMING_MSG_CMD: ProjectApp_MessageMSGCB( MSGpkt ); break; ...... } ...... } return 0;// Discard unknown events }
(3)编译下载
在IAR左侧的Workspace中,一个ZigBee设备选择CoordinatorEB编译下载,另一个ZigBee设备选择RouterEB或EndDeviceEB编译下载,如下图所示进行选择;
(4)实验现象
两个ZigBee设备分别上电后,会发现,无论按下哪个ZigBee设备上的KEY1,协调器上的LED1状态都会取反,同时协调器的串口每次都会打印出“Unicast data 16”;
【配套源码、文档、软件、硬件等资源,入口见文末】