ZigBee组网实验:多终端节点向协调器发送数据&协调器给终端节点发送数据

https://blog.csdn.net/mchen_6431/article/details/80562510

2018年06月04日 08:35:29 mchen_6431 阅读数:3655

1、多终端节点向协调器发送数据

本节介绍一个终端节点发送数据,协调器接收并打印到串口上的例子。对应的程序代码:

ZStack-CC2530-2.5.1a\Projects\zstack\Samples\SendTest

(1)系统环境配置

文档名称:SendTest程序及ZIGBEE入门介绍

硬件平台:IOT-NODE2530

软件平台:IAR EW8051-8103

首先到TI官网下载最新的Zstack协议栈,http://www.ti.com.cn/tool/cn/Z-STACK

本文使用的协议栈为swrc126.zip (22MB) - contains ZStack-CC2530-2.5.1-a.exe

下载完后,直接安装即可。默认安装到:C:\Texas Instruments\ZStack-CC2530-2.5.1a;

如果更改了安装目录,请自行查找对应目录。安装完了,对应的文件夹如下:

请在开发前详细了解Documents下的文档,这些文档对了解Zstack协议栈很有帮助,可以重点了解以下三个文档:

Z-Stack Sample Application For CC2530DB.pdf

Z-Stack Sample Applications.pdf

Z-Stack User's Guide - CC2530DB.pdf

安装这三个文档一步步做下来,基本能了解Zstack协议栈的开发。

在Zstack中如果使用自己的名称来命名工程,如SendTest工程请参考C:\Texas Instruments\ZStack-CC2530-2.5.1a\Documents

Create New Application For CC2530DB.pdf文档。

程序代码见附件,IAR工程中已经进行了适当处理,可以脱离TI的环境单独运行。

(2)协议栈构架

首先打开程序代码,找到IAR工程,打开后可以看到TI ZStack的大体框架,

如下图所示:

§ App:应用层目录,这也是用户创建各种不同工程的区域;

§ HAL:硬件层目录,包括着与硬件相关的配置及操作函数;

§ MAC:MAC层目录,包括着MAC层配置参数文件及MAC LIB库的函数接口文件;

§ MT:包括基于AF层的调试函数文件,主要包括串口等通信函数;§ NWK:网络层目录,包括着网络层配置参数文件及MAC LIB库的函数接口文件;

§ OSAL:系统目录,包括协议栈系统文档;

§ Profile:AF层目录,包括AF层处理函数文件;

§ Security:安全层目录,安全层处理函数,比如加密函数等;

§ Services:地址处理函数目录,包括着地址模式的定义及地址处理函数文档;Tools:工程配置目录,包括协议栈等配置文档;

§ ZDO ZDO ZDO ZDO:层目录,包括层处理函数文档;

§ ZMac:MAC层目录,包括MAC层参数配置及MAC层LIB库函数回调处理函数

§ ZMain:主函数目录,包括入口函数及硬件配置文件;

§ Output:输出文件目录,这是EW8051IDE自动生成的;

(3)程序的编译和下载

(i)项目属性设置

选择菜单Project->Options、右击菜单options或者通过热键(ALT+F7)打开工程属性设置。

也可以鼠标右击workspace中的工程名,如下图:

打开属性设置后如图:

一般来说,如果是在TI的协议栈的进行修改,里面的设置就不用修改。如果要具体了解各参数,请参照IAR文档。

这里值得注意的是Texas Instruments下的Download的标签,如果第一次用建议像如图那样选择,这样是将整个FALSH擦除后再Download

(ii)编译与烧写

选择Project->Debug或者热键(Ctrl+D)给开发板上的Zigbee模块下载程序。

也可以直接点IAR的如下图标来编译和下载程序,最后一个是编译并下载;

同时也可以在workspace中的工程名上点击鼠标右键来选择编译。

下图显示为DEBUG时的选项:

在调试程序时,DEBUG还是非常有用的,它能告诉你程序运行到哪了,程序为什么没有出现你预期的结果等,因此,选择一个仿真器还是有用的,并且有些仿真器加上一个节点就可以充当packet sniffer工具,对空中的包能进行实时跟踪。下图是在深联科技仿真器抓到的本例子的数据包,以后会对这些包结构做一定解析,如果也可以参考ZigBee协议栈文档,上面对这些包结构有详细的说明。

从图中的RSSI中可以看到节点的性能,负数越接近0表明节点性能越好,通信距离越长,并且协调器已经给一个终端节点分配了短地址0x796F(该地址可以通过计算得到,见IEEE 802.15.4文档)。

