当前位置: 首页 > wzjs >正文

青岛企业网站建设优化seo网站优化详解

青岛企业网站建设优化,seo网站优化详解,网络工程师是青春饭吗,徐州手机网站05_Z-Stack无线点灯 前言 ​ 本章介绍ZigBee协议栈和Z-Stack的使用方式,并以TI提供的例子讲解代码。在正式讲解ZigBee前,为读者补充无线电通信的基础以及射频芯片的相关知识。为了突出重点,Z-Stack的下载将在文章最后。 无线电基础(了解) …

05_Z-Stack无线点灯

前言

​ 本章介绍ZigBee协议栈和Z-Stack的使用方式,并以TI提供的例子讲解代码。在正式讲解ZigBee前,为读者补充无线电通信的基础以及射频芯片的相关知识。为了突出重点,Z-Stack的下载将在文章最后。

无线电基础(了解)

  • 射频通信系统(RF System): 一种在接收方与发射方实现通信的无线电系统,如广播无线电、广播电视等。
  • 无线通信系统: 由发送方(Transmitter)接收方(Receiver)组成,在发送方将低频的信息信号高频的载波信号经过调制器(Modulator)放大器(Amplifier)后发送,接收方将收到的信号进行放大、解调后输出。下图是一个简单的无线电系统:

在这里插入图片描述

  • 调制器解调器: 调制的目的是把要传输的模拟信号数字信号变换成适合信道传输的信号,解调则是从携带信息的已调信号中恢复信息的过程

在这里插入图片描述

  • 调制方式:
    • AM(Amplitude Modulation): 幅调,载波的幅值随信息信号的变化而变化
    • FM(Frequency Modulation): 频调,载波的频率随信息信号的变化而变化
    • PM(Phase Modulation): 相调,载波的相角随信息信号的变化而变化
  • 数字信号的调制叫做键移(Shift Keying)
    • ASK(Amplitude Shift Keying): 幅值键移,简单的调制手段,但对噪声敏感
    • FSK(Frequency Shift Keying): 频率键移,不易受噪声影响
    • PSK(Phase Shift Keying): 相角键移,不易受噪声影响,但需要频率和相角同步,**硬件更复杂 **(ZigBee调制方法即为PSK)
  • 信道是信息传输所用的通道,不同的信源信宿在不同的信道上传输信息,信道的带宽频率决定了信号的质量和干扰

射频模块(了解)

​ 一个基本的射频由晶振(Crystal)射频集成电路(RF-IC)Balun匹配器(Matching)、滤波器(Filter)和天线(Antenna)组成

  • 晶振: 提供基准频率
  • RF-IC: 包含收发器,SOC或集成微控制器
  • Balun: 平衡不平衡转换器,原理是按天线理论,偶极天线属平衡型天线,而同轴电缆属不平衡传输线,若将其直接连接,则同轴电缆的外皮就有高频电流流过,影响天线的辐射。因此,就要在天线和电缆之间加入平衡不平衡转换器,把流入电缆屏蔽层外部的电流扼制掉
  • 匹配器: 用于匹配射频电源和负载之间的阻抗的设备,确保射频电源能够有效地将能量传输到负载中,以提供最大功率传输和系统效率
  • 滤波器: 使信号中特定的频率成分通过,而极大地衰减其他频率成分(提取有用信号)
  • 天线: 发射和接收电磁波 (增大信号传递距离)

在这里插入图片描述

CC2530-RF内核(了解)

CC2530RF内核是其无线通信能力的核心,它集成了多种功能以支持高效的无线通信:

  • 调制器: 把原始数据转换为 I/Q 信号发送到发送器 DAC
  • 解调器: 负责从收到的信号中检索无线数据
  • 帧过滤和源匹配: 帧过滤功能拒绝目标不明确的帧,源匹配对消息进行短地址匹配扩展地址匹配
  • 频率合成器(FS):RF信号产生载波,载波频率可以通过编程位于 FREQCTRL.FREQ[6:0]7位频率字设置。IEEE802.1 5.4-2006 指定 16个通道,它们位于2.4GHz频段之内。步长为 5 MHz,编号为 11~26,

