一个ZigBee工程是怎么回事.docx
- 文档编号:30403127
- 上传时间:2023-08-14
- 格式:DOCX
- 页数:26
- 大小:51.48KB
一个ZigBee工程是怎么回事.docx
《一个ZigBee工程是怎么回事.docx》由会员分享,可在线阅读,更多相关《一个ZigBee工程是怎么回事.docx(26页珍藏版)》请在冰豆网上搜索。
一个ZigBee工程是怎么回事
一个ZigBee工程是怎么回事
ByHov
注:
本文为本人接触ZigBee后的一些见解,看起来可能会有点乱,建议大家自己看过例程后作参考之用。
这样看起来会容易点。
若本文中有不合理的地方,还望指点:
)
PartOne.写在前面
我们知道每个程序都是从main函数开始执行的,在ZigBee中也不例外。
在一个Zigbee工程中,程序从main执行,经过几个函数调用(一些系统功能的初始化,建议看一下从main函数到SampleApp_ProcessEvent函数的过程),程序最终来到了SampleApp_ProcessEvent函数,SampleApp_ProcessEvent(uint8task_id,uint16events)是一个颇为重要的函数,整个工程更像是围绕着这个函数运行。
可以先在实验例程上看一下这个函数是怎么定义的。
说白了,在这个函数里面用几个if语句,来处理所有事件。
比如:
if(events&SYS_EVENT_MSG)来处理系统事件,if(events&SAMPLEAPP_SEND_PERIODIC_MSG_EVT)是用户定义的事件,可以有多个。
接着,在这些if语句中有一个SWITCH,SWITCH里面有几个case。
通过一个SWITCH语句把所要处理的任务分成几个case来处理,在每个case里面调用相应的函数,我们可以通过定义这些函数执行我们想要的功能。
其实,这就是如何在Zigbee工程里面的添加我们所需的功能的解决思路,按流水线分类,一个一个处理、执行相应的代码。
是不是有点像大一时写的C语言程序?
if、Switch-case、函数调用…一个Zigbee工程就是这么简单,接下来以SampleApp例程进行讲解。
PartTwo.ZigBee工程的结构
1.预处理
1.1INCLUDE
这里主要要考虑的问题是我们自己写的C文件,当你在工程中的App目录下添加了xx.c,比如实现传感器数据的采集,那么就要记得在SampleApp.c上#include"xx.h"。
1.2变量定义
根据项目需要自行定义。
1.3结构体定义
1.3.1簇ID(这个结构体存在于每个Zigbee工程中,作为发送数据的标识符)
constcId_tSampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS]=
{
//标识符,重要,工程会根据标识符执行不同的操作。
SAMPLEAPP_PERIODIC_CLUSTERID,//标识符名称
SAMPLEAPP_FLASH_CLUSTERID//标识符名称
};
2.两个重要的系统函数
2.1SampleApp_Init函数
在SampleApp_Init函数里面主要写一些初始化代码。
比如要用到串口通讯,那么可以在这个函数里面添加相应的串口初始化代码,如下:
voidSampleApp_Init(uint8task_id)//初始化函数
{
·······
/*串口配置结构体*/
halUARTCfg_tuartConfig;
/*串口初始化*/
uartConfig.configured=TRUE;
uartConfig.baudRate=HAL_UART_BR_38400;//波特率设置为38400
uartConfig.flowControl=FALSE;
uartConfig.flowControlThreshold=64;
uartConfig.rx.maxBufSize=128;
uartConfig.tx.maxBufSize=128;
uartConfig.idleTimeout=6;
uartConfig.intEnable=TRUE;
uartConfig.callBackFunc=UART_CallBack;
//UART_CallBack是自己写的串口回调函数,当然也可以取其它名字
HalUARTOpen(0,&uartConfig);//启动串口
·······
}
2.2SampleApp_ProcessEvent函数
SampleApp_ProcessEvent是一个Zigbee工程中最重要的函数,它是一个事件处理函数,可分为两种事件:
系统事件和用户事件。
在这个函数里面我们用来处理各种各样的事件,比如,系统事件:
绑定请求、处理按键、接受空中发送过来的数据等等;用户事件:
串口发送数据、传感器数据的获取等等。
uint16SampleApp_ProcessEvent(uint8task_id,uint16events)
{
if(events&SYS_EVENT_MSG)//如果是系统事件
{
while(MSGpkt)
{
switch(MSGpkt->hdr.event)
{
caseKEY_CHANGE:
//如果有按键操作
//执行我们想要的操作,比如
SampleApp_HandleKeys(((keyChange_t*)MSGpkt)->state,((keyChange_t*)MSGpkt)->keys);//按键处理函数
break;
caseAF_INCOMING_MSG_CMD:
//如果接收到空中消息
//执行我们想要的操作,比如
SampleApp_MessageMSGCB(MSGpkt);//消息处理函数,接受到数据当然要处理数据了,这个函数在下面会提到
break;
caseZDO_STATE_CHANGE:
//如果设备状态发生改变
//执行我们想要的操作,不同的设备可以执行不同的事件
break;
default:
break;
}
return(events^SYS_EVENT_MSG);
}
if(events&SAMPLEAPP_SEND_PERIODIC_MSG_EVT)//如果是用户事件
{
Function();//执行我们想要的操作,比如传感器数据采集
osal_start_timerEx(SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT+(osal_rand()&0x00FF)));
//注意这里用osal_start_timerEx函数来定时执行事件,如果这个事件是传感器数据的采集,那么就会定时采集相关传感器的数据
return(events^SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
return0;
}
3.其他函数
3.1按键处理函数:
voidSampleApp_HandleKeys(uint8shift,uint8keys)
{
if(keys&HAL_KEY_SW_2)//当HAL_KEY_SW_2按键被按下
{
//执行我们想要的操作
}
}
3.3消息处理事件
voidSampleApp_MessageMSGCB(afIncomingMSGPacket_t*pkt)
{
uint16flashTime;
switch(pkt->clusterId)
{
//看到这个簇ID吗?
在前面我们自己定义的,当然你也可以改成任意名字,但是要和发送的簇ID相对应,这里是接受的簇ID。
如ID1…
//如果收到簇ID为SAMPLEAPP_PERIODIC_CLUSTERID的消息
caseSAMPLEAPP_PERIODIC_CLUSTERID:
//执行我们想要的操作,比如调用一个函数,在这个函数定义里面添加我们想要的功能代码,IO控制、串口发送这些
break;
//如果收到簇ID为SAMPLEAPP_FLASH_CLUSTERID:
的消息
caseSAMPLEAPP_FLASH_CLUSTERID:
//这里执行了一个闪灯的功能
flashTime=BUILD_UINT16(pkt->cmd.Data[1],pkt->cmd.Data[2]);
HalLedBlink(HAL_LED_4,4,50,(flashTime/4));
break;
}
}
3.4数据发送函数
通过这个函数把一个节点的数据通过ZigBee网络无线发送至另一个节点,重点关注clusterID、发送的东西、发送的东西的大小
下面这个数据发送函数的功能:
发送一个簇ID为SAMPLEAPP_SEND_DATA_PTOP_CLUSTERID,内容为NAME的消息。
voidSampleApp_SendPointToPointMessage(void)
{
……..//数据定义,比如NAME[5];
if(AF_DataRequest(&Point_To_Point_DstAddr,
&SampleApp_epDesc,
SAMPLEAPP_SEND_DATA_PTOP_CLUSTERID,
//簇ID,发送标识符
5,//数据长度
NAME,//数据数组
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS)==afStatus_SUCCESS)
{
}
else
{
//Erroroccurredinrequesttosend.
}
}
3.5自己定义的函数
可以根据工程的功能,参考实验来进行定义。
在前面我们一直提到不同的情况下执行不同的功能,那我们如何执行不同的功能呢?
答案就在这里,用一个函数把我们的功能代码封装起来,在用的时间直接调用函数就行了,简单方便。
例:
OPEN_FAN();//打开风扇,这个是自己定义的,方便调用
PartThree.写在后面
上面提到的都是在ZigBee工程中我们需要注意的东西,在我们以后要做项目的时候这些东西需要我们根据项目需求作相应的修改。
虽然一个ZigBee工程的代码不少,但是大多数都是固定的,不需要我们去解决,我们要解决的是在合适的地方添加我们的代码,利用修改例程来实现我们想要的功能。
在刚接触ZigBee协议栈的时候,建议大家理解ZigBee工程中的主文件的执行流程,看懂主文件的代码是什么意思,看懂后基本就可以在例程上修改代码实现我们自己的项目了。
附:
SerialApp工程的详细注释(original)
SerialApp实现的是ZigBee协议栈中的串口通讯
/*******************************总结********************************
********************************************************************
一、在这个实验中,先绑定两个ZDO设备,组成ZigBee网络;
二、两个设备绑定后,串口通信的发送接受流程分成了九步(如注释)
第一步:
SerialApp_CallBack(),当串口有数据时此函数即被调用。
第二步:
在SerialApp_CallBack()调用SerialApp_Send(void),这是一个消息发送函数,实现将数据发送到ZigBee网络中的其他节点。
第三步:
在SerialApp_Send(void)中,通过AF_DataRequest()函数,将数据从空中发送出去,簇ID为SERIALAPP_CLUSTERID1
第四步:
SerialApp_ProcessMSGCmd()对从空中捕获到的信号进行处理,接收到发送过来的信息簇ID为SERIALAPP_CLUSTERID1
第五步:
caseSERIALAPP_CLUSTERID1:
HalUARTWrite通过串口发送数据到PC机
第六步:
收到数据后,向节点1发送一个响应事件SERIALAPP_RESP_EVT,跳到SerialApp_ProcessEvent()执行
第七步:
if(events&SERIALAPP_RESP_EVT)//串口响应事件,表示成功接受来自节点1的数据,此时调用SerialApp_Resp()
第八步:
在SerialApp_Resp()中,通过AF_DataRequest函数,将接收成功响应从空中发送出去,簇ID为SERIALAPP_CLUSTERID2
第九步:
同第四步,接收到发送过来的信息簇ID为SERIALAPP_CLUSTERID2,所以不再继续发送
以上为该例程的功能流程。
*******************************************************************************************************************************************************/
/*---------------------------------------------------------
预处理
这里可以参照基础实验,直接在自己的程序中复制。
---------------------------------------------------------*/
#include"AF.h"
#include"OnBoard.h"
#include"OSAL_Tasks.h"
#include"SerialApp.h"
#include"ZDApp.h"
#include"ZDObject.h"
#include"ZDProfile.h"
#include"hal_drivers.h"
#include"hal_key.h"
#ifdefined(LCD_SUPPORTED)
#include"hal_lcd.h"
#endif
#include"hal_led.h"
#include"hal_uart.h"
#if!
defined(SERIAL_APP_PORT)
#defineSERIAL_APP_PORT0
#endif
#if!
defined(SERIAL_APP_BAUD)
#defineSERIAL_APP_BAUDHAL_UART_BR_38400
//#defineSERIAL_APP_BAUDHAL_UART_BR_115200
#endif
//WhentheRxbufspaceislessthanthisthreshold,invoketheRxcallback.
#if!
defined(SERIAL_APP_THRESH)
#defineSERIAL_APP_THRESH64
#endif
#if!
defined(SERIAL_APP_RX_SZ)
#defineSERIAL_APP_RX_SZ128
#endif
#if!
defined(SERIAL_APP_TX_SZ)
#defineSERIAL_APP_TX_SZ128
#endif
//MillisecsofidletimeafterabyteisreceivedbeforeinvokingRxcallback.
#if!
defined(SERIAL_APP_IDLE)
#defineSERIAL_APP_IDLE6
#endif
//LoopbackRxbytestoTxforthroughputtesting.
#if!
defined(SERIAL_APP_LOOPBACK)
#defineSERIAL_APP_LOOPBACKFALSE
#endif
//ThisisthemaxbytecountperOTAmessage.
#if!
defined(SERIAL_APP_TX_MAX)
#defineSERIAL_APP_TX_MAX80
#endif
#defineSERIAL_APP_RSP_CNT4
/*-----------------------------------------------------
程序中的结构体
-----------------------------------------------------*/
//结构体:
函数所要用到的簇ID
constcId_tSerialApp_ClusterList[SERIALAPP_MAX_CLUSTERS]=
{
SERIALAPP_CLUSTERID1,
SERIALAPP_CLUSTERID2
};
//结构体:
SerialApp_SimpleDesc
constSimpleDescriptionFormat_tSerialApp_SimpleDesc=
{
SERIALAPP_ENDPOINT,//intEndpoint;
SERIALAPP_PROFID,//uint16AppProfId[2];
SERIALAPP_DEVICEID,//uint16AppDeviceId[2];
SERIALAPP_DEVICE_VERSION,//intAppDevVer:
4;
SERIALAPP_FLAGS,//intAppFlags:
4;
SERIALAPP_MAX_CLUSTERS,//byteAppNumInClusters;
(cId_t*)SerialApp_ClusterList,//byte*pAppInClusterList;
SERIALAPP_MAX_CLUSTERS,//byteAppNumOutClusters;
(cId_t*)SerialApp_ClusterList//byte*pAppOutClusterList;
};
//结构体:
SerialApp_epDesc
constendPointDesc_tSerialApp_epDesc=
{
SERIALAPP_ENDPOINT,
&SerialApp_TaskID,
(SimpleDescriptionFormat_t*)&SerialApp_SimpleDesc,
noLatencyReqs
};
/*---------------------------------------------------------
变量定义
---------------------------------------------------------*/
uint8SerialApp_TaskID;//TaskIDforinternaltask/eventprocessing.
staticuint8SerialApp_MsgID;
staticafAddrType_tSerialApp_TxAddr;
staticuint8SerialApp_TxSeq;
staticuint8SerialApp_TxBuf[SERIAL_APP_TX_MAX+1];
staticuint8SerialApp_TxLen;
staticafAddrType_tSerialApp_RxAddr;
staticuint8SerialApp_RxSeq;
staticuint8SerialApp_RspBuf[SERIAL_APP_RSP_CNT];
/*---------------------------------------------------------
函数声明
---------------------------------------------------------*/
staticvoidSerialApp_ProcessZDOMsgs(zdoIncomingMsg_t*inMsg);
staticvoidSerialApp_HandleKeys(uint8shift,uint8keys);
staticvoidSerialApp_ProcessMSGCmd(afIncomingMSGPacket_t*pkt);
staticvoidSerialApp_Send(void);
staticvoidSerialApp_Resp(void);
staticvoidSerialApp_CallBack(uint8port,uint8event);
/*----------------------------------------------------------
函数定义
----------------------------------------------------------*/
voidSerialApp_Init(uint8task_id)//初始化函数
{
SerialApp_TaskID=task_id;//任务ID
SerialApp_RxSeq=0xC3;//接收序列号
afRegister((endPointDesc_t*)&SerialApp_epDesc);//注册端口描述符
RegisterForKeys(task_id);//注册按键事件
halUARTCfg_tuartConfig;//串口配置结构体
uartConfig.configured=TRUE;//don'tcare
uartConfig.baudRate=SERIAL_APP_BAUD;//波特率
uartConfig.flowControl=TRUE;//don'tcare
uartConfig.flowControlThreshold=SERIAL_APP_THRESH;//don'tcare
uartConfig.rx.maxBufSize=SERIAL_APP_RX_SZ;//最大接收量
uartConfig.tx.maxBufSize=SERIAL_APP_TX_SZ;//最大发送量
uartConfig.idleTimeout=SERIAL_APP_IDLE;//don'tcare
uartConfig.intEnable=TRUE;//don'tcare
//SerialApp_CallBack:
当串口接收到数据后会自动执行这个函数
uartConfig.callBackFunc=SerialApp_CallBack;//接收回调函数
HalUARTOpen(SERIAL_APP_PORT,&uartCon
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 一个 ZigBee 工程 是怎么回事