(4) 实验程序简单分析

在本实验中用户涉及的程序主要有OSAL_SendTest.c,SendTest.c,SendTest.h。其他程序协议栈程序只做简单修改就行。比如我使用的是IOT-NODE2530需要修改一下串口函数等。因为硬件平台的差异性,大家可以根据实际进行修改。下面主要介绍上面提到的三个函数。

OSAL_SendTest.c函数是协议栈操作系统处理函数,这个函数实现对本实验中需要的任务的添加,具体函数如下:

  1. const pTaskEventHandlerFn tasksArr[] = {

  2. macEventLoop,

  3. nwk_event_loop,

  4. Hal_ProcessEvent,

  5. #if defined( MT_TASK )

  6. MT_ProcessEvent,

  7. #endif

  8. APS_event_loop,

  9. #if defined ( ZIGBEE_FRAGMENTATION )

  10. APSF_ProcessEvent,

  11. #endif

  12. ZDApp_event_loop,

  13. #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

  14. ZDNwkMgr_event_loop,

  15. #endif

  16. SendTest_ProcessEvent

  17. };

最后一条语句是添加本实验任务的。tasksArr的使用的参数请参照OSAL API.pdf文档。

SendTest.c是本实验用户程序的具体实现。下面来分析一下该程序。

首先,本程序不考虑协议栈绑定等相关内容,在程序中屏蔽了绑定,实验数据只是从终端节点传送到协调器节点,对于ZIGBEE网络协调器节点的短地址始终为0x0000,因此在用发送函数时,目的地址写上0x0000就能传到协调器。

其次,两个设备的 endPoint要保持一致,否则将不能通信。在程序中将SendTest_DstAddr.endPoint = SendTest_ENDPOINT;(SendTest_ENDPOINT=10)。

程序实现结果是:协调器的串口上输出如图内容:

本实例支持多个终端同时向协调器发送数据。为了区分是哪个节点发送的数据,在数据前面加上01 02 03...做区别,如上图示,为三个终端节点同时向协调器发送数据的例子。