f c = 2405 + 5 ( k − 11 ) [ M H z ] , k ∈ [ 11 , 26 ] F R E Q C T R L . F R E Q 寄存器因此设置为 F R E Q C T R L . F R E Q = 11 + 5 ( k – 11 ) f_c=2405+5(k-11)[MHz], k\in[11,26]\\ FREQCTRL.FREQ 寄存器因此设置为 FREQCTRL.FREQ = 1 1 + 5 (k – 1 1 ) fc=2405+5(k11)[MHz],k[11,26]FREQCTRL.FREQ寄存器因此设置为FREQCTRL.FREQ=11+5(k–11)

  • 命令选通处理器(CSP): 处理CPU发出的所有命令。它还有一个24 字节的很短的程序存储器,使得它可 以自动执行CSMA-CA 机制。
  • 无线电RAM: 为发送数据有一个 FIFO(TXFIFO),为接收数据有一个 FIFO(RXFIFO)。RAM 为帧过滤和源匹配存储参数。
  • RSSI: 无线电有一个内置的接收信号强度指示器(RSSI),计算一个8位有符号的数字值,可以从寄存器读出,或自动附加到收到的帧
  • 输出功率编程: RF输出功率由 TXPOWER 寄存器的7位值控制。
  • 定时器2(MAC定时器)用于为无线电事件计时,以捕获输入数据包的时间戳

值得注意的是,实际开发中,在Z-Stack的框架下,仅需要在配置文件调用接口即可完成无线电参数的配置。

ZigBee(重点)

ZigBee协议栈

在这里插入图片描述

  • ZigBee协议栈分为五层
  • 物理层(PHY):定义物理无线信道,在2.4GHz频段上提供250kbps速率的16个不同信道,868MHz 提供速率为20kbps速率的1个信道,915MHz支持速率为40kbps10个信道
  • MAC层:MAC层数据服务为物理层与网络层之间的数据传输提供一个接口, 以实现数据发送、接收和处理排列中清除一个MAC层服务数据单元。
  • 网络层:提供网络安全管理, 信息代理路由管理网络管理四大功能
  • APS(应用支持层):抽象层,为应用层提供服务,提供应用级安全管理信息管理映射器管理
  • APL(应用层):又分为AF(应用框架)ZDO(ZigBee设备对象)
    • ZDO: 主要负责设备的管理、安全加密、网络维护和绑定管理等功能
    • AF:侧重于为应用对象提供数据传输服务、端点管理和配置文件支持等

ZigBee设备类型

  • 协调器(Coordinator): 建立网络,但没有加入网络的功能,它的职责是创建管理网络,主要功能如下:
    • 扫描存在的射频环境,选择合适的信道(根据射频环境)。选择一个网络ID(又叫PAN ID)。创建并开始网络
    • 作为网络的信任中心,管理网络安全
    • 分发密钥并允许其他设备加入网络
    • 帮助在网络中建立应用级的绑定
    • 除此之外,具有路由器的功能
  • 路由器(Router): 主要功能如下:
    • 允许其他设备加入网络(在Z3.0中,该设备已被授予编队能力,允许其创建分布式安全网络)
    • 多跳路由
    • 协助子终端设备的通信
    • 一般来说要一直开启,因此要由电源供电
  • 终端设备(End-device): 不维持网络的建设,因此可以进入睡眠唤醒模式

ZigBee地址

地址类型
  • 64-bit IEEE address(MAC address) 值得注意的是TCP/IP中的MAC地址48-bit, 但二者在本质上没有区别
  • 16-bit network address(logical address / short address) 只在同一个网络中唯一,若有多个网络,则有可能有相同的短地址
相关Z-Stack API
  • NLME_GetShortAddr() : 返回当前设备的16位网络地址
  • NLME_GetExtAddr() : 返回当前设备的64位扩展地址
  • NLME_GetCoordShortAddr() : 返回当前设备父节点16位网络地址
  • NLME_GetCorrdExtAddr() : 返回当前设备父节点64位扩展地址
地址的作用

​ 在发送消息时,通常在应用层调用AF_DataRequest()接口, 需要提供目标设备的地址地址模式,它们定义在结构体afAddrType_t中(在ZcomDef.h中定义)

  • 地址类型结构体
typedef struct
{union  // union 关键字用于定义联合体(Union)。允许在同一内存位置存储不同类型的数据,但每次只能存储其中一种类型{  // 短地址和MAC地址二选一uint16 shortAddr;  ZLongAddr_t extAddr;} addr;  // addr才是成员变量afAddrMode_t addrMode;  // 地址模式byte endPoint;  // 端点,通常用于指定设备上的特定服务或功能
} afAddrType_t;
  • 地址模式枚举体
