ZigBee源码程序及解释
- 格式:doc
- 大小:130.50 KB
- 文档页数:37
竭诚为您提供优质文档/双击可除zigbee协议栈源码篇一:zigbeez-stack协议栈构架zstack基础1、zstack协议栈构架zigbee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供一些应用层api,供用户调用。
协议栈体系分层架构与协议栈代码文件夹对应表如下:整个协议栈的构架,如图所示app:应用层目录,这是用户创建各种不同工程的区域,在这个目录中包含了应用层的内容和这个项目的主要内容,在协议栈里面一般是以操作系统的任务实现的。
hal:硬件层目录,包含有与硬件相关的配置和驱动及操作函数。
mac:川@。
层目录,包含了川@。
层的参数配置文件及其mac的lib库的函数接口文件。
mt:监控调试层,主要用于调试目的,即实现通过串口调试各层,与各层进行直接交互。
nwk:网络层目录,含网络层配置参数文件及网络层库的函数接口文件,aps层库的函数接口。
osal:协议栈的操作系统。
profile: @尸层目录,包含aF层处理函数文件。
$。
皿丫五丫:安全层目录,安全层处理函数接口文件,比如加密函数等。
services:地址处理函数目录,包括着地址模式的定义及地址处理函数。
tools:工程配置目录,包括空间划分及zstack相关配置信息。
zdo: zdo 目录。
zmac:mac 层目录,包括mac 层参数配置及mac 层lib 库函数回调处理函数。
zmain:主函数目录,包括入口函数 main()及硬件配置文件。
output:输出文件目录,这个ew8051ide自动生成的。
2、zigbee20xx协议栈源码库结构分析了解了218匕。
20**协议栈整个构架后,再来看看协议栈源码库结构是什么样的,各层的具体文件是什么,建立不同的项目、添加自己的应用层任务及处理函数需要修改什么文件。
zigbee20xx协议栈zstack-1.4.2文件目录及说明如下:打开smapleapp项目工程先看app层:从上图可以看出,对于不同的项目,大部分代码都是相同的,只是在用户应用层,添加了不同的任务及事件处理函数。
图1
连接
连接时,若协调器通过网关与PC连接,则选“网关模式”进行连接;若协调器直接写PC连接,则选“直连模式”进行连接。
串口号即为PC连接时使用的串口号。
采集
连接好之后,会在界面的左侧区域1显示出当前的标签(标签的网络地址和用户ID)。
单击选中一个标签后,右侧绘图区域2会根据区域3相应的选择画出当前标签的信息;同时区域4以文字形式显示出当前标签的各种信息。
配置
图2
单击区域5的“配置”按钮,弹出图2框,即可对标签进行配置,即写操作。
在弹出图2框后,按住需配置的标签的按钮5秒钟后,该框即会显示出该标签当前的配置信息。
如,在区域1显示当前标签的网络地址。
以配置用户ID为例。
区域2的上栏显示当前配置的用户ID,下栏可以输入新的用户ID,十六位字母表示的十六进制数字,输完后点区域3的按钮,若配置成功,会弹出一个小框提示配置成功。
配置报告周期、温湿度等与配置用户ID类似。
其中配置温湿度、光照、加速度,若当前标签的配置状态为报告,则会在相应的上栏的复选框中以打钩选中表示。
获取协调器IEEE地址
图3
连接时与上面说明一致。
连接后,点击“获到协调器IEEE地址”按钮,即会在其上方的输入框中显示出当前连接的协调器的IEEE地址。
LED闪烁
图4
连接时与上面说明一致。
连接后,选中一个标签后,单击右侧的“LED闪烁”按钮,若控制成功,相应的标签的LED灯即会进行闪烁,同时也会弹出一个小框提示控制成功。
zigbee基本概念及协议术语1. 逻辑设备类型协调器(coordinator),路由器(router),终端设备(end-device)•ZigBee 协调者—coord为协调者节点*–每各ZigBee网络必须有一个.–初始化网络信息.协调器是一种特殊的路由器(待确认)•ZigBee 路由器—router为路由节点*–路由信息•ZigBee 终端节点—rfd为终端节点*–没有路由功能–低价格2 . 2.4GHz射频信道分为16个独立信道。
3. 绑定应用设备之间信息流的控制机制。
有直接绑定(OTA)、间接绑定、直接绑定(通过串口)4. 配置文件profile 应用程序框架5. 端点endpoint 每个ZigBee设备支持多达240个端点6. NWK寻址地址类型:ZigBee设备有一个64位IEEE长地址(MAC地址)通常用一个16位短地址表识网络地址分配由协调器完成相关参数:5 max_depth 网络的最大深度6 Max_children 路由器或协调器节点连接子节点最大个数20 Max_router 路由器或协调器处理的具有路由能力的子节点最大个数它是max_children的子集数据包传送单点unicast 多点multicast 广播broadcast路由:经过路由器的每个数据帧寻找一条最佳传输路径,并将该数据有效地传送到目的节点。
F8wconfig.cfg配置路由看了下面就不用纠结了。
配置文件(profile):Zigbee协议的配置文件是对逻辑组件及其相关接口的描述,是面向某个应用类别的公约、准则.通常没有程序代码与配置文件相关联.属性(attribute):设备之间通信的每一种数据像开关的状态或温度计值等皆可称为属性.每个属性可得到唯一的ID值.簇(cluster):多个属性的汇集形成了簇,每个簇也拥有一个唯一的ID.虽然个体之间传输的通常是属性信息,但所谓的逻辑组件的接口指的却是簇一级的操作,而非属性一级.终端(endpoint):每个支持一个或多个簇的代码功能块称为终端.不同的设备通过它们的终端及所支持的簇来进行通信.Cluster: is a container for one or more attributes. (一个或更多属性的集合)Attribute: a data entity which represents a physical quantity or state.(反映物理特性或状态的一个数据实体)Cluster是逻辑设备之间的事务关系Cluster定性Attribute则是某种事务关系的具体特例Attribute定量Endpoint是一个逻辑设备(个人理解为入口地址)。
竭诚为您提供优质文档/双击可除zigbee协议,源代码篇一:揭开zigbee20xx协议栈z-stack的”开源“面纱揭开zigbee20xx协议栈z-stack的”开源“面纱(20xx-11-2216:06)分类:zigbee技术学习我们都在说zigbee20xx协议栈z-stack是开源的,但是这个协议栈到底是全部开源的,还是只是开源一部分,让我们来揭开它的“开源”面纱?z-stack是在20xx年4月,德州仪器推出业界领先的zigbee协议栈,z-stack符合zigbee20xx规范,支持多种平台,z-stack 包含了网状网络拓扑的几近于全功能的协议栈,在竞争激烈的zigbee领域占有很重要地位。
配合osal完成整个协议栈的运行。
z-stack只是zigbee协议的一种具体的实现,我们要澄清的是zigbee不仅仅有z-stack这一种,也不能把z-stack 等同于zigbee20xx协议,现在也有好几个真正开源的zigbee协议栈,例如:msstatepan协议栈,freakz协议栈,这些都是zigbee协议的具体实现,而且是全部真正的开源的,它们的所有源代码我们都可以看到,而z-stack中的很多关键的代码是以库文件的形式给出来,也就是我们只能用它们,而看不到它们的具体的实现。
那下面我们就以z-stack1.4.3-1.2.0看看它的组织架构,那些功能是开源的,那些是以库文件的形式提供给我们的。
我们利用z-stack开发应用,只能知道怎么做和做什么也就是“how”和“what”,而不能准确的知道“为什么”,“why”.我们也可以通过真正这些开源的zigbee协议栈了解为什么。
我们可以从ti的官方网站下载最新的协议栈,/zigbee 我这里的是zigbee20xx版本为版本的。
下载完以后我们可以点击exe文件进行安装,默认会在c盘的根目录下建立texasinstruments目录,该目录下面的子目录就是安装z-stack的文件。
zigbee协议重要名词解释及英文缩写(转载)网络层功能:1. 加入和退出网络2. 申请安全结构3. 路由管理4. 在设备之间发现和维护路由5. 发现邻设备6. 储存邻设备信息当适当的重新分配地址联合其他设备,ZIGBEE2006可以依赖于网络协调者建立一个新网络.ZIGBEE应用层由APS(应用支持)、AF(应用结构)、ZDO(ZIGBEE设备对象)和厂商自定义应用对象组成。
APS功能1. 绑定维持工作台,定义一个两个合拢的设备进行比较建立他们的需要和服务。
2. 促进信息在设备之间的限制3. 组地址定义,移除和过滤组地址消息4. 地址映射来自于64位IEEE地址和16位网络地址5. 分裂、重新组装和可靠数据传输ZDO功能1. 定义设备内部网络(ZigBee协调者和终端接点)2. 开始和/或回答绑定请求3. 在网络设备中建立一个网络安全关系4. 在网络中发现设备和决定供给哪个应用服务ZDO同样有责任在网络中发现设备和为他们提供应用服务。
1.1.4 网络拓扑ZIGBEE网络层支持星状、树状和网状拓扑。
在星状拓扑中网络受约束与单个设备,呼叫COORD。
COORD有责任建立和维持在网络中发现的设备和其他所有设备,都知道的终端接点直接和COORD 通信。
在网状和树状拓扑中,COORD有责任建立一个网络和选择几个关键网络参数,但是网络有有可能直接应用于ZigBee路由器。
在树状网络中,利用分等级路由策略完成路由传输数据和控制消息直通网络。
树状网络在802.15.4-2003中可以采用信标引导通信。
网状网络将允许所有对等网络通信。
ZIGBEE 路又将不能在网状网络中发射规则的IEEE802.15.4-2003信标。
缩写含义AIB:应用支持层消息AF:应用结构APDU:应用支持层以下数据单位APL:应用层APS:应用支持层APSDE:应用支持层以下数据实体APSDE-SAP:应用支持层数据实体—服务通道APSME:应用支持层管理实体APSME-SAP:应用支持层管理实体—服务通道ASDU:APS服务数据单位BRT:广播重试计时器BTR:广播处理记录BTT:广播处理工作台CCM*:CSMA-CA:载波多重监听通道——避免碰撞FFD:全部功能设备GTS:担保时间跟踪IB:消息数据LQI:连接质量指示LR-WPAN:低速率无线局域网MAC:控制层MCPS-SAP:控制层公共部分—服务通道MIC:消息完整代码MLME-SAP:控制层管理实体—服务通道MSC:消息序列图表MSDU:控制层服务数据单位MSG:消息服务类型NBDT:网络广播发送时间NHLE:下一个更高层实体NIB:网络层信息数据NLDE:网络层数据实体NLDE-SAP:网络层数据实体——服务通道NLME:网络层管理实体NLME-SAP:网络层管理实体——服务通道NPDU:网络层数据单位NSDU:网络服务数据单位NWK:网络OSL:打开系统联络PAN:局域网PD-SAP:物理层数据—指向服务通道PDU:协议数据单位PHY:物理层PIB:局域网消息PLME-SAP:物理层管理实体——指向服务通道POS:私人运作空间QOS:服务质量RREP:路由回答RN:路由接点SKG:SKKE:SSP:安全服务提供SSS:安全服务说明WPAN:无线局域网XML:可扩展语言ZB:ZIGBEEZDO:ZIGBEE设备对象2.1.1APSAPS提供一个工作台在网络层和应用层之间直接服务于ZDO和厂商自定义设备。
协议栈无线透传编程原理:第一个功能:协调器的组网,终端设备和路由设备发现网络以及加入网络//第一步:Z-Stack 由main ()函数开始执行,main ()函数共做了2件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统int main( void ) ( // Initialize the operating system osal_init_system(); //第二步,操作系统初始化osal_start_system(); //初始化完系统任务事件后,正式开始执行操作系统}//第二步,进入osal_init_system() 函数,执行操作系统初始化uint8 osal_init_system( void ) //初始化操作系统,其中最重要的是,初始化机扃统的任务(// Initialize the Memory Allocation Systemosal_mem_init();// Initialize the message queueosal_qHead = NULL;// Initialize the timersosalTimerInit();// Initialize the Power Management Systemosal_pwrmgr_init();// Initialize the system tasks.osalInitTasks(); //第三步,执行操作系统任务初始化函数// Setup efficient search for the first free block of heap.osal_mem_kick();return ( SUCCESS );}//第三步,进入osalInitTasks() 函数,执行操作系统任务初始化void osalInitTasks( void ) //第三步,初始化操作系统任务(uint8 taskID = 0;tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//任务优先级由高向低依次排列,高优先级对应taskID 的值反而小macTaskInit( taskID++ ); // 不需要用户考虑nwk_init( taskID++ ); 〃不需要用户考虑Hal_Init( taskID++ ); //硬件抽象层初始化,需要我们考虑#if defined( MT_TASK )MT_TaskInit( taskID++ );#endifAPS_Init( taskID++ ); //不需要用户考虑#if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ );#endifZDApp_Init( taskID++ ); // 第四步,ZDApp层,初始化,执行ZDApp_init函数后,如果是协调器将建立网络,如果是终端设备将加入网络。
学习zigbee入门SimpleApp 例子解读-2 程序分析:灯开关灯实验:开关设备通过发送命令切换控制设备的状态,并通过指示灯的状态变化反应操作是否成功。
在SimpleApp,SimpleController.c(灯管理器设备)按键处理函数zb_HandleKeys中,当SW1被按下,它将使设备作为协调器使用;期间按下SW2,它将是该设备作为路由器启动。
1.网络形成:ZDO_StartDevice功能描述:在网络中启动设备,协调器、路由器、终端设备都可以用该函数启动,启动之后,设备根据自身的类型去建立或发现和加入网络。
看看ZDO_StartDevice函数完整形式:void ZDO_StartDevice( byte logicalType,devStartModes_t startMode,byte beaconOrder,byte superframeOrder ){ZStatus_t ret;ret = ZUnsupportedMode;#if defined(ZDO_COORDINATOR) //--条件编译语句,选择性的启动协调器if ( logicalType == NODETYPE_COORDINATOR ) //--逻辑类型,协调器{if ( startMode == MODE_HARD ) //--启动模式,硬件启动(软件启动无线龙注释暂不启动){devState = DEV_COORD_STARTING; //--协调器启动ret = NLME_NetworkFormationRequest( zgConfigPANID, zgDefaultChannelList, //--网路形成请求zgDefaultStartingScanDuration, beaconOrder,superframeOrder, false );}else if ( startMode == MODE_RESUME ) //--恢复{// Just start the coordinatordevState = DEV_COORD_STARTING;ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false ); //--路由启动请求}else{#if defined( LCD_SUPPORTED ) //--液晶显示支持(--条件编译)//HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );ClearScreen();Print8(HAL_LCD_LINE_1,10,"StartDevice ERR",1);Print8(HAL_LCD_LINE_2,10,"MODE unknown",1);#endif}}#endif // !ZDO_COORDINATOR#if !defined ( ZDO_COORDINATOR ) || defined( SOFT_START ) //--不是协调器,软件启动if ( logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE )//--逻辑类型,路由,终端设备{if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) ) //--启动模式,加入,再加入{devState = DEV_NWK_DISC;#if defined( MANAGED_SCAN ) //--管理扫描ZDOManagedScan_Next(); //--调用管理扫描ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask,BEACON_ORDER_15_MSEC );//--网络发现请求#elseret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration ); #endif}else if ( startMode == MODE_RESUME ) //--恢复{if ( logicalType == NODETYPE_ROUTER ) //--路由{ZMacScanCnf_t scanCnf; //--扫描确认devState = DEV_NWK_ORPHAN; //--设备已经失去了其母节点的信息/* if router and nvram is available, fake successful orphan scan *///--如果路由器和NVRAM可用,假成功的孤儿扫描scanCnf.hdr.Status = ZSUCCESS;scanCnf.ScanType = ZMAC_ORPHAN_SCAN;scanCnf.UnscannedChannels = 0;scanCnf.ResultListSize = 0;nwk_ScanJoiningOrphan(&scanCnf);ret = ZSuccess;}else //--终端节点{devState = DEV_NWK_ORPHAN;ret = NLME_OrphanJoinRequest( zgDefaultChannelList, //--再加入请求zgDefaultStartingScanDuration );}}else{#if defined( LCD_SUPPORTED )// HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );Print8(HAL_LCD_LINE_1,10,"StartDevice ERR",1);Print8(HAL_LCD_LINE_2,10,"MODE unknown",1);#endif}}#endif //!ZDO COORDINATOR || SOFT_STARTif ( ret != ZSuccess )osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );}2、绑定:zb_BindDevice ----已知扩展地址的绑定(1.4.3-1.2.1把已知和未知的结合起来了,还结合了绑定移除)---未知设备扩展地址的绑定---移除绑定//--设备建立绑定和移除绑定信息相关void zb_BindDevice ( uint8 create, //--是否创建绑定,ture为创建,false则解除uint16 commandId, //--命令ID,基于某种命令的绑定uint8 *pDestination ) //--指向扩展地址的指针{zAddrType_t destination; //--目的设备的类型uint8 ret = ZB_ALREADY_IN_PROGRESS; //--if ( create ) //--是否创建绑定,ture为创建,false则解除{if (sapi_bindInProgress == 0xffff) //--绑定地址为0xffff{if ( pDestination ) //--已知扩展地址的绑定,即*pDestination为非NULL{destination.addrMode = Addr64Bit; //--目的地址模式,长地址osal_cpyExtAddr( destination.addr.extAddr, pDestination );//--把扩展地址复制到extAddr中//--通过APSME_BindRequest创建绑定请求ret = APSME_BindRequest( sapi_epDesc.endPoint, commandId,&destination, sapi_epDesc.endPoint );if ( ret == ZSuccess ){// Find nwk addr //--发现网络地址,得到被绑定设备的短地址ZDP_NwkAddrReq(pDestination, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );}}else{ret = ZB_INVALID_PARAMETER;destination.addrMode = Addr16Bit;destination.addr.shortAddr = NWK_BROADCAST_SHORTADDR;if ( ZDO_AnyClusterMatches( 1, &commandId, sapi_epDesc.simpleDesc->AppNumOutClusters,sapi_epDesc.simpleDesc->pAppOutClusterList ) ){// Try to match with a device in the allow bind mode --匹配一个允许绑定模式下的设备ret = ZDP_MatchDescReq( &destination, NWK_BROADCAST_SHORTADDR,sapi_epDesc.simpleDesc->AppProfId, 1, &commandId, 0, (cId_t *)NULL, 0 );}else if ( ZDO_AnyClusterMatches( 1, &commandId, sapi_epDesc.simpleDesc->AppNumInClusters,sapi_epDesc.simpleDesc->pAppInClusterList ) ) {ret = ZDP_MatchDescReq( &destination, NWK_BROADCAST_SHORTADDR, sapi_epDesc.simpleDesc->AppProfId, 0, (cId_t *)NULL, 1, &commandId, 0 );}if ( ret == ZB_SUCCESS ){// Set a timer to make sure bind completes --设置一个时间,确保绑定完成。
哎呀研究这个数据的发送和收发研究了2天了。
今天终于把困扰我很久的一个问题给解决了。
问题:终端节点启动会为什么会自动的发送数据呢?解决过程:这个过程可是异常的艰辛。
要解决这个问题。
咱们先聊聊这个整个zigbee协议栈的工作流程。
程序肯定都是从main函数开始的,这个肯定也不例外。
大家查看一下main函数主要就是关闭中断,检查电源电压是否够高,还有就是初始化了,什么物理层,mac层等等。
而我们在这里关注2个函数就好了。
第一个是:osal_init_system();第二个:osal_start_system();第一个osal_init_system()函数就是初始化与系统运行相关的一些东西如:初始化内存分配系统,初始化消息队列,初始化定时器,初始化电源管理系统,初始化第一块堆,最后一个就是我们要讲的一个非常重要的函数:osalInitTasks();初始化任务函数void osalInitTasks( void )//系统任务初始化函数{uint8 taskID = 0;//这个指针指向了所有任务空间的首地址tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//这个tasksEvents指针总共有多少个数据空间,其实总共有多少任务就有多少个空间。
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));macTaskInit( taskID++ ); //mac层的任务是0nwk_init( taskID++ ); //网络层的任务是1Hal_Init( taskID++ ); //物理层的任务号是2#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++ );#endifGenericApp_Init( taskID );//应用程序的初始化。
Net Buildmy nwk address is:0x0000my mac address is:0x2100121314151617 my panid is:0x0021Src NWKAddr:0x0001Src MACAddr:0x0000000000000000 Src Tem:38 CSrc Bat:2.7VData Len:034Data:via:@sendocRSSI:-24LQI:159Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:29 CDst Bat:3.3VSrc NWKAddr:0x0001Src MACAddr:0x0000000000000000 Src Tem:39 CSrc Bat:2.7VData Len:034Data:via:@sendocRSSI:-24LQI:159Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:29 CDst Bat:3.3VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.4VData Len:034Data:via:@sendocRSSI:-32LQI:137Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.4VData Len:034Data:via:@sendocRSSI:-28LQI:148Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.3VData Len:034Data:via:@sendocRSSI:-29LQI:145Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:30 CDst Bat:3.3VSrc NWKAddr:0x7970Src MACAddr:0x0000000000000002 Src Tem:29 CSrc Bat:2.2VData Len:034Data:via:@sendocRSSI:-44LQI:103Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:31 CDst Bat:3.4VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.3VData Len:034Data:via:@sendocRSSI:-29LQI:145Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x7970Src MACAddr:0x0000000000000002 Src Tem:29 CSrc Bat:2.2VData Len:034Data:via:@sendocRSSI:-37LQI:123Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:30 CDst Bat:3.3VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.3VData Len:034Data:via:@sendocRSSI:-28LQI:148Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x7970Src MACAddr:0x0000000000000002 Src Tem:29 CSrc Bat:2.3VData Len:034Data:via:@sendocRSSI:-33LQI:134Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.4VSrc NWKAddr:0x796FSrc MACAddr:0x0000000000000003 Src Tem:18 CSrc Bat:2.3VData Len:034Data:via:@sendocRSSI:-29LQI:145Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.4VSrc NWKAddr:0x7970Src MACAddr:0x0000000000000002 Src Tem:29 CSrc Bat:2.2VData Len:034Data:via:@sendocRSSI:-35LQI:128Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x0001Src MACAddr:0x0000000000000000 Src Tem:36 CSrc Bat:2.7VData Len:034Data:via:@sendocRSSI:-24LQI:159Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617 Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x7970Src MACAddr:0x0000000000000002Src Tem:29 CSrc Bat:2.2VData Len:034Data:via:@sendocRSSI:-33LQI:134Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617Dst Tem:32 CDst Bat:3.3VSrc NWKAddr:0x0001Src MACAddr:0x0000000000000000Src Tem:37 CSrc Bat:2.6VData Len:034Data:via:@sendocRSSI:-26LQI:154Dst NWKAddr:0x0000Dst MACAddr:0x2100121314151617Dst Tem:32 CDst Bat:3.3V/****************************************************************************** ********************Filename: SampleApp.cRevised: $Date: 2007-10-27 17:16:54 -0700 (Sat, 27 Oct 2007) $Revision: $Revision: 15793 $Description: Sample Application (no Profile).Copyright 2007 Texas Instruments Incorporated. All rights reserved.IMPORTANT: Your use of this Software is limited to those specific rightsgranted under the terms of a software license agreement between the userwho downloaded the software, his/her employer (which must be your employer)and Texas Instruments Incorporated (the "License"). You may not use thisSoftware unless you agree to abide by the terms of the License. The Licenselimits your use, and you acknowledge, that the Software may not be modified,copied or distributed unless embedded on a Texas Instruments microcontrolleror used solely and exclusively in conjunction with a Texas Instruments radiofrequency transceiver, which is integrated into your product. Other than forthe foregoing purpose, you may not use, reproduce, copy, prepare derivativeworks of, modify, distribute, perform, display or sell this Software and/orits documentation for any purpose.YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION AREPROVIDED 揂S IS?WITHOUT W ARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,INCLUDING WITHOUT LIMITATION, ANY W ARRANTY OF MERCHANTABILITY, TITLE,NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALLTEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHERLEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVEOR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENTOF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.Should you have any questions regarding your right to use this Software,contact Texas Instruments Incorporated at .******************************************************************************* *******************//*********************************************************************This application isn't intended to do anything useful, it isintended to be a simple example of an application's structure.This application sends it's messages either as broadcast orbroadcast filtered group messages. The other (more normal)message addressing is unicast. Most of the other sampleapplications are written to support the unicast message model.Key control:SW1: Sends a flash command to all devices in Group 1.SW2: Adds/Removes (toggles) this device in and outof Group 1. This will enable and disable thereception of the flash command.*********************************************************************/ /********************************************************************* * INCLUDES*/#include "OSAL.h"#include "ZGlobals.h"#include "AF.h"#include "aps_groups.h"#include "ZDApp.h"#include "SampleApp.h"#include "SampleAppHw.h"#include "OnBoard.h"/* HAL */#include "hal_lcd.h"#include "hal_led.h"#include "hal_key.h"/********************************************************************* * MACROS*//********************************************************************* * CONSTANTS*//********************************************************************* * TYPEDEFS*//********************************************************************* * GLOBAL V ARIABLES*/// This list should be filled with Application specific Cluster IDs.const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] ={SAMPLEAPP_PERIODIC_CLUSTERID,SAMPLEAPP_FLASH_CLUSTERID};const SimpleDescriptionFormat_t SampleApp_SimpleDesc ={SAMPLEAPP_ENDPOINT, // int Endpoint;SAMPLEAPP_PROFID, // uint16 AppProfId[2]; SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; SAMPLEAPP_FLAGS, // int AppFlags:4; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList // uint8 *pAppInClusterList;};// This is the Endpoint/Interface description. It is defined here, but// filled-in in SampleApp_Init(). Another way to go would be to fill// in the structure here and make it a "const" (in code space). The// way it's defined in this sample app it is define in RAM.endPointDesc_t SampleApp_epDesc;/********************************************************************* * EXTERNAL V ARIABLES*//********************************************************************* * EXTERNAL FUNCTIONS*//********************************************************************* * LOCAL V ARIABLES*/uint8 SampleApp_TaskID; // Task ID for internal task/event processing// This variable will be received when// SampleApp_Init() is called.devStates_t SampleApp_NwkState;uint8 SampleApp_TransID; // This is the unique message ID (counter)afAddrType_t SampleApp_Periodic_DstAddr;afAddrType_t SampleApp_Flash_DstAddr;aps_Group_t SampleApp_Group;uint8* nwkaddr_mem;uint8* macaddr_mem;extern uint8 Mac_rssi;uint8 newline = '\n';uint8 rxlen; //接收数据长度uint8* databuf;//接收数据块指针uint8 SampleAppPeriodicCounter = 0;uint8 SampleAppFlashCounter = 0;/********************************************************************* * LOCAL FUNCTIONS*/void SampleApp_HandleKeys( uint8 shift, uint8 keys );void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );void SampleApp_SendPeriodicMessage( void );void SampleApp_SendFlashMessage( uint16 flashTime );void rxCB( uint8 port,uint8 event );uint8 SampleApp_ReadBattery( void );uint8 SampleApp_ReadTemperature( void );void GetDeviceInfo( void );uint8 hextoword1(uint8 t );uint8 hextoword2(uint8 t);uint8 *GetNWKAddr( void );uint8 *GetMACAddr( void );/********************************************************************* * NETWORK LAYER CALLBACKS*//********************************************************************* * PUBLIC FUNCTIONS*//********************************************************************* * @fn SampleApp_Init** @brief Initialization function for the Generic App Task.* This is called during initialization and should contain* any application specific initialization (ie. hardware* initialization/setup, table initialization, power up* notificaiton ... ).** @param task_id - the ID assigned by OSAL. This ID should be* used to send messages and set timers.** @return none*/void SampleApp_Init( uint8 task_id ){SampleApp_TaskID = task_id;SampleApp_NwkState = DEV_INIT;SampleApp_TransID = 0;// Device hardware initialization can be added here or in main() (Zmain.c).// If the hardware is application specific - add it here.// If the hardware is other parts of the device add it in main().#if defined ( SOFT_START )// The "Demo" target is setup to have SOFT_START and HOLD_AUTO_START // SOFT_START is a compile option that allows the device to start// as a coordinator if one isn't found.// We are looking at a jumper (defined in SampleAppHw.c) to be jumpered// together - if they are - we will start up a coordinator. Otherwise,// the device will start as a router.if ( readCoordinatorJumper() )zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;elsezgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;#endif // SOFT_START#if defined ( HOLD_AUTO_START )// HOLD_AUTO_START is a compile option that will surpress ZDApp// from starting the device and wait for the application to// start the device.ZDOInitDevice(0);#endif// Setup for the periodic message's destination address// Broadcast to everyoneSampleApp_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 1SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//(afAddrMode_t)afAddrGroup;SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_Flash_DstAddr.addr.shortAddr = 0xFFFF;//SAMPLEAPP_FLASH_GROUP;// Fill out the endpoint description.SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_epDesc.task_id = &SampleApp_TaskID;SampleApp_epDesc.simpleDesc= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;SampleApp_tencyReq = noLatencyReqs;// Register the endpoint description with the AFafRegister( &SampleApp_epDesc );// Register for all key events - This app will handle all key eventsRegisterForKeys( SampleApp_TaskID );// By default, all devices start out in Group 1SampleApp_Group.ID = 0x0001;osal_memcpy( SampleApp_, "Group 1", 7 );aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );halUARTCfg_t uartConfig;uartConfig.configured = TRUE;uartConfig.baudRate = HAL_UART_BR_38400;uartConfig.flowControl = FALSE;uartConfig.flowControlThreshold = 1;uartConfig.rx.maxBufSize = 255;uartConfig.tx.maxBufSize = 255;uartConfig.idleTimeout = 1;uartConfig.intEnable = TRUE;uartConfig.callBackFunc = rxCB;HalUARTOpen (HAL_UART_PORT_0, &uartConfig);#if defined ( LCD_SUPPORTED )HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );#endif}/********************************************************************** @fn SampleApp_ProcessEvent** @brief Generic Application Task event processor. This function* is called to process all events for the task. Events* include timers, messages and any other user defined events.** @param task_id - The OSAL assigned task ID.* @param events - events to process. This is a bit map and can* contain more than one event.** @return none*/uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ){afIncomingMSGPacket_t *MSGpkt;if ( events & SYS_EVENT_MSG ){MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );while ( MSGpkt ){switch ( MSGpkt->hdr.event ){// Received when a key is pressedcase KEY_CHANGE:SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );break;// Received when a messages is received (OTA) for this endpointcase AF_INCOMING_MSG_CMD:SampleApp_MessageMSGCB( MSGpkt );break;// Received whenever the device changes state in the networkcase ZDO_STA TE_CHANGE:SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);if ( (SampleApp_NwkState == DEV_ZB_COORD)|| (SampleApp_NwkState == DEV_ROUTER)|| (SampleApp_NwkState == DEV_END_DEVICE) ){GetDeviceInfo();// Start sending the periodic message in a regular interval.osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );}else{// Device is no longer in the network}break;default:break;}// Release the memoryosal_msg_deallocate( (uint8 *)MSGpkt );// Next - if one is availableMSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );}// return unprocessed eventsreturn (events ^ SYS_EVENT_MSG);}// Send a message out - This event is generated by a timer// (setup in SampleApp_Init()).if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ){// Send the periodic messageSampleApp_SendPeriodicMessage();// Setup to send message again in normal period (+ a little jitter)osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );// return unprocessed eventsreturn (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);}// Discard unknown eventsreturn 0;}/********************************************************************** Event Generation Functions/********************************************************************** @fn SampleApp_HandleKeys** @brief Handles all key events for this device.** @param shift - true if in shift/alt.* @param keys - bit field for key events. Valid entries:* HAL_KEY_SW_2* HAL_KEY_SW_1** @return none*/void SampleApp_HandleKeys( uint8 shift, uint8 keys ){if ( keys & HAL_KEY_SW_1 ){/* This key sends the Flash Command is sent to Group 1.* This device will not receive the Flash Command from this* device (even if it belongs to group 1).*/SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );}if ( keys & HAL_KEY_SW_2 ){/* The Flashr Command is sent to Group 1.* This key toggles this device in and out of group 1.* If this device doesn't belong to group 1, this application* will not receive the Flash command sent to group 1.*/aps_Group_t *grp;grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );if ( grp ){// Remove from the groupaps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );}else{// Add to the flash groupaps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );}}/********************************************************************* * 节点信息结构体*typedef struct{uint8 SENSOR_TYPE; //传感器类型uint8 NODE_TYPE; //节点类型uint8 NWK_ADDR; //节点网络地址uint8 MAC_ADDR; //节点物理地址MACuint8 PANID; //网络标识uint8 TEMPERATURE; //温度uint8 BATTERY; //电量}NODE_INFO; //节点信息NODE_INFO node_info;**********************************************************************/ /********************************************************************* * LOCAL FUNCTIONS*//********************************************************************* * @fn SampleApp_MessageMSGCB** @brief Data message processor callback. This function processes* any incoming data - probably from other devices. So, based* on cluster ID, perform the intended action.** @param none** @return none*/void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ){uint16 flashTime;/****************************************************************/uint8 str_Src_NWKAddr[ ] = "Src NWKAddr:";uint8 str_Src_MACAddr[ ] = "Src MACAddr:";uint8 str_Src_Tem[ ] = "Src Tem:";uint8 str_Src_Bat[ ] = "Src Bat:";uint8 str_Dst_NWKAddr[ ] = "Dst NWKAddr:";uint8 str_Dst_MACAddr[ ] = "Dst MACAddr:";uint8 str_Dst_Tem[ ] = "Dst Tem:";uint8 str_Dst_Bat[ ] = "Dst Bat:";uint8 str_Data_Len[ ] = "Data Len:";uint8 str_Data[ ] = "Data:";uint8 str_RSSI[ ] = "RSSI:-";uint8 str_LQI[] = "LQI:";//uint8 newline = '\n';uint8 Src_nwk_addr_H;uint8 Src_nwk_addr_L;uint8 Dst_nwk_addr_H;uint8 Dst_nwk_addr_L;uint8 data_Len[3];uint8 *data_pointer;uint8 Src_nwk_addr[6];uint8 Src_mac_addr[18];uint8 Src_Tem_buffer[4];uint8 Src_Bat_buffer[4];uint16 Dst_shortaddr;uint8 Dst_nwk_addr[6];uint8 *Dst_macaddr;uint8 Dst_mac_addr[18];uint8 RSSI_buffer[2];uint8 LQI_buffer[3];uint8 Dst_Tem_Read;uint8 Dst_Tem_buffer[4];uint8 Dst_Bat_Read;uint8 Dst_Bat_buffer[4];/****************************************************************/switch ( pkt->clusterId ){case SAMPLEAPP_PERIODIC_CLUSTERID:/****************************************************************///----------------/*data_length*/data_Len[0] = (pkt->cmd.Data[0])/100+48;data_Len[1] = ((pkt->cmd.Data[0])%100)/10+48;data_Len[2] = (pkt->cmd.Data[0])%10+48;//----------------Src_nwk_addr[0] = 48;Src_nwk_addr[1] = 120;Src_nwk_addr_H = pkt->cmd.Data[1];Src_nwk_addr_L = pkt->cmd.Data[2];Src_nwk_addr[2] = hextoword1(Src_nwk_addr_H);Src_nwk_addr[3] = hextoword2(Src_nwk_addr_H);Src_nwk_addr[4] = hextoword1(Src_nwk_addr_L);Src_nwk_addr[5] = hextoword2(Src_nwk_addr_L);//-----------------Src_mac_addr[0] = 48;Src_mac_addr[1] = 120;for( uint8 i=2;i<18;i++ ){Src_mac_addr[i] = pkt->cmd.Data[1+i];}//-----------------Src_Tem_buffer[0] = pkt->cmd.Data[19];Src_Tem_buffer[1] = pkt->cmd.Data[20];Src_Tem_buffer[2] = ' ';Src_Tem_buffer[3] = 'C';//-----------------Src_Bat_buffer[0] = pkt->cmd.Data[21];Src_Bat_buffer[1] = '.';Src_Bat_buffer[2] = pkt->cmd.Data[22];Src_Bat_buffer[3] = 'V';//-----------------data_pointer = &(pkt->cmd.Data[23]);//-----------------Dst_shortaddr = NLME_GetShortAddr();Dst_nwk_addr_H = (uint8)((Dst_shortaddr&0xff00)>>8);Dst_nwk_addr_L = (uint8)Dst_shortaddr;Dst_nwk_addr[0] = 48;Dst_nwk_addr[1] = 120;Dst_nwk_addr[2] = hextoword1(Dst_nwk_addr_H);Dst_nwk_addr[3] = hextoword2(Dst_nwk_addr_H);Dst_nwk_addr[4] = hextoword1(Dst_nwk_addr_L);Dst_nwk_addr[5] = hextoword2(Dst_nwk_addr_L);//----------------Dst_macaddr = GetMACAddr();Dst_mac_addr[0] = 48;Dst_mac_addr[1] = 120;for( uint8 i=2;i<18;i++ ){Dst_mac_addr[i] = *Dst_macaddr++;}//----------------Dst_Tem_Read = SampleApp_ReadTemperature();Dst_Tem_buffer[0] = (Dst_Tem_Read/10)+'0';Dst_Tem_buffer[1] = (Dst_Tem_Read%10)+'0';Dst_Tem_buffer[2] = ' ';Dst_Tem_buffer[3] = 'C';//----------------Dst_Bat_Read = SampleApp_ReadBattery();Dst_Bat_buffer[0] = (Dst_Bat_Read/10)+'0';Dst_Bat_buffer[1] = '.';Dst_Bat_buffer[2] = (Dst_Bat_Read%10)+'0';Dst_Bat_buffer[3] = 'V';//----------------RSSI_buffer[0] = ((uint8)(~Mac_rssi+1))/10+48;//pkt->rssi/100+48;RSSI_buffer[1] = ((uint8)(~Mac_rssi+1))%10+48;//(pkt->rssi%100)/10+48; //----------------LQI_buffer[0] = pkt->LinkQuality/100+48;LQI_buffer[1] = (pkt->LinkQuality%100)/10+48;LQI_buffer[2] = pkt->LinkQuality%10+48;//----------------//Src NWKAddrHalUARTWrite ( 0, str_Src_NWKAddr, 12 );HalUARTWrite ( 0, Src_nwk_addr, 6 );HalUARTWrite ( 0, &newline, 1 );//Src MACAddrHalUARTWrite ( 0, str_Src_MACAddr, 12 );HalUARTWrite ( 0, Src_mac_addr, 18 );HalUARTWrite ( 0, &newline, 1 );//Src TemHalUARTWrite ( 0, str_Src_Tem, 8 ); HalUARTWrite ( 0, Src_Tem_buffer, 4 ); HalUARTWrite ( 0, &newline, 1 );//Src BatHalUARTWrite ( 0, str_Src_Bat, 8 ); HalUARTWrite ( 0, Src_Bat_buffer, 4 ); HalUARTWrite ( 0, &newline, 1 );//data lengthHalUARTWrite ( 0, str_Data_Len, 9 ); HalUARTWrite ( 0, data_Len, 3 ); HalUARTWrite ( 0, &newline, 1 );//dataHalUARTWrite ( 0, str_Data,5 ); HalUARTWrite ( 0, data_pointer, 11 ); HalUARTWrite ( 0, &newline, 1 );//RSSIHalUARTWrite ( 0, str_RSSI, 6 ); HalUARTWrite ( 0, RSSI_buffer, 2 ); HalUARTWrite ( 0, &newline, 1 );//LQIHalUARTWrite ( 0, str_LQI, 4 ); HalUARTWrite ( 0, LQI_buffer, 3 ); HalUARTWrite ( 0, &newline, 1 );//Dst NWKAddrHalUARTWrite ( 0, str_Dst_NWKAddr, 12 ); HalUARTWrite ( 0, Dst_nwk_addr, 6 ); HalUARTWrite ( 0, &newline, 1 );//Dst MACAddrHalUARTWrite ( 0, str_Dst_MACAddr, 12 ); HalUARTWrite ( 0, Dst_mac_addr, 18 ); HalUARTWrite ( 0, &newline, 1 );//Dst TemHalUARTWrite ( 0, str_Dst_Tem, 8 ); HalUARTWrite ( 0, Dst_Tem_buffer, 4 ); HalUARTWrite ( 0, &newline, 1 );//Dst BatHalUARTWrite ( 0, str_Dst_Bat, 8 );HalUARTWrite ( 0, Dst_Bat_buffer, 4 );HalUARTWrite ( 0, &newline, 1 );HalUARTWrite ( 0, &newline, 1 );HalUARTWrite ( 0, &newline, 1 );/****************************************************************///HalUARTWrite( HAL_UART_PORT_0,(pkt->cmd).Data,(pkt->cmd).DataLength );HalLedBlink( HAL_LED_4, 4, 50, (1000 / 4) );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;}}void rxCB( uint8 port,uint8 event ){uint8 temp[8];HalUARTRead(HAL_UART_PORT_0,temp,8);HalUARTWrite(HAL_UART_PORT_0,temp, 8);}/********************************************************************** @fn SampleApp_SendPeriodicMessage** @brief Send the periodic message.** @param** @return*/void SampleApp_SendPeriodicMessage( void ){uint8 databuf[34];/*nwk_addr*/uint16 nwk_addr;uint8 nwk_addr_H;uint8 nwk_addr_L;nwk_addr=NLME_GetShortAddr();nwk_addr_H=(uint8)((nwk_addr&0xff00)>>8);nwk_addr_L=(uint8)nwk_addr;/*mac_addr*/uint8 *macaddr;macaddr = GetMACAddr();/*Temperature*/uint8 Tem_Read;Tem_Read = SampleApp_ReadTemperature();/*Battery*/uint8 Bat_Read;Bat_Read = SampleApp_ReadBattery();databuf[0] = 34; //一字节存放数据长度datalength databuf[1] = nwk_addr_H; //一字节存放源地址高8位databuf[2] = nwk_addr_L; //一字节存放源地址低8位nwk_addrfor(uint8 i=3;i<19;i++){databuf[i] = *macaddr++;} //mac_addrdatabuf[19] = (Tem_Read/10)+'0';databuf[20] = (Tem_Read%10)+'0'; //temperaturedatabuf[21] = (Bat_Read/10)+'0';databuf[22] = (Bat_Read%10)+'0'; //batterydatabuf[23] = 'v';databuf[24] = 'i';databuf[25] = 'a';databuf[26] =':';databuf[27] = '@';databuf[28] = 's';databuf[29] = 'e';databuf[30] = 'n';databuf[31] = 'd';databuf[32] = 'o';databuf[33] = 'c';if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,34,databuf,//(uint8*)&SampleAppPeriodicCounter,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){}else{// Error occurred in request to send.}}/********************************************************************** @fn SampleApp_SendFlashMessage** @brief Send the flash message to group 1.** @param flashTime - in milliseconds** @return none*/void SampleApp_SendFlashMessage( uint16 flashTime ){uint8 buffer[3];buffer[0] = (uint8)(SampleAppFlashCounter++);buffer[1] = LO_UINT16( flashTime );buffer[2] = HI_UINT16( flashTime );if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc,SAMPLEAPP_FLASH_CLUSTERID,3,buffer,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){}else{// Error occurred in request to send.}}/****************************************************************************** * @fn SampleApp_ReadBattery** @brief Reports battery sensor reading** @param** @return*/// ADC definitions for CC2430 from the hal_adc.c file#define HAL_ADC_REF_125V 0x00 /* Internal 1.25V Reference */#define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */#define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */#define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */#define HAL_ADC_CHN_VDD3 0x0f /* Input channel: VDD/3 */#define HAL_ADC_CHN_TEMP 0x0e /* Temperature sensor */uint8 SampleApp_ReadBattery( void ){#if defined HAL_MCU_CC2430uint16 value;/* Clear ADC interrupt flag */ADCIF = 0;ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3);/* Wait for the conversion to finish */while ( !ADCIF );/* Get the result */value = ADCL;value |= ((uint16) ADCH) << 8;/** value now contains measurement of Vdd/3* 0 indicates 0V and 32767 indicates 1.25V* voltage = (value*3*1.25)/32767 volts* we will multiply by this by 10 to allow units of 0.1 volts*/value = value >> 6; // divide first by 2^6value = value * 37.5;value = value >> 9; // ...and later by 2^9...to prevent overflow during multiplication return value;#endif // CC2430。
/*zigbee传输协议:节点数、传输频率(周期)、传输距离、传输数据种类、数据可靠性要求,节点拓扑结构组成。
基本流程1.初始化网络地址,打开接收机或关闭接收机。
2.初始化basicRfConfig,确定网络ID、信道、是否需要应答、是否采用加密机制等。
3.初始化周边设备,如时钟、各个I/O口等。
4.事件的处理,如发送报文或接受报文后的数据处理等。
typedef signed char int8;typedef unsigned char uint8;typedef signed short int16;typedef unsigned short uint16;大小typedef signed long int32;typedef unsigned long uint32;*/类容大概:1.定义接/收缓存区大小。
2.初始化数据长度。
3.定义点对点通讯的网络ID、信道、通讯地址。
4.创建basicRfCfg_t的静态数据结构类。
5.定义数据通讯的格式6.定义网络ID、信道、通讯地址的数组大小。
7.编写主函数a)定义数组i和config_flag[1]标记,长整型len变量;b)初始化单片机,串口波特率,DMA;c)config_flag标记flash情况并向串口发送,判断标记看是否需要初始化flash驱动设置并复位串口;d)初始化无线配置并向串口发送,标记Flash驱动情况;e)编写串口命令处理i.编写命令固定头给pTxData[]并打开1、2号灯;ii.编写while循环不断读取串口数据;iii.uRxlen和uRxData归0;iv.读串口数据,返回长度给uRxlen,数据内容给uRxData数组,延迟5秒;v.编写zigbee配置数据(源于串口)处理:如果收到数据判断类型并标记在config_flag[0],共有以下三种情况:1.FF,FA:标记0x02,代表主控端,传感器,继电器配置。
2.FF,FB:标记0x03,代表读取配置数据给串口。
Zigbee基础实验-简单通信编程Zigbee基础实验(6)—简单通信编程简单通信编程实验中两节点分别充当开关和电灯,通过在开关节点上的操作来控制电灯节点。
源代码:#include <hal_lcd.h>#include <hal_led.h>#include <hal_joystick.h>#include <hal_assert.h>#include <hal_board.h>#include <hal_int.h>#include "hal_mcu.h"#include "hal_button.h"#include "hal_rf.h"#include "util_lcd.h"#include "basic_rf.h"#define RF_CHANNEL 25 // 信道选择。
// 定义各个参数的值#define PAN_ID 0x2007 //网络ID#define SWITCH_ADDR 0x2520 //开关节点的地址#define LIGHT_ADDR 0xBEEF //电灯节点的地址#define APP_PAYLOAD_LENGTH 1 //负载字节的长度,信息的长度。
#define LIGHT_TOGGLE_CMD 0 //被传送的开关命令。
//节点状态。
0为空闲#define IDLE 0#define SEND_CMD 1// 定义该节点所承担的任务(开关或电灯)#define NONE 0#define SWITCH 1#define LIGHT 2#define APP_MODES 2static uint8 pTxData[APP_PAYLOAD_LENGTH]; //发送数组static uint8 pRxData[APP_PAYLOAD_LENGTH]; //接收数组static basicRfCfg_t basicRfConfig;// 模式选择菜单static menuItem_t pMenuItems[] ={"Switch", SWITCH,"Light", LIGHT};static menu_t pMenu ={pMenuItems,N_ITEMS(pMenuItems)};static void appLight(); //实现电灯功能static void appSwitch(); //实现远程开关功能static uint8 appSelectMode(void); //功能选择static void appLight() //实现电灯功能{halLcdWriteLine(HAL_LCD_LINE_1, "Light");halLcdWriteLine(HAL_LCD_LINE_2, "Ready");// 初始化射频模块basicRfConfig.myAddr = LIGHT_ADDR; //网络地址if(basicRfInit(&basicRfConfig)==FAILED) {HAL_ASSERT(FALSE); //初始化错误处理}basicRfReceiveOn(); //打开接收功能。
点对点实验现象:发射端红灯亮、黄灯灭接收端红灯闪、黄灯灭接通时,两端都红黄灯交替闪烁SET_MAIN_CLOCK_SOURCE(CRYSTAL); //hal.hRFPWR = 0x04;while(RFPWR & 0x10);initUART();void initUART(void) //通用异步接收/发送装置hal.h{// Setup for UART0IO_PER_LOC_UART0_AT_PORT0_PIN2345();SET_MAIN_CLOCK_SOURCE(CRYSTAL);UART_SETUP(0, 57600, HIGH_STOP);UTX0IF = 1;}IO_DIR_PORT_PIN(port, pin, dir) //管脚输入输出设置IO_OUT IO_INvoid initRfTest(void) //射频测试初始化{UINT32 frequency = 2405000;INIT_GLED(); //RF04EB.hINIT_YLED();radioInit(frequency, myAddr); //cul radio.c spp.c}INT_GLOBAL_ENABLE(INT_ON); // 中断总开关hal.hBYTE sendBuffer[] = "Hello"; //发送数据应答与否cul radio.c spp.c res = radioSend(sendBuffer, sizeof(sendBuffer), remoteAddr, DO_ACK ); //DO_NOT_ACK #define RECEIVE_TIMEOUT 800 //接收数据cul radio.c spp.cBYTE* receiveBuffer;BYTE length;BYTE res;BYTE sender;res = radioReceive(&receiveBuffer, &length, RECEIVE_TIMEOUT, &sender);点对多点实验现象:发射端1、2 红黄灯同时闪烁后交替闪烁接收端红黄灯同时闪烁后全灭发射端1、2同时连接上接收端时,接收端红黄灯交替闪烁1端连接上时,接收端黄灯闪烁闪烁时间是交替闪烁的十倍左右2端连接上时,接收端红灯闪烁闪烁时间是交替闪烁的十倍左右为何修改需要应答时,不能正常工作???暂时认为接收端周期性的切换信道,故应答较不容易#define NO_1_FREQUENCY 2480000 //信道间隔5MHz P21#define NO_2_FREQUENCY 2483000 //KHz为单位void initRfTest(UINT32 frequency) //射频测试初始化{#ifdef WXL_TX1frequency = NO_1_FREQUENCY;#endif#ifdef WXL_TX2frequency = NO_2_FREQUENCY;#endif//T1:2 480 000 , T2:2 420 000INIT_YLED(); //RF04EB.hINIT_RLED();radioInit(frequency, myAddr); //cul radio.c spp.c}#if defined(WXL_RX) //通道切换接收{myAddr = ADDRESS_0; //myAddr = 0x01; 由于接收是切换,所以可以将两个发射端地址设置为相同remoteAddr = ADDRESS_1; //remoteAddr = 0x02;while(1){Receivesel = (Receivesel+1)%3;//自动切换信道if(Receivesel ==0)Receivesel = 1;TryToReceive = TRY_TO_RECEIVE; //每次接收时的尝试链接接收次数if(Receivesel==1)frequency = NO_1_FREQUENCY;if(Receivesel==2)frequency = NO_2_FREQUENCY;/*Receivesel = (Receivesel+1)%2;//自动切换信道TryToReceive = TRY_TO_RECEIVE;if(Receivesel==0)frequency = NO_1_FREQUENCY;if(Receivesel==1)frequency = NO_2_FREQUENCY;*/initRfTest(frequency);receiveMode();}}ZigBee2004实验现象:星型网络协调器开黄灯一直亮(代表建立好网络)、红灯不亮终端红黄灯全灭RFD 模块加入到网络中时,协调器黄灯先闪烁两下后协调器和终端黄灯一直亮、红灯闪烁串状网络协调器开黄灯一直亮(代表建立好网络)、红灯不亮路由器红黄灯全灭终端红黄灯全灭路由器加入到网络中时,协调器黄灯闪烁两下、路由器黄灯亮红灯灭终端加入网络时,加入其和协调器、路由器的距离较短者当加入时,路由器或者协调器黄灯闪烁两下如果关掉路由器节点的电源,RFD 节点和网络协调器的通信就会中断。
ZigBee模块通信实现(电路介绍与程序分析)产品名:ZigBee模块型号:ZICM2410 PO-2厂商:广州周立功公司代理(美国CEL公司的MeshConnect模块)参数:* 103db链路预算;* 接收灵敏度:-97dbm@ 1.5V* 发送功率:+6dbm@1.5V* 3000英尺无障碍传输距离* 最低睡眠电流:;SC16IS752IPW 芯片; LC11C14(ARM M0内核)从原理图可以看出,ZigBee模块的RXD\TXD接在了SC16IS752IPW芯片的RXB\TXB上,而该芯片的CS\SI\SO\SCLK接在LPC11C14的PIO2_0\PIO2_1\PIO2_2\PIO2_3\PIO3_3上。
说明LPC11C14主控芯片是通过SPI间接与ZigBee模块通讯,所以我们只需要关注SC16IS752IPW芯片即可,往该芯片发送数据,ZigBee自然也能收到数据。
数据流向:应用程序 ; M0的SPI控制器 ;SC16IS752IPW ; ZigBee模块程序流程:1、初始化LPC11C14的SSP1 的GPIO引脚,即PIO2_0\PIO2_1\PIO2_2\PIO2_3/* 初始化响应PIO引脚ssp.c *//* arg1:SSPI0或SSPI1*/void SPI_IOConfig(uint8_t portNum){if(portNum == 0){/* 此处为通道0的代码未贴出*/}else/* port number 1 */{// 主要设置 SSP1 使之能与 SC16IS752IPW 通信间接与 ZigBee 通信LPC_SYSCON->;PRESETCTRL |= (0x1;SYSAHBCLKCTRL |= (1;SSP1CLKDIV = 0x02;/* Divided by 2 设置 SSP1 时钟分频 48Mhz/2=24Mhz*/LPC_IOCON->;PIO2_2 &= ~0x07;/* SSP I/O config */LPC_IOCON->;PIO2_2 |= 0x02;/* SSP MISO 将PIO2_2设置为 SSP MISO 模式*/LPC_IOCON->;PIO2_3 &= ~0x07;LPC_IOCON->;PIO2_3 |= 0x02;/* SSP MOSI 将PIO2_3设置为 SSP MOSI 模式*/LPC_IOCON->;PIO2_1 &= ~0x07;LPC_IOCON->;PIO2_1 |= 0x02;/* SSP CLK将PIO2_1设置为 SSP 时钟 *//* Enable AHB clock to the GPIO domain. */LPC_SYSCON->;SYSAHBCLKCTRL |= (1;PIO2_0 &= ~0x07;/* SSP SSEL is a GPIO pin 设置PIO2_0 作为普通IO管脚功能 *//* port2, bit 0 is set to GPIO output and high */ GPIOSetDir( PORT2, 0, 1 );// 设置为输出GPIOSetValue( PORT2, 0, 1 ); // 输出高电平暂时不使能该器件是片选引脚}}2、初始化 SSP1 寄存器ssp.c/* arg1:SSPI0或SSPI1arg2:传送位数 arg3:时钟分配*/void SPI_Init(uint8_t portNum, uint8_t Bit, uint8_t EvenDiv){uint8_ti, Dummy=Dummy;if(portNum == 0){/* 此处为通道0的代码未贴出*/}else{LPC_SSP1->;CR0 = 0x0700 | (Bit-1); // (Bit-1)=0b0111 8位传输串行时钟速率、总线类型、数据长度LPC_SSP1->;CPSR = EvenDiv;// 时钟预分频寄存器设置为2分频 ->;48Mhz/2=24Mhzfor ( i = 0; i ;DR;/* clear the RxFIFO 数据寄存器,读空则接受FIFO 写满则发送 FIFO */NVIC_EnableIRQ( SSP1_IRQn );// 使能中断LPC_SSP1->;CR1 = SSPCR1_SSE;// SSP1以正常模式与串行总线上的其它设备相互通信。
ZigBee ——node(节点)、profile(规约)、邻居表⼏个概念:node(节点):在zigbee堆栈中最多有三种节点:Coordinator(协调器)、Router(路由器)、End Device(终端)。
其中Coordinator负责选择⼯作频段,建⽴⽹络,允许⼦设备加⼊⽹络;Router负责传递消息,允许⼦设备加⼊⽹络;End Device只负责收发消息。
⼀个⽹络中可以有若⼲Router和End Device,但只能有⼀个Coordinator。
下⾯⼏个图说得更清楚点profile:有⼈将profile翻译为“规约”,它规定了设备的具体应⽤环境(这是由zigbee使⽤联盟制定的,我们只能选择其⼀)。
其中stack profile定义了⽹络类型、深度等;application profile针对给定的stack profile定义了不同功能的标准函数,说明了设备类型、接⼝、如何传输数据等等。
总之,profile就是对设备的描述。
⽬的是形成标准,便于不同制造商间产品的兼容。
descriptor:cluster:attribute:endpoint:endpoint的作⽤举例说明下:假如我们想让node1的开关1控制node2的灯1、2、3,开关2只控制灯4。
但是由于节点间信息只依靠⽹络地址定位,所以node2接收到node1的控制信息后,⽆法判断究竟是哪个开关的控制信息。
所以引⼊了endpoint概念(这和TCP/IP协议⾥的“端点”概念很像),给node2两个endpoint(端⼝),⼀个对应开关1,⼀个对应开关2。
这样node2的应⽤程序就能通过接收到的endpoint来区别究竟是接收到哪个开关的信息了。
杂记:ZigBee⽹络层的主要功能是路由,路由算法是它的核⼼。
⽬前ZigBee⽹络层主要⽀持两种路由算法——树状路由和⽹状路由。
树状路由(具体可以参考ZigBee的协议栈规范)把整个⽹络看作是以协调器为根的⼀棵树,因为整个⽹络是由协调器所建⽴的。
协议栈无线透传编程原理:第一个功能:协调器的组网,终端设备和路由设备发现网络以及加入网络//第一步:Z-Stack 由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统int main( void ) { .......// Initialize the operating systemosal_init_system(); //第二步,操作系统初始化......osal_start_system(); //初始化完系统任务事件后,正式开始执行操作系统......}//第二步,进入 osal_init_system()函数,执行操作系统初始化uint8 osal_init_system( void ) //初始化操作系统,其中最重要的是,初始化操作系统的任务{// Initialize the Memory Allocation Systemosal_mem_init();// Initialize the message queueosal_qHead = NULL;// Initialize the timersosalTimerInit();// Initialize the Power Management Systemosal_pwrmgr_init();// Initialize the system tasks.osalInitTasks(); //第三步,执行操作系统任务初始化函数// Setup efficient search for the first free block of heap.osal_mem_kick();return ( SUCCESS );}//第三步,进入osalInitTasks()函数,执行操作系统任务初始化void osalInitTasks( void ) //第三步,初始化操作系统任务{uint8 taskID = 0;tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//任务优先级由高向低依次排列,高优先级对应 taskID 的值反而小macTaskInit( taskID++ ); //不需要用户考虑nwk_init( taskID++ ); //不需要用户考虑Hal_Init( taskID++ ); //硬件抽象层初始化,需要我们考虑#if defined( MT_TASK )MT_TaskInit( taskID++ );#endifAPS_Init( taskID++ ); //不需要用户考虑#if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ );#endifZDApp_Init( taskID++ ); //第四步,ZDApp层,初始化,执行ZDApp_init函数后,如果是协调器将建立网络,如果是终端设备将加入网络。
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_Init( taskID++ );#endifSerialApp_Init( taskID ); //应用层SerialApp层初始化,需要用户考虑在此处设置了一个按键触发事件,//当有按键按下的时候,产生一个系统消息}//第四步,进入ZDApp_init()函数,执行ZDApp层初始化//The first stepvoid ZDApp_Init( uint8 task_id ) //The first step,ZDApp层初始化。
{// Save the task IDZDAppTaskID = task_id;// Initialize the ZDO global device short address storageZDAppNwkAddr.addrMode = Addr16Bit;ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.// Check for manual "Hold Auto Start"ZDAppCheckForHoldKey();// Initialize ZDO items and setup the device - type of device to create.ZDO_Init();// Register the endpoint description with the AF// This task doesn't have a Simple description, but we still need // to register the endpoint.afRegister( (endPointDesc_t *)&ZDApp_epDesc );#if defined( ZDO_USERDESC_RESPONSE )ZDApp_InitUserDesc();#endif // ZDO_USERDESC_RESPONSE// Start the device?if ( devState != DEV_HOLD ) //devState 初值为DEV_INIT ,所以在初始化ZDA层时,就执行该条件语句{ZDOInitDevice( 0 ); //The second step, 接着转到ZDOInitDevice()函数,执行The third step;}else{// Blink LED to indicate HOLD_STARTHalLedBlink ( HAL_LED_4, 0, 50, 500 );}ZDApp_RegisterCBs();} /* ZDApp_Init() *///The third step,执行ZDOInitDevice()函数,执行设备初始化uint8 ZDOInitDevice( uint16 startDelay ) //The third step, ZDO层初始化设备,{.......// Trigger the network startZDApp_NetworkInit( extendedDelay ); //网络初始化,跳到相应的函数里头,执行The fourth step.......}//The fouth step,执行 ZDApp_NetWorkInit()函数void ZDApp_NetworkInit( uint16 delay ) //The fourth step,网络初始化{if ( delay ){// Wait awhile before starting the deviceosal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT,delay ); //发送ZDO_NETWORK_INIT(网络初始化)消息到 ZDApp层,转到//ZDApp层,执行The fifth step , ZDApp_event_loop() 函数}else{osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );}}//The fifth step,转到ZDApp_event_loop()函数UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events ){if ( events & ZDO_NETWORK_INIT ) //The fivth step,网络初始化事件处理{// Initialize apps and start the networkdevState = DEV_INIT;//设备逻辑类型,启动模式,信标时间,超帧长度,接着转到The sixth step,去启动设备,接着执行The sixth step,转到ZDO_StartDevice() ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,DEFAULT_BEACON_ORDER,DEFAULT_SUPERFRAME_ORDER );// Return unprocessed eventsreturn (events ^ ZDO_NETWORK_INIT);}}//The sixth step,执行ZDO_StartDevice()函数,启动设备void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder ) //The sixth step{......if ( ZG_BUILD_COORDINATOR_TYPE && logicalType ==NODETYPE_COORDINATOR ) //当设备作为协调器时,执行这个条件语句。
{if ( startMode == MODE_HARD ){devState = DEV_COORD_STARTING;//向网络层发送网络形成请求。
当网络层执行NLME_NetworkFormationRequest()建立网络后,将给予 ZDO层反馈信息。
// 接着转到The seventh step,去执行ZDApp层的ZDO_NetworkFormationConfirmCB()函数ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,zgDefaultStartingScanDuration, beaconOrder,superframeOrder, false );}if ( ZG_BUILD_JOINING_TYPE && (logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) ) //当为终端设备或路由时{if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) ){devState = DEV_NWK_DISC;// zgDefaultChannelList与协调器形成网络的通道号匹配。