文章来自于百度文库:http://wenku.baidu.com/link?url=uiESmBOQ1hHnGX-MQQnRWpr93rOo6kdF8vVG_HA1JwzCg7kPYzbQ_YLww_AMjWIQ-9K87qDP6SFj5F1e99fRd6151zNPr4aaO6xlYSHQyOC
使用方法简介:一般情况下用户只需要额外添加三个文件就可以完成一个项目。一个是主文件,存放具体的任务事件处理函数;一个是这个主文件的头文件;另外一个是以Osal开头的操作系统接口文件,是专门存放任务处理函数数组tasksArr[]的文件。这样就实现了Z-Stack代码的公用,用户只需要添加这几个文件,编写自己的任务处理函数就可以了。
-----学习ZigBee操作系统抽象层应用程序编程接口。
-----剖析一个简单的例程学习使用Z-Stack。
下面工作一一弄明白:
(1)头文件----参考例程添加头文件。
(2)系统初始化和使用----函数Init和ProcessEvent。
(3)任务建立,调用,切换
(4)中断配置----熟悉编程接口即可。
(5)定时器使用----熟悉编程接口即可。
(6)驱动文件编写和调用
(7)网络建立和加入--> 组网
(8)电源管理----节能配置----熟悉编程接口即可。
(9)编写程序----使用五向按键控制四个LED灯(先看懂Simple例程)。
有选择的读代码:
需要读的代码:APP(全部代码);HAL和Zmain的全部或部分代码。
其他:熟悉编程接口和使用方法。
一、Z-Stack 操作系统抽象层应用程序编程接口:
1、信息管理API:
信息管理 API 为任务和处理单元之间的信息交换提供了一种具有不同处理环境的机制(例如,在一个控制循环中调用中断服务常规程序或函数)。这个 API 中的函数可以使任务分配或回收信息缓冲区,给其它任务发送命令信息以及接收回复信息。API包括四个函数:
(1) osal_msg_allocate ():分配一个信息缓冲;
(2) osal_msg_deallocate():回收一个信息缓冲区;
(3) osal_msg_send():发送命令或数据信息;
(4) osal_msg_receive():检索/接收一条已收到的命令信息;
1、任务同步API:
这个 API 使得任务等待事件发生,并在等待期间返回控制。这个 API 中的函数可以用来为一个任务设置事件,并无论设置了什么事件都通知任务。仅有一个函数osal_set_event():用来为一个任务设置事件标志。
2、定时器管理API:
这个API使得内部的(Z-Stack)任务和外部的(应用层)任务都可以使用定时器。API提供了启动和停止一个定时器的功能,这定时器可设定递增的一毫秒。
(1)osal_start_timer():启动一个定时器;
(2)osal_start_timerEx():增加了taskID参数。它允许访问者调用程序为另一个任务设置定时器;
(3)osal_stop_timer():调用函数用来停止一个已启动的定时器;
(4)osal_stop_timerEx():用来停止一个已启动的定时器;
(5)osal_GetSystemClock():读取系统时钟。
4、中断管理 API:
此API使得一个任务可以与外部中断相互交流。API 中的函数允许和每个中断去联络一个具体的服务例程。中断可以启用或禁用。在服务例程内部,可以为其它任务设置事件。
(1)osal_int_enable():启用一个中断;
(2)osal_int_disable():禁用一个中断。
5、任务管理 API:
在OSAL系统中,API常用于添加和管理任务。每个任务由初始化函数和事件处理函数组成。OSAL调用osalInitTasks()(应用程序提供)去初始化这任务且 OSAL 运用一个任务列表(const pTaskEventHandlerFntasksArr[])去为每个任务(也是应用程序提供)调用事件处理程序。
(1)osal_init_system():初始化OSAL系统,在使用任何其它OSAL函数之前必须先调用此函数启动OSAL系统。
(2)osal_start_system():任务系统中的主循环函数。它将检查所有的任务事件且为含有该事件的任务调用任务事件处理函数。假如有特定任务的事件,这个函数将为该任务调用事件处理例程来处理事件。相应任务的事件处理例程一次处理一个事件。一个事件被服务后,剩余的事件将等待下一次循环。如果这没有事件(服务与所有任务),这个函数使处理器程序处于睡眠模式。
6、内存管理 API:
该API 代表一个简单的内存分配系统。这些函数允许动态存储内存分配。
(1) osal_mem_alloc():一个简单的内存分配函数,如果分配成功则返回一个指向缓冲区的指针;
(2) osal_mem_free():释放存储空间便于再次运用。
7、电源管理 API:
当它安全关闭接收器和外部硬件时,这个系统为应用程序或任务提供了一种告知OSAL的方法。接着使处理器转入睡眠。
(1)osal_pwrmgr_device():当升高电源或需要改变电源时(例如电池支持的协调器)这个函数应由中心控制实体(比如ZDO)调用。
(2)osal_pwrmgr_task_state():无论这个任务是否想要保护电源,每个任务都将调用此函数。任务将调用此函数来表决是否需要OSAL保护电源或推迟电源保护。默认情况下,当一个任务被创建时,它自己的电源状态设置为保护模式。如果该任务一直想要保护电源,就根本不必调用此函数。
8、非易失性存储器(NV)的 API:
描述了OSAL非易失性存储器系统。该系统为应用程序提供了一种把信息永久保存到设备内存的方法。它还能用于ZigBee规范要求的把某些项目永久保存到协议栈。NV函数的职能是读写任意数据类型的用户自定义项目,比如结构体和数组。用户能通过设置适当的偏移和长度来读和写一个整体的项目或元素。API独立于NV存储介质,并且能用于实现闪存或EEPROM。
每个易失性的项目都仅有一个ID,当一些ID值由栈或平台保留或运用时,应用程序中有特定一系列的ID值。假如应用程序创建自己的易失性项目,它必须从应用范围的值内选择一个标识符。参考下面的列表:
(1)osal_nv_item_init():初始化NV项目,这个函数检查存在NV的项目,假如不存在,它将通过这个函数去创建或初始化。
(2)osal_nv_read():从NV中读出数据。这个函数能用来从NV 中带有偏移的索引指向的项目读出整个项目或一个元素。读出的数据复制到*buf中。
(3)osal_nv_write():写入数据到NV,这个函数用来通过带有偏移的索引指向项目的偏移量来写入整个NV项目。
(4)osal_offsetof():计算一个结构体内元素的内存偏移量,以字节为单位。
二、Zigbee启动过程:
1、Zigbee启动过程详见前面Page3。
2、Zigbee启动过程总结:
(1)Zmain.c文件中包含程序入口main()函数。
(2)main()函数主要做了做了两件工作,一个是系统初始化,即有启动代码来初始化硬件系统和软件架构需要的各个模块,另一个作用是执行操作系统实体---main函数最后调用函数Osal_start_system()来启动操作系统。
(3)用户如何编写应用程序:
一般用户只需额外添加三个文件即可完成一个项目:主文件---SampleApp.c,存放具体的任务事件处理函数;主文件的头文件---SampleApp.h;第三个是以Osal开头的操作系统接口文件---OSAL_SampleApp.c,是专门存放任务处理函数数组tasksArr[]的文件。这样就实现了Z-Stack代码的公用,用户只需要添加这几个文件,编写自己的任务处理函数就可以了。
(4)SampleApp例程中分为四个部分:DemoEB、CoordinatorEB、RouterEB和EndDeviceEB,在按键发送闪烁试验中仅仅使用了DemoEB。
3、一个完整的初始化过程(按键发送闪烁实验):
main()-->osal_init_system()-->osalInitTasks()-->SampleApp_Init(task_id)
涉及的文件为:ZMain.c、OSAL.c、OSAL_SampleApp.c和SampleApp.c,也就是启动文件-->系统文件-->系统接口文件-->应用程序。
4、一个完整的任务/事件处理过程(按键发送闪烁实验):
main() --> osal_start_system() --> osal_run_system() --> tasksArr --> SampleApp_ProcessEvent();同样是:启动文件-->系统文件-->系统接口文件-->应用程序;其中osal_start_system是个无限循环:for(;;)。
1、操作系统接口文件---OSAL_SampleApp.c(按键发送闪烁实验):
主要是定义了结构体:函数指针数组tasksArr(包含SampleApp_ProcessEvent)和任务初始化函数osalInitTasks;其中tasksArr在OSAL.c中被调用:events=(tasksArr[idx])(idx,events)à此语句就是调用了函数指针数组中的一个函数,(tasksArr[idx])为函数名,(idx,events)位函数的参数(任务号和事件),events为返回值。
2、SampleApp_Init()---按键发送闪烁实验:
(1) 通用应用程序任务初始化函数,这个函数在初始化过程中被调用,该函数应该包含任何特定于应用程序的初始化(即硬件初始化/设置,表的初始化,电源初始化等等)。
(2) 自己编写应用初始化函数可以在这个函数基础上添加其他初始化函数。
3、SampleApp_ProcessEvent()---按键发送闪烁实验:
(1)通用应用程序任务事件处理函数。这个函数被调用处理任务的所有事件。事件类型包括定时器、信息和其他用户定义的事件(如Key事件)。
(2)自己编写事件处理函数可以在这个函数基础上添加其他用到的事件。
7、SimpleApp:
(1)分为四部分:ControllerEB、CollectorEB、SensorEB和SwitchEB;其中按键控制LED例程使用了ControllerEB(协调器)和SwitchEB(终端节点);无线测温实验使用了SensorEB(终端节点)和CollectorEB(协调器);
(2)sapi.c和sapi.h:相当于操作系统接口文件---OSAL_SampleApp.c;
(3)按键控制LED全过程:
按下SimpleControllerEB的up键建立zigbee网络-->按下SimpleControllerEB的up键允许别的模块对其绑定-->按下SimpleSwitchEB的up键搜索网络并加入到网络-->再次按下SimpleSwitchEB的up键与SimpleControllerEB建立绑定-->交替按下SimpleSwitchEB的right键来控制SimpleControllerEB模块的LED1的交替亮灭。
(4)按键控制LED程序解读:
---SimpleControllerEB的zb_AllowBind(myAllowBindTimeout ) -->允许绑定
---SimpleSwitchEB的zb_BindDevice()-->建立绑定
---SimpleSwitchEB的zb_SendDataRequest(0xFFFE, TOGGLE_LIGHT_CMD_ID, ******)-->发送闪灯指令
---sapi.c中的SAPI_ProcessEvent调用osal_msg_receive-->接收指令并执行
---SAPI_ProcessEvent函数位于函数数组tasksArr中被轮询调用。
---AF_INCOMING_MSG_CMD-->SAPI_ReceiveDataIndication-->zb_ReceiveDataIndication-->最终调用HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE)使LED1闪烁
8、网络建立(组网—建立网络和节点加入网络):
osal_init_system()-->osalInitTasks()-->ZDApp_Init(taskID++)--> ZDOInitDevice(0)--> ZDApp_NetworkInit( extendedDelay )用于启动连接网络 --> osal_start_timerEx --> osal_start_system() --> osal_run_system()--> tasksArr --> ZDApp_event_loop(位于函数数组tasksArr中)--> ZDO_StartDevice --> NLME_NetworkFormationRequest(路由器或终端节点请求)--> ZDO_NetworkFormationConfirmCB(协调器确认)--> osal_set_event --> 回到ZDApp_event_loop--> ZDO_UpdateNwkStatus -->网络已建立。
9、按键发送闪烁实验---先看懂再改写:
(1) SampleApp_Init:初始化读跳线(IO口电平)判断节点/设备类型。
(2) SampleApp_ProcessEvent:事件处理函数,会被循环调用;功能是接收其他节点发来的消息或指令,其中包括按键指令(有按键按下),然后调用按键处理函数进行相应的操作;接收消息事件是指接收到消息或者指令。
(3) SampleApp_HandleKeys:按键操作函数,处理所有的按键事件(按键是指本节点的按键)。
(4) SampleApp_SendFlashMessage(SAMPLEAPP_FLASH_DURATION):此函数发送闪烁命令(组播),调用函数AF_DataRequest发送数据。
(5) aps_FindGroup ( SAMPLEAPP_ENDPOINT,SAMPLEAPP_FLASH_GROUP ):该节点是否位于本组之中;
aps_RemoveGroup(SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP ):如果节点位于本组,则从本组中移除。
(6)SampleApp_MessageMSGCB:调用HalLedBlink函数实现闪灯,闪烁四次,周期为250ms,占空比50%。
(7)按键操作总结:
KEY_CHANGE事件:按键按下也被封装成一条消息,但并非是其他节点发送的消息;消息不代表无线通信接收到数据。
10、 无线测温实验---先看懂再改写:
(1) 发送流程:main() --> osal_start_system() --> osal_run_system() --> tasksArr -->SAPI_ProcessEvent --> zb_HandleOsalEvent --> myApp_ReadTemperature --> zb_SendDataRequest --> AF_DataRequest。
(2) 接收流程:main() --> osal_start_system() --> osal_run_system() --> tasksArr -->SAPI_ProcessEvent --> AF_INCOMING_MSG_CMD --> SAPI_ReceiveDataIndication --> zb_ReceiveDataIndication --> osal_memcpy --> MT_ProcessEvent --> MT_ProcessIncomingCommand --> 串口发送函数HalUARTWrite。
(3) 函数解读:
11、 透明传输实验---先看懂再改写:
(1) 初始化:
main() --> osal_init_system() --> osalInitTasks() --> SerialApp_Init()
(2) 发送流程:
main() --> osal_start_system() --> osal_run_system() --> tasksArr --> SerialApp_ProcessEvent -->SerialApp_Send() --> HalUARTRead --> AF_DataRequest
(3) 接收流程:
main() --> osal_start_system() --> osal_run_system() --> tasksArr --> SerialApp_ProcessEvent --> AF_INCOMING_MSG_CMD --> SerialApp_ProcessMSGCmd
--> HalUARTWrite(发送数据到串口)
Zigbee协议栈-DIY修改实验
1、多个按键分别控制多个灯闪烁实验—重新COPY官方协议栈进行实验:
2、无线测温---使用DS18B20进行试验:
3、读懂如何判断跳线---ID号,并进行修改。
Zigbee网络管理
一个节点除了64位的IEEE地址(MAC地址-物理地址),16位的网络地址,每个节点还提供了8位的应用层入口地址(端点:EndPoint),对应于用户应用对象。端点0为ZDO接口,端点1至240供用户自定义应用对象使用,端点255为广播地址,端点241-254保留为将来使用。
每一个应用都对应一个配置文件(Profile)。配置文件内容包括:设备ID(Device ID),事务ID(Cluster ID),属性ID(AttributeID),及AF使用何种服务类型等信息。在zigbee协议中,一个配置文件中允许最多2^16个设备(16位表示),2^8个事务,每个事务支持最多约2^16个属性。