typedef enum
{afAddrNotPresent = AddrNotPresent, afAddr16Bit= Addr16Bit,afAddr64Bit= Addr64Bit,afAddrGroup= AddrGroup,afAddrBroadcast = AddrBroadcast
} afAddrMode_t;
  • 单播(Unicast)时,要求目的设备的网络地址(短地址)已知,并将addrMode设置为Addr16Bit

  • 间接传播(Indirect)时,由于不知道最终地点,从发送设备的"绑定表"中查找目的地,需将addrMode设置为AddrNotPresent

  • 广播(Broadcast)时addrMode设置为AddrBroadcast,目的地址可设置为:

    • NWK_BROADCAST_DEVALL 将消息广播给所有设备,包括睡眠中的设备(对于睡眠中的设备,其消息由父节点保持,保持时间通过宏NWK_INDIRECT_TIMEOUT设置, 可以在f8wConfig.cfg文件中找到)。
    • NWK_BROADCAST_SHORTADDR_DEVRXON 将消息广播给所有设备,不包括睡眠中的设备
    • NWK_BROADCAST_SHORTADDR_DEVZCZR 将消息广播给所有路由器,包括协调器
  • 组播时(Group Addressing)时,addrMode设置为afAddrGroup并将目的地址设置层组号,而在这之前必须要先定义一个组

    aps_Group_t group;   
    // Assign yourself to group 1
    group.ID = 0x0001;
    group.name[0] = 6; // First byte is string length
    osal_memcpy( &(group.name[1]), “Group1”, 6);
    aps_AddGroup( SAMPLEAPP_ENDPOINT, &group );  // 定义一个组
    

ZigBee组网(了解)

  • 协调器扫描环境,选择合适信道创建网络,并随机生成一个网络ID(PAN ID)PAN ID可以在配置文件中提前设置。创建好网络后,协调器会定期发送信标帧(Beacon),包含网络信息(例如 PAN ID、信道信息等),以便附近的设备能够检测到这个网络并决定是否加入。
  • 加入网络时,设备先通过扫描信道寻找可用ZigBee网络。找到可用网络后,设备需要向协调器发送加入请求(Join Request)加入请求包括设备的地址(通常是一个唯一的 IEEE 地址)和设备希望加入的网络类型(例如,是否希望成为终端设备、路由器等)。
  • 协调器会检查加入设备的请求,根据网络规则和安全策略决定是否授权设备加入网络。如果授权,它会向设备发送一个加入响应(Join Response)加入响应中还会包含一个状态字段,表示加入是否成功。若成功,协调器为加入设备分配一个网络地址(短地址)。若失败,设备需要重新发起加入请求,或选择其他可用的网络。
  • 网络建立完成后,由路由器和协调器对网络进行维护

ZigBee主要参数配置

  • PAN ID: 通过配置文件f8wConfig.cfg中的宏定义ZDO_CONFIG_PAN_ID进行配置,当其被设置成0xFFFF协调器在新建网络时,会随机生成PAN ID,对于加入网络的设备来说,它可能加入任意存在的网络
  • 信道设置: 通过配置文件f8wConfig.cfg中的宏定义DEFAULT_CHANLIST进行配置,可以选择11-26号共16个信道
  • 全局配置非易失活存储器: 在项目中启用编译标志NV_INIT,会将ZGlobal.c中存储的全局配置加载到非易失活存储器中,该配置在TI给的样例中默认开启
  • 网络层非易失活存储器: 在项目中启用编译标志NV_RESTORE,将网络层参数保存在非易失活存储器中,这样设备能从意外重启或者断电中快速恢复到网络中。在实际使用中,该选项必须启动。仅在开发过程中,由于某些特殊需要可以暂时关闭。
  • 应用层非易失活存储器: 除了配置数据,非易失活存储器还保留了0x0401 to 0x0FFF 条目ID(Item ID)用于应用程序数据的存储,具体的ID列表ZComDef.h文件中可以查到
    • 要保存一个变量到非易失活存储器中,首先要创建一个条目ID(Item ID)
    • 调用osal_nv_item_init()初始化Item,需要的参数有条目ID(Item ID),变量长度和初始值
    • 调用osal_nv_write()在对应Item中写入数据
    • 调用osal_nv_read()在对应Item中读出数据
    • 这些接口定义在OSAL_Nv.c文件中

ZigBee应用层开发(重点)