对于怎么修改数据请参考下面代码,其中theMessageData[]为用户需要发的数据:

  1. static void SendTest_SendTheMessage( void )

  2. {

  3. char theMessageData[] = "02 Welcome to use this sendTest ----chenym\n--The test is based on IOT-NODE2530--\n";

  4. if ( AF_DataRequest( &SendTest_DstAddr, &SendTest_epDesc,

  5. SENDTEST_CLUSTERID,

  6. (byte)osal_strlen( theMessageData ) + 1,

  7. (byte *)&theMessageData,

  8. &SendTest_TransID,

  9. AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

  10. {

  11. // Successfully requested to be sent.

  12. }

  13. else

  14. {

  15. // Error occurred in request to send.

  16. }

  17. }

只有在终端节点加入网络后才能发送数据给协调器,一旦网络中断数据就不再发,这个机制是通过判断网络状态来实现的,代码如下:

  1. if ( (SendTest_NwkState == DEV_END_DEVICE) ) //只在设备为终端节点时,才发送数据

  2. {

  3. // Start sending "the" message in a regular interval.

  4. osal_start_timer( SendTest_SEND_MSG_EVT,

  5. SendTest_SEND_MSG_TIMEOUT );

  6. }

上面语句中SendTest_SEND_MSG_EVT是一个事件,只在定时器时间到才触发该事件,在程序中设置

#define SendTest_SEND_MSG_TIMEOUT 1000

也就是在网络建成后每一秒向协调器发送数据。

对于操作系统的介绍请参考文档,以后我也会就这个做些介绍。

SendTest_ProcessEvent函数为操作系统的一任务(上面已经介绍了怎么加入任务),总是被周期性轮询。当检测到一个event就执行相关程序。

在一个任务中有16个事件,用16位来表示,每一位代表一个事件,其中0x8000为系统事件SYS_EVENT_MSG,任务还和task_id有关。

MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SendTest_TaskID );

程序段是将收到的消息存放到MSGpkt指定的区域中。

(下面代码,部分代码与程序可能有出入,请以具体程序参考。)

  1. while ( MSGpkt )//消息不为空

  2. { switch ( MSGpkt->hdr.event )

  3. {

  4. case KEY_CHANGE://按键状态改(本实验不涉及)

  5. SendTest_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );

  6. break;

  7. case AF_DATA_CONFIRM_CMD://AF层数据发送完成后确认报告

  8. // This message is received as a confirmation of a data packet sent.

  9. // The status is of ZStatus_t type [defined in ZComDef.h]

  10. // The message fields are defined in AF.h

  11. afDataConfirm = (afDataConfirm_t *)MSGpkt;

  12. sentEP = afDataConfirm->endpoint;

  13. sentStatus = afDataConfirm->hdr.status;

  14. sentTransID = afDataConfirm->transID;

  15. (void)sentEP;

  16. (void)sentTransID;

  17. HAL_TOGGLE_LED1();//加入LED1来指示数据发送出

  18. // Action taken when confirmation is received.

  19. if ( sentStatus != ZSuccess )

  20. {

  21. // The data wasn't delivered -- Do something

  22. }

  23. break;

  24. case AF_INCOMING_MSG_CMD://新的报文来

  25. HAL_TOGGLE_LED1();//加入LED1来指示新报文来

  26. SendTest_MessageMSGCB( MSGpkt );//新报文回调函数

  27. break;

  28. case ZDO_NEW_DSTADDR://ZDO终端地址改变,这个是在加入绑定后引起的,本实验不涉及

  29. ZDO_NewDstAddr = (ZDO_NewDstAddr_t *)MSGpkt;

  30. dstEP = ZDO_NewDstAddr->dstAddrDstEP;

  31. dstAddr = &ZDO_NewDstAddr->dstAddr;

  32. SendTest_DstAddr.addrMode = (afAddrMode_t)dstAddr->addrMode;

  33. SendTest_DstAddr.endPoint = dstEP;

  34. SendTest_DstAddr.addr.shortAddr = dstAddr->addr.shortAddr;

  35. break;

  36. case ZDO_STATE_CHANGE://网络状态改变,在这里启动第一次数据传输

  37. SendTest_NwkState = (devStates_t)(MSGpkt->hdr.status);

  38. if ( (SendTest_NwkState == DEV_END_DEVICE) ) //只在设备为终端节点时,才发送数据

  39. {

  40. // Start sending "the" message in a regular interval.

  41. osal_start_timer( SendTest_SEND_MSG_EVT,

  42. SendTest_SEND_MSG_TIMEOUT );

  43. }//这个在上面已经有介绍

  44. break;

  45. default:

  46. break;

  47. }

  48. // Release the memory

  49. osal_msg_deallocate( (uint8 *)MSGpkt );

  50. // Next

  51. MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SendTest_TaskID );

  52. }

  53. if ( events & SendTest_SEND_MSG_EVT )//如果事件为消息传送事件

  54. {

  55. // Send "the" message

  56. SendTest_SendTheMessage();//调用消息发送函数

  57. // Setup to send message again

  58. if ( (SendTest_NwkState == DEV_END_DEVICE) )//解释同前

  59. osal_start_timer( SendTest_SEND_MSG_EVT,

  60. SendTest_SEND_MSG_TIMEOUT );

  61. // return unprocessed events

  62. return (events ^ SendTest_SEND_MSG_EVT);

  63. }

  64. 消息回调函数实现:

  65. void SendTest_MessageMSGCB( afIncomingMSGPacket_t *pkt )

  66. {

  67. switch ( pkt->clusterId )

  68. {

  69. case SendTest_CLUSTERID:

  70. // "the" message

  71. #if defined( LCD_SUPPORTED )

  72. HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );

  73. #elif defined( WIN32 )

  74. WPRINTSTR( pkt->cmd.Data );

  75. #endif

  76. HalUARTWrite( HAL_UART_PORT_1,(pkt->cmd).Data, (pkt->cmd).DataLength);//将接收到的数打印到串口上

  77. break;

  78. }

  79. }

对于串口的初始化在SendTest_Init函数中,上面的红色显示函数就是将收到的数据信息打印在串口终端上。

下面介绍一下,发送函数AF_DataRequest

该函数用于发送数据

函数声明:

  1. afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,

  2. uint16 cID, uint16 len, uint8 *buf, uint8 *transID,

  3. uint8 options, uint8 radius );

具体参数:

dstAddr:目的地址指针,其中的地址模式是:afAddrNotPresent(用于绑定)、afAddrGroup(传送到一组目的节点)afAddrBroadcast(广播发送)、afAddr16Bit(直接发送),在本实验中afAddr16Bit地址模式,在SendTest_Init初始化中将SendTest_DstAddr.addrMode 设置为(afAddrMode_t)Addr16Bit;

srcEP:发送的endpoint的Endpoint描述的指针

cID:Cluster ID,实验中使用SendTest_CLUSTERID

