ZigBee初探
1、环境
硬件:
开发板:CC2530-256
端口调试助手:CCDebuger
软件:
集成开发环境:IAR Embedded Workbench IDE 8051
串口调试软件:SSCOM5.12.1
协议栈:Z-stack2.4
IAR Workbench:https://www.iar.com/iar-embedded-workbench/#!?architecture=8051
Z-Stack2.4:https://download.csdn.net/download/qq_30033537/13631492
更新的Z-stack:Z-STACK A fully compliant ZigBee 3.x solution: Z-Stack | TI.com
以上软件的安装不一一介绍,IAR Workbench需要版权,自行百度安装。
2、Z-Stack
将Z-stack2.4下载之后解压。
2.1、目录介绍
1、Components
该目录只要是存放了协议栈的程序文件,如hal、mac、osal等。
在一个标准Z-stack我们可以找到对应,如下图:
2、Documents
顾名思义,就是说明文档存放的目录。存放了TI提供的大量的说明文件,想要深入学习Z-stack可以通过这个目录学习,但是都是英文文档。
3、Tools
一些工具,我们不重点管这个
4、Project【重要】
这对我们来说是最重要的一个目录,里面存放了我们开发用的项目。
并且,我们开发的项目必须放到该目录下才能与Components目录下的协议栈文件关联使用,否则在IAR IDE编译时会找不到文件。
对于初学者我们重点学习Samples目录下的文件
2.2、快速开发
接下来,我们重点关注Samples下的项目文件,通过GenericApp快速示例程序,我们快速搭建一个入门案例。
1、进入GenericApp目录
2、进入CC2530DB
3、eww项目文件
4、导入项目
5、项目结构介绍
我们重点关注的是App部分,下面我们修改示例代码实现第一个程序。
GenericApp.h
该文件我们展示不需要修改,里面定义了一些宏定义以及需要的头文件
#ifndef GENERICAPP_H
#define GENERICAPP_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ZComDef.h"
#define GENERICAPP_ENDPOINT 10
#define GENERICAPP_PROFID 0x0F04
#define GENERICAPP_DEVICEID 0x0001
#define GENERICAPP_DEVICE_VERSION 0
#define GENERICAPP_FLAGS 0
#define GENERICAPP_MAX_CLUSTERS 1
#define GENERICAPP_CLUSTERID 1
#define GENERICAPP_SEND_MSG_TIMEOUT 5000 // Every 5 seconds
#define GENERICAPP_SEND_MSG_EVT 0x0001
extern void GenericApp_Init( byte task_id );
extern UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events );
#ifdef __cplusplus
}
#endif
#endif
GenericApp.c
该文件是我们重点的编码对象,里面集成了:
设备描述、设备初始化、消息处理等
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "GenericApp.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID
};
// 简单设备描述符:定义了设备ID等信息
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT, // int Endpoint;
GENERICAPP_PROFID, // uint16 AppProfId[2];
GENERICAPP_DEVICEID, // uint16 AppDeviceId[2];
GENERICAPP_DEVICE_VERSION, // int AppDevVer:4;
GENERICAPP_FLAGS, // int AppFlags:4;
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList, // byte *pAppInClusterList;
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList // byte *pAppInClusterList;
};
endPointDesc_t GenericApp_epDesc;
byte GenericApp_TaskID;
devStates_t GenericApp_NwkState;
byte GenericApp_TransID;
afAddrType_t GenericApp_DstAddr;
// 函数头
void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
void GenericApp_HandleKeys( byte shift, byte keys );
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void GenericApp_SendTheMessage( void );
// 任务初始化函数
void GenericApp_Init( byte task_id )
{
GenericApp_TaskID = task_id; // 任务优先级
GenericApp_NwkState = DEV_INIT;
GenericApp_TransID = 0; // 数据包序列号
GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent; // 发送模式:点播
GenericApp_DstAddr.endPoint = 0;
GenericApp_DstAddr.addr.shortAddr = 0;
// 下面是设备描述符的初始化
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
// 将节点描述符注册以便于OSAL为其提供服务
afRegister( &GenericApp_epDesc );
}
// 事件处理函数
// 在该函数中我们通过osal_msg_receive( GenericApp_TaskID )函数拿到发生的事件
// 通过判断事件发生的类型:如ZDO_STATE_CHANGE,状态改变类型
// 实现不同逻辑:如亮灯:HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
afIncomingMSGPacket_t *MSGpkt;
afDataConfirm_t *afDataConfirm;
byte sentEP;
ZStatus_t sentStatus;
byte sentTransID;
(void)task_id;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
// 设备状态改变处理逻辑:如上电等
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (GenericApp_NwkState == DEV_ZB_COORD)
|| (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE) )
{
// 亮灯
HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
}
break;
// 其他处理逻辑
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt );
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
return (events ^ SYS_EVENT_MSG);
}
if ( events & GENERICAPP_SEND_MSG_EVT )
{
GenericApp_SendTheMessage();
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
return 0;
}
对于提供的示例程序,我们进行精简,得到以上的程序
以上程序实现了开机亮灯的效果。
6、编译运行
通过CCDebuger将CC2530连接到电脑,在项目中依次编译、连接、运行