功能说明

  • zigbee组网
    • zigbee协调器创建网络
    • zigbee终端加入网络
    • 回调事件处理(如重连,连接成功后执行的功能等…)
  • 协调器控制终端开关灯
    • LED驱动配置
    • 协调器定时触发事件,通过ZCL层,向终端发送命令
    • 终端通过ZCL层,接收命令,并控制LED亮灭

需要用到的API

  • 应用程序开发需用到BDB(Base Device Behavior) APIBDB层指定了基本设备的运行环境、初始化、调试和操作程序,这些接口使设备ZigBee网络中合理可行(定义了设备在ZigBee网络中的基本行为)
  • 需要使用基本的OSAL(OS Abstraction Layer) APIOSAL层提供任务注册及初始化任务间信息交换任务同步中断处理定时器内存分配等功能的接口
  • 一些应用可能用到HAL(Hardware Abstract Layer) API,提供了按键LCD串口等驱动,用户可以根据自己的需求选择性使用
  • ZCL层相关API, Zigbee联盟规定的一些接口,

OSAL任务

OSAL设计的目标是,在不需要修改OSAL的前提下,分散式的使用Z-Stack接口,在OSAL的支持下,Z-Stack的主要子系统以OSAL任务的方式运行。对于用户来说,需要至少创建一个OSAL任务来运行其需要实现的应用。创建一个OSAL任务的步骤如下:

  • 用户需要实现osalInitTasks()功能

  • 将任务添加到tasksArr任务数组中(定义在OSAL_"Application Name".c文件中,如OSAL_SampleSwitch.c)

  • 需要实现自定义任务初始化函数zcl"Application Name"_Init(如zclSampleSw_Init())对任务配置进行初始化,并在osalInitTasks()中调用它

  • 需要实现自定义任务事件处理函数zcl“Application Name”_event_loop(如zclSampleSw_event_loop()),并将其放入tasksArr任务数组中。每一个OSAL任务可定义15种事件,其中SYS_EVENT_MSG(0x8000)OSAL任务的保留事件

  • Note: 任务的优先级由其在tasksArr任务数组中的位置决定,第一个任务的优先级最高

/********************************************************************** @fn      osalInitTasks** @brief   This function invokes the initialization function for each task.** @param   void** @return  none*/
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++ );
#if !defined (DISABLE_GREENPOWER_BASIC_PROXY) && (ZG_BUILD_RTR_TYPE)gp_Init( taskID++ );
#endifHal_Init( taskID++ );
#if defined( MT_TASK )MT_TaskInit( taskID++ );
#endifAPS_Init( taskID++ );
#if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ );
#endifZDApp_Init( taskID++ );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_Init( taskID++ );
#endif// Added to include TouchLink functionality #if defined ( INTER_PAN )StubAPS_Init( taskID++ );#endif// Added to include TouchLink initiator functionality #if defined( BDB_TL_INITIATOR )touchLinkInitiator_Init( taskID++ );#endif// Added to include TouchLink target functionality #if defined ( BDB_TL_TARGET )touchLinkTarget_Init( taskID++ );#endifzcl_Init( taskID++ );bdb_Init( taskID++ );zclSampleSw_Init( taskID );  // 自定义任务初始化
}
  • 在例子SampleSwitchOSAL_SampleSw.c文件中,可以看到在osalInitTasks()函数的最后一行,调用了自定义的zclSampleSw_Init()函数。实际开发中,我们只需讲这里替换成自己的任务初始化函数
const pTaskEventHandlerFn tasksArr[] = {macEventLoop,nwk_event_loop,
#if !defined (DISABLE_GREENPOWER_BASIC_PROXY) && (ZG_BUILD_RTR_TYPE)gp_event_loop,
#endif  Hal_ProcessEvent,
#if defined( MT_TASK )MT_ProcessEvent,
#endifAPS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )APSF_ProcessEvent,
#endifZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_event_loop,
#endif//Added to include TouchLink functionality#if defined ( INTER_PAN )StubAPS_ProcessEvent,#endif// Added to include TouchLink initiator functionality#if defined ( BDB_TL_INITIATOR )touchLinkInitiator_event_loop,#endif// Added to include TouchLink target functionality#if defined ( BDB_TL_TARGET )touchLinkTarget_event_loop,#endifzcl_event_loop,bdb_event_loop,zclSampleSw_event_loop   // 自定义任务事件处理
};
  • 在例子SampleSwitchOSAL_SampleSw.c文件中,可以看到在taskArr任务数组的最后一行,保存了自定义的函数zclSampleSw_event_loop的入口

  • 通过osal_start_timerEx触发事件