len:发送数据包长度,该长度不包括ZIGBEE包中的帧头和帧尾,只是用户数据的长度

buf:用户发送数据区指针

transID:传输序号指针,该序号将随发送的次数增加而增加

options:具体参数参照下表:

(5)生成hex文件

如果需要将代码生成hex文件,请在协议栈里设置:

(1)首先打开f8w2530.xcl文件

位置为:

修改下面两行代码:

// Include these two lines when generating a .hex file for banked code model:

-M(CODE)[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*\

_NR_OF_BANKS+_FIRST_BANK_ADDR=0x8000

//

将注释去掉。不过在用debug调试模式时,需要注释,请区别对待。否则会提示如下警告:

另外进行如下设置:

重新编译就能生成hex文件了,对应的位置为:

SendTest\CC2530DB\EndDeviceEB\Exe 文件夹内。

(6) 用cc debugger调试程序

安装(5)的设置,首先注释掉下面两行:

// Include these two lines when generating a .hex file for banked code model:

//-M(CODE)[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*\

//_NR_OF_BANKS+_FIRST_BANK_ADDR=0x8000

//

另外进行如下设置:

请用户区分对待。

2、协调器控制终端发送数据

在实验1中,只实现了终端enddevice主动向协调器发送数据的情况。本例子实现由协调器发送命令让终端开始传输数据。对应的程序代码为:ZStack-CC2530-2.5.1a\Projects\zstack\Samples\SendTest_Cor

(1)系统环境配置

文档名称:SendTest程序及ZIGBEE入门介绍

硬件平台:IOT-NODE2530

软件平台:IAR EW8051-8103

其他见实验9.

(2)程序实现与分析

现在简单实现如下:

(i)、加入串口回调函数并在SendTest.c的开始声明函数

  1. void testCB(uint8 port,uint8 event)

  2. {

  3. uint8 temp[9];

  4. uint8 IEEE_ADDR[8];

  5. HAL_TOGGLE_LED1();

  6. if (event & HAL_UART_RX_TIMEOUT)

  7. {

  8. HalUARTRead(HAL_UART_PORT_0,temp,9);

  9. for(uint8 i=0;i<8;i++)

  10. IEEE_ADDR[i]=temp[i];

  11. APSME_LookupNwkAddr ( IEEE_ADDR, &SendTest_DstAddr.addr.shortAddr);

  12. if (SendTest_DstAddr.addr.shortAddr!=0)

  13. AF_DataRequest( &SendTest_DstAddr, &SendTest_epDesc,

  14. SENDTEST_CLUSTERID,

  15. 9,

  16. (byte *)&temp,

  17. &SendTest_TransID,

  18. AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) ;

  19. }

  20. }

在这个函数中完成从串口接收到数据,并且将其发送给终端节点。为了获得终端节点的短地址,用了APSME_LookupNwkAddr ,该函数用于由长地址获得短地址。该函数的使用说明请参考Z-Stack API.pdf。该函数有局限性,只能从自身的地址空间中查找短地址,而不是通过无线查询。

(ii)、终端节点不像实验1那样直接发送数据给协调器,而是在收到协调器发送的控制信息后,做相应处理。

处理程序如下:

  1. static void SendTest_MessageMSGCB( afIncomingMSGPacket_t *pkt )

  2. {

  3. switch ( pkt->clusterId )

  4. {

  5. case SENDTEST_CLUSTERID:

  6. // "the" message

  7. #if defined( LCD_SUPPORTED )

  8. HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );

  9. #elif defined( WIN32 )

  10. WPRINTSTR( pkt->cmd.Data );

  11. #endif

  12. HalUARTWrite( HAL_UART_PORT_0,(pkt->cmd).Data, (pkt->cmd).DataLength);//将接收到的数打印到串口上

  13. if((pkt->cmd).Data[8]==0x55)

  14. {

  15. HAL_TOGGLE_LED2();

  16. osal_start_timerEx( SendTest_TaskID,

  17. SENDTEST_SEND_MSG_EVT, //只有在收到协调器给发送的0x55时才启动发送

  18. SENDTEST_SEND_MSG_TIMEOUT );

  19. }

  20. else osal_stop_timerEx(SendTest_TaskID,SENDTEST_SEND_MSG_EVT);//其他情况停止发送

  21. break;

  22. }

  23. }

(iii)、当协调器和终端节点分别烧写程序后,先使用SmartRF Flash Programmer软件读一下终端节点的64位长地址,在例子中改为:00 12 4B 00 02 4A CE E2

如图:

