zigbee Zstack协议栈
# 一、Zstack协议栈概述## 什么是Zstack协议栈
为了使Zigbee的开发更加简单高效,TI公司推出了基于cc2530芯片的协议栈Z-STACK.协议栈的实质就是能实现各个功能的实例框架代码,我们想要实现自己的功能程序,只需要在协议栈的基础上修改或添加即可。
- Z-STACK的发展
- 由0.01版本 到 1.5.1a..
- mesh: 之前的升级版本
- HA:家庭自动化(智能家居)
- SE:智能能源
....他们的区别是应用部分不同(初学者建议用早期的版本)
# 二、Zstack协议栈结构
Z-Stack协议栈符合ZigBee协议,由物理层、MAC层、网络层和应用层组成,由于Z-Stack协议栈是一个半开源的协议栈,MAC层和网络层的部分源代码是非开源的,因此我们学习的开源部分,主要包括main函数、APP层、ZDO层、NWK层和HAL层。
## 1.工程目录结构
!(https://i.loli.net/2021/05/26/yardNfnAIW6GRzV.png)
**APP**: 应用层目录, 这是用户创建各种不同工程的区域, 在这个目录中包含了应用层的内容和这个项目的主要内容, 在协议栈里面一般是以操作系统的任务实现的。
**HAL**: 硬件层目录, 包含有与硬件相关的配置和驱动及操作函数。
**MAC**: MAC 层目录, 包含了 MAC 层的参数配置文件及其 MAC 的 LIB 库的函数接口文件。
**MT**: 监控调试层, 主要用于调试目的, 即实现通过串口调试各层, 与各层进行直接交互。
**NWK**: 网络层目录, 含网络层配置参数文件及网络层库的函数接口文件, APS 层库的函数接口。
**OSAL**: 协议栈的操作系统。
**Profile**: AF 层目录, 包含 AF 层处理函数文件。
**Security**: 安全层目录, 安全层处理函数接口文件, 比如加密函数等。
**Services**: 地址处理函数目录, 包括着地址模式的定义及地址处理函数。
**Tools**: 工程配置目录, 包括空间划分及 ZStack 相关配置信息。
**ZDO**: ZDO 目录。
**ZMac**: MAC 层目录, 包括 MAC 层参数配置及 MAC 层 LIB 库函数回调处理函数。
**ZMain**: 主函数目录, 包括入口函数 main( ) 及硬件配置文件。
**Output**: 输出文件目录, 这个 EW8051 IDE 自动生成的。
## 2.main函数解析
```c
int main( void )
{
/* 关闭所有中断*/
osal_int_disable( INTS_ALL );
/* 初始化硬件设备*/
HAL_BOARD_INIT();
/*电源检测*/
zmain_vdd_check();
/*初始化I/O*/
InitBoard( OB_COLD );
/*初始化硬件抽象层HAL驱动*/
HalDriverInit();
/*初始化NV*/
osal_nv_init( NULL );
/*初始化 MAC*/
ZMacInit();
/*确定64位IEEE地址*/
zmain_ext_addr();
/*初始化NV向量*/
zgInit();
```
```c
#ifndef NONWK
/* AF层初始化/
afInit();
#endif
/*初始化任务*/
osal_init_system();
/*开启中断*/
osal_int_enable( INTS_ALL );
/*硬件I/O初始化完毕*/
InitBoard( OB_READY );
zmain_dev_info();
/* 如果定义了LCD,初始化LCD */
#ifdef LCD_SUPPORTED
zmain_lcd_init();
#endif
#ifdef WDT_IN_PM1
/* 如果定义了看门狗,看门狗使能 */
WatchDogEnable( WDTIMX );
#endif
/*操作系统运行*/
osal_start_system();
return 0;
}
```
**osal_int_disable()**
```c
uint8 osal_int_disable( uint8 interrupt_id )
{
/*判断ID是否为中断ID*/
if ( interrupt_id == INTS_ALL )
{
/*关掉所有中断*/
HAL_DISABLE_INTERRUPTS();
/*中断关闭成功,返回SUCCESS */
return ( SUCCESS );
}
else
{
/*如果ID与INST_ALL不同,返回
INVALID_INTERRUPT_ID*/
return ( INVALID_INTERRUPT_ID );
}
}
```
## 3.APP层解析
OSAL_SampleApp.c中包含osalInitTasks()与taskArr[]。
**osalInitTasks()函数主要功能是为任务分配空间**
```c
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID++ );
nwk_init( taskID++ );
Hal_Init( taskID++ );
#if defined( MT_TASK )
MT_TaskInit( taskID++ );
#endif
APS_Init( taskID++ );
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_Init( taskID++ );
#endif
ZDApp_Init( taskID++ );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_Init( taskID++ );
#endif
SampleApp_Init( taskID );
```
!(https://i.loli.net/2021/05/26/OtP5B8fUnWrgd6v.png)
**OSAL_SampleApp.c**
**tasksArr中存放了事件处理回调函数**
```c
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SampleApp_ProcessEvent
};
```
!(https://i.loli.net/2021/05/26/rsQCP2c8fxyIqGb.png)
**Z-Stack协议栈的APP层主要功能是实现用户定义的事件,APP层由5个文件组成**
!(https://i.loli.net/2021/05/26/k3UGemgx1C9XwiV.png)
> SamplApp.c文件主要有两个功能:
> (1)对应用层用户定义的任务
> (2)进行初始化;调用事件处理函数。
- 用户任务初始化函数SampleApp_Init()
- 任务处理函数SampleApp_ProcessEvent()
- 按键处理事件SampleApp_HandleKeys()
- 数据发送函数SampleApp_SendFlashMessage()
- 数据发送函数SampleApp_SendPeriodicMessage()
- 数据接收函数SampleApp_MessageMSGCB()
**SampleApp_Init()**
```c
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
#if defined ( BUILD_ALL_DEVICES )
if ( readCoordinatorJumper() )
zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
else
zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif
#if defined ( HOLD_AUTO_START )
ZDOInitDevice(0);
#endif
/*SampleApp_Periodic_DstAddr地址模式初始化为广播地址*/
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
/* SampleApp_Periodic_DstAddr端点初始化*/
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
```
!(https://i.loli.net/2021/05/26/tds2QgvXJ3oVEZN.png)
**SampleApp_Init()**
```c
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 );
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
}
```
!(https://i.loli.net/2021/05/26/6sLdxJYnTbaSX7l.png)
**SampleApp_ProcessEvent()**
!(https://i.loli.net/2021/05/26/51wDP3WtGNag4bl.png)
**SampleApp_ProcessEvent()**
!(https://i.loli.net/2021/05/26/6zkNFOLaug9Emrw.png)
**SampleApp_HandleKeys()**
!(https://i.loli.net/2021/05/26/7TjwEdWIztmGA8i.png)
**SampleApp_MessageMSGCB()**
SampleApp_MessageMSGCB()函数主要实现数据接收功能,数据的接收通过判断簇ID来
与发送端发送的数据进行匹配。
!(https://i.loli.net/2021/05/26/NhZEzC1kVlR6IoK.png)
**SampleApp_SendPeriodicMessage()**
SampleApp_SendPeriodicMessage()函数主要功能是实现周期性数据的发送,通过调用
AF_DataRequest()函数进行数据的发送。
!(https://i.loli.net/2021/05/26/Py9Q5Wf8MlFbAZp.png)
**SampleApp.h**
!(https://i.loli.net/2021/05/26/1udrm6CODpyFgk4.png)
## 4.ZDO层解析
**目录结构**
!(https://i.loli.net/2021/05/26/GDjxraLHCcnSbzU.png)
ZDApp_Init()函数:初始化ZDO网络设备短地址;获得64位IEEE地址信息;ZDO层初始化;网络设备启动。
## 5.NWK层解析
### **目录结构**
!(https://raw.githubusercontent.com/Editblog/PicGo/main/img/20210527185136.png)
### **网络拓扑结构**
```c
/*星型网络*/
#define NWK_MODE_STAR 0
/*树型网络*/
#define NWK_MODE_TREE 1
/*网状网络*/
#define NWK_MODE_MESH 2
```
### **网络参数设置**
```c
/*协议栈模式参数*/#define NETWORK_SPECIFIC 0#define HOME_CONTROLS 1#define ZIGBEEPRO_PROFILE 2#define GENERIC_STAR 3#define GENERIC_TREE 4/*信道设置*/#define MAX_CHANNELS_868MHZ 0x00000001#define MAX_CHANNELS_915MHZ 0x000007FE#define MAX_CHANNELS_24GHZ 0x07FFF800
```
## 6.HAL层解析
!(https://raw.githubusercontent.com/Editblog/PicGo/main/img/20210527185224.png)
```c
HAL目录Common:实现了硬件初始化函数Hal_Init()、硬件抽象层驱动初始化HalDriverInit ()函数和硬件抽象层事件处理函数Hal_ProcessEvent();Include:中主要包含了硬件资源的定义与函数声明;Target:主要为LED等硬件资源进行配置、实现硬件资源的实现函数;
```
Hal_Init()函数主要为硬件抽象层注册任务ID
```c
void Hal_Init( uint8 task_id ){ /* 注册任务 ID */ Hal_TaskID = task_id;}
```
HalDriverInit()函数主要实现硬件资源的初始化
```c
void HalDriverInit (void){/*定时器初始化*/#if (defined HAL_TIMER) && (HAL_TIMER == TRUE) HalTimerInit();#endif/*ADC初始化*/#if (defined HAL_ADC) && (HAL_ADC == TRUE) HalAdcInit();#endif/*DMA初始化*/#if (defined HAL_DMA) && (HAL_DMA == TRUE) HalDmaInit();#endif/*Flash初始化*/#if (defined HAL_FLASH) && (HAL_FLASH == TRUE) HalFlashInit();#endif/*AES初始化*/#if (defined HAL_AES) && (HAL_AES == TRUE) HalAesInit();#endif
```
```c
/*LCD初始化*/#if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdInit();#endif/*LED初始化*/#if (defined HAL_LED) && (HAL_LED == TRUE) HalLedInit();#endif/*UART初始化*/#if (defined HAL_UART) && (HAL_UART == TRUE) HalUARTInit();#endif/*KEY按键初始化*/#if (defined HAL_KEY) && (HAL_KEY == TRUE) HalKeyInit();#endif/*SPI初始化*/#if (defined HAL_SPI) && (HAL_SPI == TRUE) HalSpiInit();#endif}
```
HHal_ProcessEvent()函数由APP层OSAL_SampleApp.c文件调用,主要实现硬件抽象层的各种事件处理,比如系统消息事件、LED闪烁事件、按键事件和睡眠模式事件。
```c
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ){ uint8 *msgPtr; /*系统消息事件*/ if ( events & SYS_EVENT_MSG ) { msgPtr = osal_msg_receive(Hal_TaskID); while (msgPtr) { osal_msg_deallocate( msgPtr ); msgPtr = osal_msg_receive( Hal_TaskID ); } return events ^ SYS_EVENT_MSG; } /*LED闪烁事件*/ if ( events & HAL_LED_BLINK_EVENT ) {#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE) HalLedUpdate();#endif /* BLINK_LEDS && HAL_LED */ return events ^ HAL_LED_BLINK_EVENT; }
```
```c
/*按键事件*/if (events & HAL_KEY_EVENT){#if (defined HAL_KEY) && (HAL_KEY == TRUE)/* Check for keys */HalKeyPoll();if (!Hal_KeyIntEnable){osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);}#endifreturn events ^ HAL_KEY_EVENT;}/*睡眠模式*/#ifdef POWER_SAVINGif ( events & HAL_SLEEP_TIMER_EVENT ){halRestoreSleepLevel();return events ^ HAL_SLEEP_TIMER_EVENT;}#endifreturn 0;}
```
HTarget hal_board_cfg.h文件中为硬件资源LED等进行配置,在官方的协议栈中定义了3个LED,分别接CC2530的P1_0、P1_1和P1_4引脚。
```c
/* LED1配置 */#define LED1_BV BV(0)#define LED1_SBIT P1_0#define LED1_DDR P1DIR#define LED1_POLARITY ACTIVE_HIGH #ifdef HAL_BOARD_CC2530EB_REV17/* LED2配置 */#define LED2_BV BV(1)#define LED2_SBIT P1_1#define LED2_DDR P1DIR#define LED2_POLARITY ACTIVE_HIGH /* LED3配置 */#define LED3_BV BV(4)#define LED3_SBIT P1_4#define LED3_DDR P1DIR#define LED3_POLARITY ACTIVE_HIGH#endif
```
控制LED开关状态。
```c
#if defined (HAL_BOARD_CC2530EB_REV17) && !defined (HAL_PA_LNA) && !defined (HAL_PA_LNA_CC2590) /*打开LED*/#define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0); )#define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0); )#define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0); )#define HAL_TURN_OFF_LED4() HAL_TURN_OFF_LED1() /*关闭LED*/#define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1); )#define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1); )#define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1); )#define HAL_TURN_ON_LED4() HAL_TURN_ON_LED1() /*LED状态改变*/#define HAL_TOGGLE_LED1() st( if (LED1_SBIT) { LED1_SBIT = 0; } else { LED1_SBIT = 1;} )#define HAL_TOGGLE_LED2() st( if (LED2_SBIT) { LED2_SBIT = 0; } else { LED2_SBIT = 1;} )#define HAL_TOGGLE_LED3() st( if (LED3_SBIT) { LED3_SBIT = 0; } else { LED3_SBIT = 1;} )#define HAL_TOGGLE_LED4() HAL_TOGGLE_LED1() #define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT))#define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT))#define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT))#define HAL_STATE_LED4() HAL_STATE_LED1()#endif
```
在Drives文件中定义了硬件资源的驱动函数文件
- **LED**:在hal_led.c文件中实现,为LED提供驱动函数;
- **ADC**:在hal_adc.c文件中实现,为ADC提供驱动函数;
- **KEY**:在hal_key.c文件中实现,为按键提供驱动函数;
- **LCD**:在hal_LCD.c文件中实现,为LCD提供驱动函数;
- **定时器**:在hal_timer.c文件中实现,为定时器提供驱动函数;
- **串口**:在hal_uart.c文件中实现,为串口提供驱动函数;
- **DMA**:在hal_dma.c文件中实现,为DMA提供驱动函数;
- **flash**:在hal_flash.c文件中实现,为flash提供驱动函数。
APP应用层调用LED设置函数
```c
HalLedSet(uint8 leds,uint8 mode);HalLedBlink(uint8 leds,uint8 numBlink,uint8 percend,uint16 period);
```
!(https://raw.githubusercontent.com/Editblog/PicGo/main/img/20210527185047.png)
终于有人发物联网相关的东西了,当年学ZigBee学不通已经转行{:1_907:} zhaomingzhi 发表于 2021-7-26 08:47
终于有人发物联网相关的东西了,当年学ZigBee学不通已经转行
再不发 我也快要转行了,实在没有资源学 想学zigbee加一 ble能mesh组网之后,zigbee优势已经不大了
感觉这么多年,一直没发展起来
页:
[1]