目录
1.基础概念
2.Zigbee协议栈工作流程
3。代码讲解
(这个实验当中我们只用到协调器以及终端)。
协议栈中很多东西已经帮我们写好,我们以后使用仅仅需要修改增加一些内容。因此代码不需要全部都懂。(初学者不要尝试将所有的代码都看懂,循序渐进。)
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
//这一部分为新加进来的代码
//------------------------配置串口---------------------------------
MT_UartInit(); //串口初始化
MT_UartRegisterTaskID(task_id); //注册串口任务
HalUARTWrite(0,"UartInit OK\n", sizeof("UartInit OK\n"));
//-----------------------------------------------------------------
#if defined ( BUILD_ALL_DEVICES )
if ( readCoordinatorJumper() )
zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
else
zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif // BUILD_ALL_DEVICES
#if defined ( HOLD_AUTO_START )
ZDOInitDevice(0);
#endif
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//广播模式
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;//广播地址
/*//组播的代码
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;*/
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &SampleApp_epDesc );
RegisterForKeys( SampleApp_TaskID );
/*//组播的代码
// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0001;
osal_memcpy( SampleApp_Group.name, "Group 1", 7 );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
*/
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
#endif
}
其中 MT_UartInit()在目录中MT文件中的MT_UART.c的文件当中,为串口的初始化。
这个初始化的函数当中,我们需要将波特率设置好,流控制关闭,其他的可以不用管。
然后我们就可以调用HalUARTWrite(0,"UartInit OK\n", sizeof("UartInit OK\n"))来发送初始化完成的提示。然后,如上面的代码块一样,将组播的代码注释掉。
接下来,我们进入到uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )当中。
//在这个函数当中完成对事件的处理
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case KEY_CHANGE:
SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
break;
case AF_INCOMING_MSG_CMD://接收到数据包就进行处理
SampleApp_MessageMSGCB( MSGpkt );
break;
case ZDO_STATE_CHANGE://协调器状态改变就进入下面的函数,协调器刚建立网络就会进去
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
}
break;
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt );
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
}
return (events ^ SYS_EVENT_MSG);
}
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )//上面有出现哦,协调器状态改变
{
SampleApp_SendPeriodicMessage();//协调器发送数据
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
return 0;
}
接下来进入SampleApp_SendPeriodicMessage()函数当中。
void SampleApp_SendPeriodicMessage( void )
{//联网后进入这个函数
uint8 *buff=NULL;
if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR)//判断Zigbee的逻辑类型,如果是协调器
{
buff="I am coordinator device\r\n";
}
else if(zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE)//如果是终端
{
buff="I am endpoint device\r\n";
}
// AF_DataRequest()这个函数是真正发送数据的函数,我们需要将第三第四个参数该为数组的大小,以及数组的内容,然后就可以发送了。
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
strlen(buff),//传输数据的字节大小
buff,//传输数据
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
}
}
数据发送完了,当接受到数据包后,MSGpkt->hdr.event=AF_INCOMING_MSG_CMD,接下来,我们就要进入SampleApp_MessageMSGCB( MSGpkt )当中。
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )//无线数据包接收到之后
{
uint16 flashTime;
switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID://接收到该命令后执行的代码
HalUARTWrite(0,(pkt->cmd).Data,(pkt->cmd).DataLength);//将接受到的数据打印到串口中
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;
}
}
1.注意协调器与终端的烧录,需要分开烧录。可由上图所示更改。
2.以下问题为版本不兼容
以及一堆 Undefined external "?V1" referred in AF类似的,都是由于版本不兼容的原因。解决方法:
;----------------------------------------------------------------;
; Virtual registers ;
; ================= ;
; Below is some segment needed for the IAR ICC C/EC++ compiler ;
; ;
; BREG : A segment for 8 bit registers for use by the compiler. ;
; ?B0 is the first register. ;
; VREG : Segment that holds up to 32 virtual registers for ;
; use by the compiler. ?V0 is the first register. ;
; PSP : Segment containing the PDATA stack pointer (?PSP) ;
; XSP : Segment containing the XDATA stack pointer (?XSP) ;
; ;
;----------------------------------------------------------------;
;----------------------------------------------------------------;
PROGRAM VIRTUAL_REGISTERS
PUBLIC ?B0
PUBLIC ?V0
PUBLIC ?V1
PUBLIC ?V2
PUBLIC ?V3
PUBLIC ?V4
PUBLIC ?V5
PUBLIC ?V6
PUBLIC ?V7
PUBLIC ?V8
PUBLIC ?V9
PUBLIC ?V10
PUBLIC ?V11
PUBLIC ?V12
PUBLIC ?V13
PUBLIC ?V14
PUBLIC ?V15
PUBLIC ?V16
PUBLIC ?V17
PUBLIC ?V18
PUBLIC ?V19
PUBLIC ?V20
PUBLIC ?V21
PUBLIC ?V22
PUBLIC ?V23
PUBLIC ?V24
PUBLIC ?V25
PUBLIC ?V26
PUBLIC ?V27
PUBLIC ?V28
PUBLIC ?V29
PUBLIC ?V30
PUBLIC ?V31
PUBLIC ?PSP
PUBLIC ?XSP
RSEG BREG:BIT:NOROOT
?B0:
DS 8
RSEG VREG:DATA:NOROOT
?V0:
DS 1
?V1:
DS 1
?V2:
DS 1
?V3:
DS 1
?V4:
DS 1
?V5:
DS 1
?V6:
DS 1
?V7:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V7
?V8:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V8
?V9:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V9
?V10:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V10
?V11:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V11
?V12:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V12
?V13:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V13
?V14:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V14
?V15:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V15
?V16:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V16
?V17:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V17
?V18:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V18
?V19:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V19
?V20:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V20
?V21:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V21
?V22:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V22
?V23:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V23
?V24:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V24
?V25:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V25
?V26:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V26
?V27:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V27
?V28:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V28
?V29:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V29
?V30:
DS 1
RSEG VREG:DATA:NOROOT
REQUIRE ?V30
?V31:
DS 1
RSEG PSP:DATA:NOROOT
EXTERN ?RESET_PSP
REQUIRE ?RESET_PSP
?PSP:
DS 1
RSEG XSP:DATA:NOROOT
EXTERN ?RESET_XSP
REQUIRE ?RESET_XSP
?XSP:
DS 2
ENDMOD ; VIRTUAL_REGISTERS
END