然后打开串口助手,在串口助手中写入 E2 CE 4A 02 00 4B 12 00 55,则启动终端节点发送,如果最后一位为其他值则停止发送。串口助手写入如图:

发送E2 CE 4A 02 00 4B 12 00 44将停止终端节点上报数据。

ZigBee组网实验:多终端节点向协调器发送数据协调器给终端节点发送数据相关推荐

  1. zigbee组网实验:温湿度采集实验SHT10

    对应的代码包:https://download.csdn.net/download/mchen_6431/11536608 硬件采用:深联智达公司产品: https://tb.am/ronna Zig ...

  2. ZigBee开发(15)--组网实验点播

    /***考试周,我抓紧把ZigBee的记录补一下,其实早就做了,被学院的事情耽搁了,博客一直没写,这两天给他补上************/ 前言: Zigbee 的通讯方式主要有三种点播.组播.广播. ...

  3. ZigBee组网流程

    第一个功能:协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Stack  由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查 ...

  4. 基于XBee进行ZigBee组网(二)——ZigBee网络与XCTU的使用

    本文主要介绍ZigBee网络的基本结构,三种组成ZigBee网络的基本节点:协调器(coordinator).路由器(router).终端(end device),如何使用XCTU对XBee进行基本参 ...

  5. xbee模块和单片机_基于XBee进行ZigBee组网

    该文章转帖自:http://blog.csdn.net/u012261135/article/details/48594419 文章简单地介绍了XBee模块.应用组合和2种通讯方式,还有XCTU的基本 ...

  6. Zigbee组网流程程序分析

    转载:http://blog.sina.com.cn/s/blog_9d48d26f01015tph.html 第一个功能:协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Sta ...

  7. ZigBee组网从未如此简单!

    想用ZigBee,想组网,不想看复杂的组网协议怎么办?看完这一篇就够了! ZigBee的前身是1998年由INTEL.lBM等产业巨头发起的"Homer flite"技术,随着我国 ...

  8. ZigBee组网详解

    ZigBee组网原理详解 https://blog.csdn.net/u012912039/article/details/52250253 1.组网概述 组建一个完整的zigbee网状网络包括两个步 ...

  9. zigbee组网过程浅析

    zigbee协议栈使用的是zstack版本,该协议栈的整体功能有点类似于操作系统.下面以SimpleApp例程为例,对协议栈的组网流程进行描述. 协议栈是用C语言实现的,由于C语言的入口都是main函 ...

  10. ZigBee组网原理详解

    ZigBee组网原理详解 https://blog.csdn.net/u012912039/article/details/52250253 1.组网概述 组建一个完整的zigbee网状网络包括两个步 ...

最新文章

  1. Ubuntu18.04 安装 gnuplot
  2. 识别强直性脊柱炎高效和疾病特定的基质改变
  3. 【采用】百度大规模知识图谱构建及智能应用
  4. 面试高频问题:HashMap实现原理
  5. mysql 排序去重复_php mysql 过滤重复记录并排序
  6. 【objectMapper实体转换异常】 com.fasterxml.jackson.databind.exc.MismatchedInputException
  7. 对对象类型和调用方法属性进行存储以提升反射性能
  8. 图像算法研究---一种简单的YUV转RGB的优化算法
  9. 返回最大数,不同语言之间的比较
  10. PAT 1060 Are They Equal (25 分)
  11. C++成员变量初始化列表中初始化顺序
  12. python元组是有序还是无序_python-03 元组和字典
  13. c++:ISO C++ forbids declaration of ‘xxx’ with no type
  14. 安徽医科大学计算机二级证书,勇追梦 终圆梦 安徽医科大学2021届推免生成绩喜人...
  15. 用HTML5编写日历,js编写当天简单日历效果【实现代码】_javascript技巧
  16. 高校学籍管理系统(SQL Server数据库课程设计)
  17. win8.1各版本的区别
  18. Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊
  19. 蓝桥杯---历届真题 题解
  20. (三)拨开生活中的数字迷雾,警惕图表的陷阱

热门文章

  1. 三维图看法亲身经验.
  2. Mac系统制作win10启动U盘踩坑实操
  3. 计算机基础知识表格斜线,怎么在excel中画斜线-制作好看的Excel表格必备技能:3秒制作斜线表头,简单到没朋友...
  4. VBS实现添加网络打印机
  5. WEB服务器安全设置,有效防护网站攻击70%
  6. ubuntu20磁盘新建分区与挂载
  7. Youtube更改视频原始语言
  8. kaggle入门titanic分析
  9. instead of 的用法
  10. 解决office2016显示图标异常