zclSampleSw_Init初始化函数

void zclSampleSw_Init( byte task_id )
{zclSampleSw_TaskID = task_id; // 保存任务ID// Set destination address to indirectzclSampleSw_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;zclSampleSw_DstAddr.endPoint = 0;zclSampleSw_DstAddr.addr.shortAddr = 0;// Register the Simple Descriptor for this applicationbdb_RegisterSimpleDescriptor( &zclSampleSw_SimpleDesc );// Register the ZCL General Cluster Library callback functionszclGeneral_RegisterCmdCallbacks( SAMPLESW_ENDPOINT, &zclSampleSw_CmdCallbacks );zclSampleSw_ResetAttributesToDefaultValues();// Register the application's attribute listzcl_registerAttrList( SAMPLESW_ENDPOINT, zclSampleSw_NumAttributes, zclSampleSw_Attrs );// Register the Application to receive the unprocessed Foundation command/response messageszcl_registerForMsg( zclSampleSw_TaskID );// Register for all key events - This app will handle all key events 注册按键事件RegisterForKeys( zclSampleSw_TaskID );// 注册回调函数bdb_RegisterCommissioningStatusCB( zclSampleSw_ProcessCommissioningStatus );// Register for a test endpointafRegister( &sampleSw_TestEp );#ifdef ZCL_DIAGNOSTIC// Register the application's callback function to read/write attribute data.// This is only required when the attribute data format is unknown to ZCL.zcl_registerReadWriteCB( SAMPLESW_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );if ( zclDiagnostic_InitStats() == ZSuccess ){// Here the user could start the timer to save Diagnostics to NV}
#endif#if defined (OTA_CLIENT) && (OTA_CLIENT == TRUE)// Register for callback events from the ZCL OTAzclOTA_Register(zclSampleSw_TaskID);
#endifzdpExternalStateTaskID = zclSampleSw_TaskID;/**LOOK HERE **/ 
/* 对于初始化函数来说,保存任务ID,注册按键是基本的. 其余就是根据需求,注册一些事件和回调函数
上面代码中zcl层, 是zigbee联盟规定的一些定义,各个厂商在开发时都遵循这些定义,从而实现互联互通
因此, 全删了或者留下影响都不大, 我们先专注于自己的功能即可(zcl层功能用到时再仔细学习) */
// 实现无线点灯,首先需要建立网络(由协调器完成)
#ifdef ZDO_COORDINATOR  // 协议器需完成 建立网络/发送调试信息的工作// Init UartzclSampleSw_InitUart(); // 串口初始化 调试可用ZDO_RegisterForZDOMsg ( zclSampleSw_TaskID, Device_annce ); // 注册Device_annce簇ID// 协调器收到 终端的地址广播会产生该事件, 需要在zclSampleSw_event_loop进行处理bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |BDB_COMMISSIONING_MODE_FINDING_BINDING ); // 建立一个网络NLME_PermitJoiningRequest(255);  // 允许加入网络
#else  // 若不是协调器 只需加入网络,并广播地址bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_STEERING |BDB_COMMISSIONING_MODE_FINDING_BINDING ); // 加入网络// 加入网络后 广播自己的地址 直接放这不管有没有成功都会执行// zclSampleSw_DeviceAnnce(); // 注释掉, 移动到zclSampleSw_ProcessCommissioningStatus回调函数中会更好
#endif
}

zclSampleSw_event_loop事件处理

