Zigbee入门指导(二)
2010年08月06日
  Zigbee入门指导(二)
  ――运行Zigbee例程
  logiclimit
  在Zigbee入门指导(一)中讲解了基于CC2430的Zigbee开发环境的搭建,安装完Ti的协议栈后,里面有多个例程,帮助用户入门及作为自己工程的基本框架。在Zigbee入门指导(二)中,我们将通过演示执行相关的例程,了解Zigbee应用的启动流程(不是Zigbee网络的启动流程),了解运行一个自定义Zigbee工程所要作的软件方面的改动和工程选项的配置。所用的开发套件为无线龙的套件。
  一、修改HAL
  HAL及所谓的Hardware Abstration Layer,通俗的了解即为开发板的硬件驱动,由于所用的是无线龙的开发板,与Ti的原装开发板有差异,需要对协议栈自带的HAL进行修改。HAL文件存放在目录中,里面有、、三个目录,中定义的与外设无关的硬件操作,存放的是头文件,而存放的是目标文件,里面根据目标板的不同分为、、。所用的无线龙的开发板和CC2430EB最为相似,故修改中的内容。按键操作几乎在每个例程中都会用到,故此处以按键驱动的修改为例,演示HAL的修改。
  先了解下Ti和无线龙扩展板的不同之处。Ti的CC2430EB原理图在Ti文档SWRU133.pdf(位于SWRU133.zip中)。Page29是按键电路的原理图,如图1
  图1(左上角是元件图)
  CC2430EB的按键其实是摇杆,上下左右四个方向和电阻网络相连,通过放大电路送到CC2430的P0.6脚,经AD采样后判断摇杆摆向哪个方向,按键编号为SW1~SW4摇杆也可像普通按键一样按下,产生一个直流电平变化,接到P0.5脚,按键编号为SW5。除此之外,还有一个独立按键连到P0.1脚,按键编号为SW6。
  无线龙的开发板则是用六个独立按键,上下左右四个按键和电阻网络相连,接P0.6,由AD采样得出是哪个键被按下。还有两个按键OK、Cancel分别直接和P0.5、P0.4相连。由于Ti和无线龙上下左右四个按键的电阻网络有差异,AD采样值有所不同,要予以修改。还有修改SW5、SW6的读取为的无线龙地OK、Cancel两个按键。
  要修改的文件为hal_key.c,要修改的部分宏定义、uint8 HalKeyRead ()、void HalKeyPoll ()。
  修改SW6的引脚定义,行156中的HAL_KEY_BIT1改为HAL_KEY_BIT4
  156: #define HAL_KEY_SW_6_BIT HAL_KEY_BIT4
  修改uint8 HalKeyRead ()中的SW5、SW6有关的内容,注释掉以下语句
  #if defined (HAL_KEY_SW_6_ENABLE) if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */ { keys |= HAL_KEY_SW_6; }#endif#if defined (HAL_KEY_SW_5_ENABLE) if (HAL_KEY_SW_5_PORT & HAL_KEY_SW_5_BIT) /* Key is active high */ { keys |= HAL_KEY_SW_5; }#endif
  在对应位置添加
  if (P0_5 == 0){ keys |= 0x04;} if (P0_4 == 0){ keys |= 0x20;}
  修改用于判断哪个方向键被按下的P0.6采样值,do{}while中的条件语句注释掉,取之以下内容
  if ((adc >= 0x55) && (adc = 0x40) && (adc = 0x18) && (adc 为例,介绍Zigbee工程设置。CC2430的开发环境为IAR,相信接触过MSP430的朋友对其不会陌生,有关Zigbee工程的设置实际上就是通过IAR的工程设置完成的。打开下的GenericApp.eww。
  打开工程后,界面如图2
  图2
  同一个工程中包含的多个project,根据开发板的类型(EB和DB)、Zigbee网络中的节点类型(Coordinator、Router和EndDevice)一共有六个project,我们只需用到CoordinatorEB和EndDeviceEB这两个project。先把project选择为CoordinatorEB,在GenericApp-CoordinatorEB上右击,选择Options…进入工程设置界面,选择C/C++ Compiler->Preprocessor,设置预编译项。去掉LCD_SUPPORTED=DEBUG,HAL_UART在GenericApp中可加可不加,如图3所示
  图3
  通过条件编译选项设定是否添加相关的硬件驱动和调试选项,去掉LCD_SUPPORTED=DEBUG的原因是Ti的开发板和无线龙开发板的LCD接口不一样,而我们又没有修改相关Hal文件,无法使用LCD显示,加入HAL_UART的原因是我们将使用串口作为调试信息的输出。
  三、Zigbee工程启动流程解析
  用户相关的应用程序代码是在App类的文件当中,其与Zigbee是如何关联起来的呢?如何调配处理器时间去处理应用程序、响应外设和进行无线收发呢?Ti协议栈通过了一个小型的操作系统实现了复杂多样的事件处理。CC2430具有128KB ROM、8KB RAM,如此大的空间为SOC(System On Chip)提供了有力保障。操作系统的API介绍在《OSAL API_F8W-2003-0002_》中,在这个操作系统中提供了消息管理、任务同步、定时器管理、中断管理、任务管理、内存管理、电院管理和非易失内存管理等功能。用户的应用程序要以任务(task)的方式注册到系统中,一个task对应于自己的事件处理函数(event processor)。task的添加,event和task的关联,事件处理函数和对应task的关联将在以下的流程解析中讲解。
  1、main()
  编译工程(快捷键F7),将模块连接到PC,调试工程(快捷键Ctrl + D)。进入到函数的入口――main()函数,位于ZMain Group的ZMain.c中。在main()中完成了相关硬件和软件的初始化,作为重点,我们要关注的是
  190: osal_init_system();
  和
  206: osal_start_system(); // No Return from here
  我们先来看osal_init_system()。在osal_init_system右击,选择Go to definition of osal_init_system,追踪其定义(注意“追踪”的方法,下文所述的追踪都是指用这个方法)。
  2、osal_init_system()
  osal_init_system()定义在OSAL Group的OSAL.c中,进行了操作系统相关的初始化工作,需要重点关注的是
  927: osalInitTasks();
  追踪其定义。
  3、osalInitTasks()和添加task到OS
  osalInitTasks()定义在App Group的OSAL_GenericApp.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++ ); ZDApp_Init( taskID++ ); GenericApp_Init( taskID );}
  在这个函数中,我们看到了将task添加到系统的过程,每添加一个task,taskID就加1。最后一句GenericApp_Init()正是关注的重点,追踪它。
  4、GenericApp_Init()和注册event到task中
  GenericApp_Init()位于GenericApp.c中,完成了endPoint的设定和注册、按键事件的注册,即把相关的enevt和相关的task进行了关联,当发生这些event时,会由和相应task关联的事件处理函数进行处理。到此,已经了解了如何添加task、如何关联event和task,那么task和事件处理函数的关联又是如何进行的呢?先找找GenericApp_Init对应的事件处理函数,解决这个问题,要回到ZMain.c中main()里的osal_start_system(),追踪它吧!
  5、osal_start_system()和task及事件处理函数的关联
  osal_start_system()定义在OSAL.c中。osal_start_system()中最有可能是执行事件处理函数的就是行977了
  977: events = (tasksArr[idx])( idx, events );
  tasksArr是函数数组,idx代表task的id,events代表相应的事件,猜测正确吗,追踪它。
  在OSAL_GenericApp.c中找到了tasksArr的定义,内容如下
  const pTaskEventHandlerFn tasksArr[] = { macEventLoop, nwk_event_loop, Hal_ProcessEvent,#if defined( MT_TASK ) MT_ProcessEvent,#endif APS_event_loop, ZDApp_event_loop, GenericApp_ProcessEvent};
  如果追踪里面的数组成员,它们都是事件处理函数,注意,里面的成员顺序和osalInitTasks()中task的添加顺序是一样的,即task的ID和其对应的事件处理函数在tasksArr中的序号是一样的,这样在调用(tasksArr[idx])( idx, events )时,完成了task和对应的事件处理函数的关联。
  6、事件处理
  上面我们了解了task和对应事件处理函数关联方式,我们重点分析下用户自定义task的事件处理函数GenericApp_ProcessEvent()。通过行233
  233: if ( events & SYS_EVENT_MSG )
  和行300
  300: if ( events & GENERICAPP_SEND_MSG_EVT )
  可知,起码有两类事件:SYS_EVENT_MSG和GENERICAPP_SEND_MSG_EVT,显然,SYS_EVENT_MSG是协议栈已经定义好的系统事件,而GENERICAPP_SEND_MSG_EVT就是用户自定义的事件了。事件号是一个16bit的常量,使用独热码(one-hot code)编码,方便进行event的提取,这样一个task中最多可以有16个event,SYS_EVENT_MSG已经占用了0x8000,故自定义的事件只能有16个。由于事件号使用独热码,故事件的提取和清除可以用简单的位操作指令实现。事件提取events & GENERICAPP_SEND_MSG_EVT,事件清除events ^ GENERICAPP_SEND_MSG_EVT。系统事件包函了各种系统消息(message),系统事件中的消息号是一8bit常量,定义在ZComDef.h中,
  322: #define SPI_INCOMING_ZTOOL_PORT 0x21 // Raw data from ZTool Port (not implemented) 323: #define SPI_INCOMING_ZAPP_DATA 0x22 // Raw data from the ZAPP port (see serialApp.c) 324: #define MT_SYS_APP_MSG 0x23 // Raw data from an MT Sys message 325: #define MT_SYS_APP_RSP_MSG 0x24 // Raw data output for an MT Sys message 326: 327: #define AF_DATA_CONFIRM_CMD 0xFD // Data confirmation 328: #define AF_INCOMING_MSG_CMD 0x1A // Incoming MSG type message 329: #define AF_INCOMING_KVP_CMD 0x1B // Incoming KVP type message 330: #define AF_INCOMING_GRP_KVP_CMD 0x1C // Incoming Group KVP type message 331: 332: #define KEY_CHANGE 0xC0 // Key Events 333: 334: #define ZDO_NEW_DSTADDR 0xD0 // ZDO has received a new DstAddr for this app 335: #define ZDO_STATE_CHANGE 0xD1 // ZDO has changed the device's network state 336: #define ZDO_MATCH_DESC_RSP_SENT 0xD2 // ZDO match descriptor response was sent 337: #define ZDO_CB_MSG 0xD3 // ZDO incoming message callback
  用户可以自定义系统事件的消息范围为0xE0~0xFF,现只针对SYS_EVENT_MSG中的两个处理函数进行说明。
  AF_INCOMING_MSG_CMD:当模块接收到属于自己的无线数据信息时,就会触发AF_INCOMING_MSG_CMD消息,由相关的处理函数处理接收到的信息。
  ZDO_STATE_CHANGE:当网络状态改变时就会触发此消息,其在这个工程中的作用是,当节点建立网络(作为协调器)、加入网络(作为终端)时,运行
  osal_start_timerEx( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT, GENERICAPP_SEND_MSG_TIMEOUT );
  osal_start_timerEx()的作用是启动一系统定时器,当其溢出(GENERICAPP_SEND_MSG_TIMEOUT)时,会触发task(GenericApp_TaskID)的事件(GENERICAPP_SEND_MSG_EVT)。又看到事件GENERICAPP_SEND_MSG_EVT了,它是用户定义的事件,分析之。
  if ( events & GENERICAPP_SEND_MSG_EVT ){ // Send "the" message GenericApp_SendTheMessage(); // Setup to send message again osal_start_timerEx( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT, GENERICAPP_SEND_MSG_TIMEOUT ); // return unprocessed events return (events ^ GENERICAPP_SEND_MSG_EVT);}
  以上就是GENERICAPP_SEND_MSG_EVT的处理函数,先分析总的流程,GenericApp_SendTheMessage()发送信息,osal_start_timerEx()重新启动一系统定时器,同样是指向task(GenericApp_TaskID)的事件(GENERICAPP_SEND_MSG_EVT),返回时要注意清除当前事件(events ^ GENERICAPP_SEND_MSG_EVT),否则会反复处理同一个事件,陷入死循环。
  四、Zigbee应用模型
  对数据进行收发还需对Zigbee的应用模型有所了解。Profile和Endpoint是Zigbee应用层中有关应用模型的,概念,先给出这两个概念的官方的定义:
  Application Profiles are an agreement on a series of messages defining an application space (for example, “Home Automation” or “Smart Energy”)
  Endpoints are a logical extension added to a single ZigBee radio which permits support for multiple applications, addressed by the Endpoint number (1-240)
  Key Relationships:
  Maximum of 240 Endpoints per ZigBee Device (Endpoint 0 is reserved to describe the generic device capabilities and Endpoint 255 is reserved for broadcasting to all endpoints, Endpoints 241-254 are reserved for future use)
  One Application Profile described per Endpoint 。
  我个人的理解是:某个具体的应用(application)的相关操作被定义成一个profile,profile和应用层的结合通过endpoint来实现,一个zigbee设备有240个endpoint。
  在GenericApp_Init( byte task_id )中有以下相关的定义
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;GenericApp_epDesc.task_id = &GenericApp_TaskID;GenericApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;GenericApp_epDesc.latencyReq = noLatencyReqs;
  追踪相关的变量可知使用类型endPointDesc_t描述endpoint的类型,其定义在AF.h中
  typedef struct{ byte endPoint; byte *task_id; // Pointer to location of the Application task ID. SimpleDescriptionFormat_t *simpleDesc; afNetworkLatencyReq_t latencyReq;} endPointDesc_t;
  需要进一步了解的是SimpleDescriptionFormat_t,其定义也在AF.h中
  typedef struct{ byte EndPoint; uint16 AppProfId; uint16 AppDeviceId; byte AppDevVer:4; byte Reserved:4; // AF_V1_SUPPORT uses for AppFlags:4. byte AppNumInClusters; cId_t *pAppInClusterList; byte AppNumOutClusters; cId_t *pAppOutClusterList;} SimpleDescriptionFormat_t;
  里面有AppProfId,即为Profile Id,可以从这个结构中看到,profile中有In、Out两种类型的Cluster,Cluster此处可理解为操作,每类Cluster对应着一个ClusterList,list中的每个成员对应一种操作,GenericApp的GenericApp_SimpleDesc为
  const SimpleDescriptionFormat_t GenericApp_SimpleDesc ={ GENERICAPP_ENDPOINT, // int Endpoint; GENERICAPP_PROFID, // uint16 AppProfId[2]; GENERICAPP_DEVICEID, // uint16 AppDeviceId[2]; GENERICAPP_DEVICE_VERSION, // int AppDevVer:4; GENERICAPP_FLAGS, // int AppFlags:4; GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters; (cId_t *)GenericApp_ClusterList, // byte *pAppInClusterList; GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters; (cId_t *)GenericApp_ClusterList // byte *pAppInClusterList;};
  五、运行例程
  1、运行
  至此,对Zigbee的一些基本概念已经介绍完了,让我们运行第一个例程吧。先确认是否已按前文所述修改HAL及工程设置。由于每有移植LCD驱动,使用串口输出相关的信息。修改GenericApp.c中的void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
  void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ){ switch ( pkt->clusterId ) { case GENERICAPP_CLUSTERID: HalUARTWrite(HAL_UART_PORT_0, (uint8*)pkt->cmd.Data, pkt->cmd.DataLength); // "the" message#if defined( LCD_SUPPORTED ) HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );#elif defined( WIN32 ) WPRINTSTR( pkt->cmd.Data );#endif break; }}
  编译后分别下载,即可运行。
  2、使用Packet Sniffer观察无线数据
  为了了解有关的无线信号,使用Packet Sniffer侦测空中的Zigbee信号,使用一个SmartRF04EB+CC2430模块配合Packet Sniffer软件即可完成上述功能。
  运行Packet Sniffer,先要选择协议及物理设备的芯片类型。
  图4 协议及芯片类型
  之后的显示面板的功能如图
  图5
  运行后会把数据划分后显示出来
  图6
  各部分含义请自行学习。观察两个模块相互发送的”Hello Word”,用户数据是在APS层,找到一段含APS Payload的数据包,内容为
  图7
  48 65 6C 6C 6F 20 57 6F 72 6C 64 00即为Hello World的字符串。
  六、进阶和提高
  自行学习以下内容
  1、尝试运行其它例程,有使用LCD的地方改成用串口输出
  2、编写相关的LCD驱动
  3、配合Packet Sniffer了解Zigbee网络建立和数据收发过程
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/logiclimit/archive/2010/06/20/5681932.aspx

Zigbee入门指导(二)相关推荐

  1. Zigbee入门指导(二)mdash;mdash;运行Zigbee例程

    Zigbee入门指导(二) --运行Zigbee例程 logiclimit 在Zigbee入门指导(一)中讲解了基于CC2430的Zigbee开发环境的搭建,安装完Ti的协议栈后,里面有多个例程,帮助 ...

  2. 史上最萌最认真的机器学习/深度学习/模式识别入门指导手册(一)

    喵喵喵~大家元宵节快乐噢.有没有要陪小夕出去看烟花的吖... 小夕借此给热爱学习的喵喵们献上这篇拙文,希望不要嫌弃哦~ 还有,小夕画的封面图是不是很棒呀( ̄∇ ̄) 小夕发现现在想进军人工智能领域的程序 ...

  3. 网站制作入门指导教程

    作者:韩亚飞_yue31313_韩梦飞沙 QQ:313134555 网站制作入门指导教程 目录 前言...2 第一步:网站基础知识学习...5 第二步:最简单的网站架设与制作过程...7 第三步:HT ...

  4. 新手必看:生成对抗网络的初学者入门指导

    新手必看:生成对抗网络的初学者入门指导 https://www.cnblogs.com/DicksonJYL/p/9698877.html 本文为 AI 研习社编译的技术博客,原标题 A Beginn ...

  5. 万事开头难(一)——Cocos2d-JS游戏开发入门指导

    当你信心满满,斗志昂扬地下定决心学习新技术时,你是否也有这样的感觉:技术还没学,却在配置环境上浪费了大量时间, 最重要的是,无论怎样,就是配不对,想怒砸电脑!!!你是否还有这样的感觉:一头扎进去学了好 ...

  6. HTML5菜鸟入门指导:简介、平台搭建、示例演示

    HTML5菜鸟入门指导:简介.平台搭建.示例演示 一.HTML5简介 1.  了解HTML (1).什么是HTML? HTML是用来描述网页的一种语言: HTML指超文本标记语言(Hyper Text ...

  7. 【SSRS】入门篇(二) -- 建立数据源

    原文:[SSRS]入门篇(二) -- 建立数据源 通过 [SSRS]入门篇(一) -- 创建SSRS项目 这篇,我们建立了一个SSRS项目: 接下来,我们以 AdventureWorks2012 示例 ...

  8. Node.js核心入门(二)

    目录: Node.js核心入门(一) 全局对象 常用工具 事件机制 Node.js核心入门(二) 文件系统访问 HTTP服务器与客户端 文件系统 fs fs 模块是文件操作的封装,它提供了文件的读取. ...

  9. SpringBoot入门(二)——起步依赖

    本文来自网易云社区 在前一篇我们通过简单几步操作就生成了一个可以直接运行的Web程序,这是因为SpringBoot代替我们做了许多工作,概括来讲可以分为起步依赖和自动配置.这一篇先来看看起步依赖. 项 ...

最新文章

  1. linux下gdb所有实用方法
  2. jq控制div是否展示_选择控制台_调度台之前,这几点你应该要看!
  3. BoW图像检索Python实战
  4. xhprof windows下安装和使用(windows版本)
  5. jasmine没有调用fixture.detectChanges就取不到元素的原因
  6. Incorrect line ending: found carriage return (\r) without corresponding newline (\n)错误的解决方案...
  7. CompressedOops:Java压缩参考简介
  8. Postman使用入门
  9. jquery easyUi的学习笔记{一头扎进EasyUI}
  10. 鸿蒙正式版什么时候上线,终于来了!华为鸿蒙正式版6月2日上线,EMUI时代落幕...
  11. 吴昊品游戏核心算法 Round 17 —— M*N PUZZLE 与 N PUZZLE 的解的唯一性定理(由特殊到一般)...
  12. HTML5 教程(四) - 内联元素
  13. 【目录】pygame网络游戏教程
  14. Sick编码器CanOpen通信
  15. 计算机hp1007打印程序,HP P1007
  16. python调用按键精灵插件_Textobot-用交互式TB插件在iPhone上砸壳更美滋滋
  17. 计算机显卡内存分布查看,Win10电脑查看显卡内存的详细教程
  18. 一切要靠自己努力去争取!!!
  19. 无线射频专题《射频信号,射频的传输行为,吸收,放射,散射,折射,衍射,损耗,增益,多径现象》
  20. 计算机视觉注意力网络(三)——CBAM [ECCV 2018]

热门文章

  1. 神秘国度的爱情故事——广州大学课程设计
  2. mysql--大于小于等于
  3. 为什么wps数字前面有撇号_excel表格中数据前有撇号-Excel 如何去除数字前面的撇号...
  4. matlab图像处理 识别颜色,MATLAB图像处理_直接操作像素点进行颜色变换
  5. Tableau 添加加权平均参考线
  6. 华为鸿蒙的三大遗憾和一个好消息
  7. win10开机系统恢复(WinRE)中找不到系统恢复映像或功能不全的解决方法
  8. 家居家装行业人群洞察白皮书.pdf
  9. JMeter做性能测试之前,你应该要知道的套路?
  10. [渝粤教育] 中南大学 科学计算与MATLAB语言 参考 资料