/***考试周,我抓紧把ZigBee的记录补一下,其实早就做了,被学院的事情耽搁了,博客一直没写,这两天给他补上************/
前言: Zigbee 的通讯方式主要有三种点播、组播、广播。点播,顾名思义就是点对点通信,也就是 2 个设备之间的通讯,不容许有第三个设备收到信息;组播,就是把网络中的节点分组,每一个组员发出的信息只有相同组号的组员才能收到。广播,最广泛的也就是 1 个设备上发出的信息所有设备都能接收到。这也是 ZigBee 通信的基本方式。
点播(点对点通讯)
点播描述的就是网络中 2 个节点相互通信的过程。确定通信对象的就是节点的 16bit 短地址。
首先,在AF.H文件中,可以看到这段代码
1 typedef enum 2 { 3 afAddrNotPresent = AddrNotPresent, 4 afAddr16Bit = Addr16Bit, 5 afAddr64Bit = Addr64Bit, 6 afAddrGroup = AddrGroup, 7 afAddrBroadcast = AddrBroadcast 8 } afAddrMode_t;
该类型是一个枚举类型:
当 addrMode= Addr16Bit 时,对应点播方式;
当 addrMode= AddrGroup 时,对应组播方式;
当 addrMode= AddrBroadcast 时,对应广播方式;
打开SampleApp.c加入点对点通信定义
afAddrType_t Point_To_Point_DstAddr;//点对点通信定义 //go to definition of afAddrType_t 可以找到刚才的枚举内容
对 Point_To_Point_DstAddr 一些参数进行配置 加入如下代码
// 点对点通讯定义 Point_To_Point_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//点播 Point_To_Point_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; Point_To_Point_DstAddr.addr.shortAddr = 0x0000; //发给协调器
第三行的意思是点播的发送对象是 0x0000,也就是协调器的地址。节点和协调器点对点通讯。
添加自己的点对点发送函数,在 SampleAPP.c 最后加入下面代码
void SampleApp_SendPointToPointMessage( void ) { uint8 data[]="Hello Tian!"; if ( AF_DataRequest( &Point_To_Point_DstAddr, &SampleApp_epDesc, SAMPLEAPP_POINT_TO_POINT_CLUSTERID, sizeof(data), data, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } }
/***********************添加完之后记得在SampleApp.c文件开头添加函数声明****************/
加入 SAMPLEAPP_POINT_TO_POINT_CLUSTERID 的定义如所示:
#define SAMPLEAPP_POINT_TO_POINT_CLUSTERID 3//传输编号
添加接收函数
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; switch ( pkt->clusterId ) { case SAMPLEAPP_POINT_TO_POINT_CLUSTERID: HalUARTWrite(0,"I get data\n",11);//用于提示有数据 HalUARTWrite(0, &pkt->cmd.Data[0],10); //打印收到数据 HalUARTWrite(0,"\n",1); //回车换行,便于观察 break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); break; } }
注册周期发送事件
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ( //(SampleApp_NwkState == DEV_ZB_COORD)|| //协调器不给自己点播 (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) ) { // Start sending the periodic message in a regular interval. osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); } else { // Device is no longer in the network } /*由于协调器不允许给自己点播,故周期性点播初始化时协调器不能初始化*/
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { SampleApp_SendPointToPointMessage();//周期性发送函数 // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); // return unprocessed events return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); }
将修改后的程序分别以协调器、路由器、终端的方式下载到 3 个节点设备中,连接串口。可以看到只有协调器在一个周期内收到信息。也就是说路由器和终端均与地址为 0x00(协调器)的设备通信,不与其他设备通信。实现点对点传输。