uint16 zclSampleSw_event_loop( uint8 task_id, uint16 events ) // 应用层各种事件的处理
{afIncomingMSGPacket_t *MSGpkt;(void)task_id;  // Intentionally unreferenced parameter//Send toggle every 500msif( events & SAMPLESW_TOGGLE_TEST_EVT ){osal_start_timerEx(zclSampleSw_TaskID,SAMPLESW_TOGGLE_TEST_EVT,500);zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, 0 );// return unprocessed eventsreturn (events ^ SAMPLESW_TOGGLE_TEST_EVT);}if ( events & SYS_EVENT_MSG ){while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleSw_TaskID )) ){switch ( MSGpkt->hdr.event ){case ZCL_INCOMING_MSG:  // // Incoming ZCL Foundation command/response messageszclSampleSw_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );break;case KEY_CHANGE:zclSampleSw_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );break;case ZDO_STATE_CHANGE:break;#if defined (OTA_CLIENT) && (OTA_CLIENT == TRUE)case ZCL_OTA_CALLBACK_IND:zclSampleSw_ProcessOTAMsgs( (zclOTA_CallbackMsg_t*)MSGpkt  );break;
#endif#ifdef ZDO_COORDINATOR  // LOOK Here// 通过 ZDO_RegisterForZDOMsg注册case ZDO_CB_MSG: // 收到 终端地址消息会产生该事件zclSampleSw_processZDOMgs( (zdoIncomingMsg_t *)MSGpkt );break; #endifdefault:break;}// Release the memoryosal_msg_deallocate( (uint8 *)MSGpkt );}// return unprocessed eventsreturn (events ^ SYS_EVENT_MSG);}#if ZG_BUILD_ENDDEVICE_TYPE    if ( events & SAMPLEAPP_END_DEVICE_REJOIN_EVT ){bdb_ZedAttemptRecoverNwk();return ( events ^ SAMPLEAPP_END_DEVICE_REJOIN_EVT );}
#endif#ifdef ZDO_COORDINATOR  // 协调器if ( events & SAMPLEAPP_ONOFF_TEST_EVT )  // 开关灯事件{zclSampleSw_OnOffTest();  // 发送开关灯命令osal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_ONOFF_TEST_EVT, SAMPLEAPP_ONOFF_TEST_PERIOD); // 重复触发事件return ( events ^ SAMPLEAPP_ONOFF_TEST_EVT );  // 返回剩余事件}
#else// Rejoinif ( events & SAMPLEAPP_REJOIN_EVT )  // 重连事件 非协调器{// 重新连接bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING |BDB_COMMISSIONING_MODE_FINDING_BINDING );return ( events ^ SAMPLEAPP_REJOIN_EVT );  // 返回剩余事件}
#endif// Discard unknown eventsreturn 0;
}

组网功能详解

  • 对于协调器使用bdb_StartCommissioning()创建一个网络,模式为FORMATIONFINDING_BINDING,并调用NLME_PermitJoiningRequest()允许其他设备入网

  • 对于终端使用bdb_StartCommissioning()加入网络,模式为STEERINGFINDING_BINDING,终端成功加入网络后,调用zclSampleSw_DeviceAnnce()向网络广播自己的地址.

​ 具体代码如下(已删除其他功能,zclSampleSw_Init函数中):

#ifdef ZDO_COORDINATOR  // 协议器需完成 建立网络/发送调试信息的工作  ZDO_RegisterForZDOMsg ( zclSampleSw_TaskID, Device_annce );  // 注册 Device_annce 簇IDbdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |BDB_COMMISSIONING_MODE_FINDING_BINDING ); // 建立一个网络NLME_PermitJoiningRequest(255);  // 允许加入网络
#else  // 若不是协调器bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_STEERING |BDB_COMMISSIONING_MODE_FINDING_BINDING ); // 加入网络
#endif
  • 回调函数和重连事件:

    • zcl_samplesw.h文件中定义重连事件重连事件间隔
    #ifdef ZDO_COORDINATOR
    #else// rejoin#define SAMPLEAPP_REJOIN_EVT          0x0080#define SAMPLEAPP_REJOIN_PERIOD       1000
    #endif
    
    • 编写bdb_StartCommissioning的回调函数zclSampleSw_ProcessCommissioningStatus,该函数在zclSampleSw_Init中通过bdb_RegisterCommissioningStatusCB()注册(可以往上找找看)
    static void zclSampleSw_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg)
    {switch(bdbCommissioningModeMsg->bdbCommissioningMode){case BDB_COMMISSIONING_FORMATION:if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS){bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | bdbCommissioningModeMsg->bdbRemainingCommissioningModes);}else{}break;case BDB_COMMISSIONING_NWK_STEERING:  // 在这里处理if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS){// 如果连接成功#ifdef ZDO_COORDINATORzclSampleSw_DeviceAnnce();  // 加入网络后 广播自己的地址#else #endif}else // 连接失败{#ifdef ZDO_COORDINATOR#else // 启动重连事件osal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_REJOIN_EVT, SAMPLEAPP_REJOIN_PERIOD);#endif}break;case BDB_COMMISSIONING_FINDING_BINDING:if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS){//YOUR JOB:}else{//YOUR JOB://retry?, wait for user interaction?}break;case BDB_COMMISSIONING_INITIALIZATION://Initialization notification can only be successful. Failure on initialization //only happens for ZED and is notified as BDB_COMMISSIONING_PARENT_LOST notification//YOUR JOB://We are on a network, what now?break;
    #if ZG_BUILD_ENDDEVICE_TYPE    case BDB_COMMISSIONING_PARENT_LOST:if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_NETWORK_RESTORED){//We did recover from losing parent}else{//Parent not found, attempt to rejoin again after a fixed delayosal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_END_DEVICE_REJOIN_EVT, SAMPLEAPP_END_DEVICE_REJOIN_DELAY);}break;
    #endif }
    }
    
  • 事件处理

    • (终端)在事件处理函数zclSampleSw_event_loop中,处理重连事件
    #ifdef ZDO_COORDINATOR
    #else// Rejoin 重新加入网络if ( events & SAMPLEAPP_REJOIN_EVT ){bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING |BDB_COMMISSIONING_MODE_FINDING_BINDING );return ( events ^ SAMPLEAPP_REJOIN_EVT );}
    #endif
    
    • (协调器)在事件处理函数zclSampleSw_event_loop中,处理ZDO事件(Device_annce)
    switch ( MSGpkt->hdr.event )
    {...
    #ifdef ZDO_COORDINATORcase ZDO_CB_MSG:  // 当协调器收到Device_annce消息会触发该事件zclSampleSw_processZDOMgs( (zdoIncomingMsg_t *)MSGpkt ); // ZDO消息处理函数break;...
    #endif
    }
    
    /*** @fn      zclSampleSw_processZDOMgs** @brief   Process ZDO Message*/
    static void zclSampleSw_processZDOMgs(zdoIncomingMsg_t *pMsg)
    {switch ( pMsg->clusterID ){case Device_annce:{zclSampleSw_OnOffTestAddr = pMsg->srcAddr.addr.shortAddr;  // 保存地址HalLcdWriteStringValue("Node:", pMsg->srcAddr.addr.shortAddr, 16, 3);}break;default:break;}
    }
    
  • zclSampleSw_DeviceAnnce

 /*** @brief 终端广播自己的网络地址*/static void zclSampleSw_DeviceAnnce( void ){    ZDP_DeviceAnnce(NLME_GetShortAddr(),//获取本设备的网络地址(短地址)NLME_GetExtAddr(),//获取本设备的物理地址(通常就是MAC地址)ZDO_Config_Node_Descriptor.CapabilityFlags,0);    }

ZCL层On/Off命令收发

​ ZCL定义了On/Off Cluster命令,借助ZCL层,可方便实现协调器对终端设备下达命令

  • zcl_samplesw.c中的zclSampleSw_Init中,可找到zcl层的初始化代码
// Register the ZCL General Cluster Library callback functions  
zclGeneral_RegisterCmdCallbacks(SAMPLESW_ENDPOINT,  
&zclSampleSw_CmdCallbacks);  // 注册回调函数列表zclSampleSw_ResetAttributesToDefaultValues();    // 设置参数为默认值// Register the application's attribute list    为设备注册一个属性列表。
zcl_registerAttrList(SAMPLESW_ENDPOINT,zclSampleSw_NumAttributes,zclSampleSw_Attrs);  // Register the Application to receive the unprocessed Foundation command/response messages 
// 告诉设备需要接收未处理的Foundation(基础)命令或者响应消息。
zcl_registerForMsg( zclSampleSw_TaskID );
  • zclSampleSw_CmdCallbacks添加On/Off命令的回调函数zclSampleSw_OnOffCB,它的定义如下:
/*** @fn      zclSampleSw_OnOffCB** @brief   ZCL Command - On/Off*/
static void zclSampleSw_OnOffCB( uint8 cmd )  // 终端收到 On/Off命令后, 会执行该回调函数
{if(cmd == COMMAND_ON){HalLcdWriteString("Set ON", 4);  HalLedSet(HAL_LED_ALL, HAL_LED_MODE_ON);  // 终端控制LED灯亮}else if(cmd == COMMAND_OFF){HalLcdWriteString("Set OFF", 4);HalLedSet(HAL_LED_ALL, HAL_LED_MODE_OFF);  // 灭}
}
  • zclSampleSw_processZDOMgs函数中加入事件触发
/*** @fn      zclSampleSw_processZDOMgs** @brief   Process ZDO Message*/
static void zclSampleSw_processZDOMgs(zdoIncomingMsg_t *pMsg)
{switch ( pMsg->clusterID ){case Device_annce:{zclSampleSw_OnOffTestAddr = pMsg->srcAddr.addr.shortAddr;  // 保存地址HalLcdWriteStringValue("Node:", pMsg->srcAddr.addr.shortAddr, 16, 3);HalLcdWriteString("On/Off Test...", 4);osal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_ONOFF_TEST_EVT, SAMPLEAPP_ONOFF_TEST_PERIOD); // 触发开关事件}break;default:break;}
}
  • zclSampelSw_eventloop中处理SAMPLEAPP_ONOFF_TEST_EVT事件
#ifdef ZDO_COORDINATORif ( events & SAMPLEAPP_ONOFF_TEST_EVT ){zclSampleSw_OnOffTest();  // 处理函数osal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_ONOFF_TEST_EVT, SAMPLEAPP_ONOFF_TEST_PERIOD);  // 过一段时间重新触发事件, 实现命令发送的周期性return ( events ^ SAMPLEAPP_ONOFF_TEST_EVT ); // 返回未处理的事件}
#else
...
#endif
/*** @fn      zclSampleSw_OnOffTest** @brief   Send On/Off Command to device*/
static void zclSampleSw_OnOffTest(void)
{afAddrType_t destAddr;static uint8 txID = 0;static bool  on   = true;destAddr.endPoint = SAMPLESW_ENDPOINT;destAddr.addrMode = Addr16Bit;destAddr.addr.shortAddr = zclSampleSw_OnOffTestAddr;if(on){HalLcdWriteString("Command: ON", 4);zclGeneral_SendOnOff_CmdOn(SAMPLESW_ENDPOINT, &destAddr,TRUE,txID++);  // 协调器发送开灯命令}else{HalLcdWriteString("Command: OFF", 4);zclGeneral_SendOnOff_CmdOff(SAMPLESW_ENDPOINT, &destAddr,TRUE,txID++);// 协调器发送关灯命令}on = !on; // 切换开关
}

硬件驱动层移植

​ 见硬件Zstack-驱动移植篇,提供LED、Uart以及LCD的参考方案

参考资料

RF Basics, RF for Non-RF Engineers

CC2530 Software Examples User’s Guide (Rev. A

射频百科|巴伦(balun)的基本原理与应用 - 知乎

射频电源匹配器工作原理及组成 - 知乎

【Zigbee】进阶篇(1) Zigbee协议栈创建简单项目,协议栈、事件、消息学习_zstack系统事件都有哪些-CSDN博客

ZigBee2007协议规范.PDF

CC2530中文数据手册.PDF

Z-Stack 3.0 Developer’s Guide.pdf
5.3 ZCL 开关命令收发实验 - ZigBee 3.0 开发指南

http://www.dtcms.com/wzjs/282985.html

相关文章:

  • 网站设计 方案seo专业培训费用
  • h5网站后台管理模板nba交易最新消息
  • 无锡有网页制作公司吗郑州网站优化软件
  • 小程序怎么推广引流包头整站优化
  • 武汉网站建设机构永久免费建站系统
  • 设计高端网站建设引擎搜索优化
  • 酒店类网站开发的策略外贸如何做网站推广
  • 个人做论坛网站需要哪些备案营销推广文案
  • 十大免费论文网站合肥关键词排名技巧
  • 北京专业做网站公司10条重大新闻
  • 做网站公众号要多少钱互联网推广中心
  • 做网站的开场白网站品牌推广公司
  • 建设厅副厅长关键词优化排名查询
  • 大连坐做网站公司免费seo在线工具
  • 怎么做网站 教学头条今日头条
  • 烟台电子商务产业园网站建设广告优化师的工作内容
  • 动态网站项目实训教程任务3怎么做哪个平台推广效果好
  • 知识库wordpressseo优化人员
  • 江门网站制作套餐企业策划方案怎么做
  • 网站建设程序做哪些在线客服系统平台有哪些
  • shopex网站 css乱了淮北seo排名
  • 莱芜搜狗推广提供seosem是指什么意思
  • 大学生创新创业网站开发电商卖货平台有哪些
  • 北京做网站建设价格百度网站怎么做
  • 深圳做地铁的公司网站发软文的网站
  • 唐山网站建设优化网页设计制作网站模板图片
  • 普陀做网站价格seo优化专员工作内容
  • 网站建设中的端口泰安seo网络公司
  • 电商网站可以用dw做网上哪里接app推广单
  • 凡客网站登录seo教程自学网