ZigBee协议栈开发(五)

一、协议栈的使用

1、更改文件中的名称为自己的定义

2、选择不同的选项卡来选择协调器、路由器、终端程序的下载,由于选项选择不同,就会导致参与编译的配置文件不同,配置不同就会导致部分宏定义不同,宏定义不同就会导致工程里某些宏的值不同,这些宏值不同就会影响程序执行的流程,就会导致出现不同的功能,所以就有了不同功能的代码版本,协调器、路由器、终端。

3、代码解析:

(1)-DDEFAULT_CHANLIST=0x00000800  // 11 - 0x0B 

#define  DEFAULT_CHANLIST 0x00000800

DEFAULT_CHANLIST表明Zigbee模块要工作的网络,当有多个信道参数值进行或操作之后,把结果作为DEFAULT_CHANLIST 值,那么对于路由器和终端协调器的意义分别是:

路由器和终端:

  可以在参与或操作的这些信道上选择一个相对来说最佳的网络加入进去

协调器

  可以在参与或操作的这些信道上选择一个最佳的信道并在这个信道上创建自己的Zigbee网络

(2)PANID

 非0xFFFF时

   路由器和终端:必须要加入到PANID为参数值这样一个Zigbee无线局域网

   协调器:要创建一个网络,并且把这个参数值作为这个网络的PANID

 为0xFFFF时:

   路由器和终端:在加入网络的时候没有PANID的限制

   协调器:可以随机生成一个值,把这个随机值作为这个网络的PANID

当两个模块下载相同的协调器代码,并且指定的PANID参数值为非0xFFFF时,先上电的协调器会首先建立一个以这个参数为PANID的网络,后上电的会创建一个以这个参数加1为PANID的网络,再多则依次加1创建网络。

(3)uint8osal_set_event( uint8 task_id, uint16 event_flag )

在ZStack里按照代码功能来分,分成不同的层,比如硬件操作相关的硬件层,网络相关的网络层,自己写应用程序的应用层。几乎每一个层都是一个任务,系统为每一个任务分配一个一个字节的唯一数值编号,每一个任务都能处理一些他们能够处理的事物,我们把数值编号叫做任务ID,他们能处理的事物叫做事件。这个函数的第一个参数是任务ID,第二个是事件号,调用这个函数可以指定任务中的事件进行处理。

(4)uint8 osal_start_timerEx(uint8 taskID, uint16 event_id, uint16 timeout_value )

这个函数与上一个函数类似,前两个参数都相同,多加了一个参数是间隔时间(单位是ms),调用这个函数可以指定任务的某个事件在一定时间之后进行处理。

用户可以自己定义自己的事件并且进行处理,一个任务号对应的事件只能有16个,因为事件号只有16位,每个事件号之能是16位中有1位为1。但是系统在运行时,会有许多事件需要处理,所以事件号是不够用的,为此引入了消息的概念。

消息处理的原理:

首先定义事件:#define SYS_EVENT_MSG            0x8000  // A message is waiting event

当需要应用层任务来处理某件事时,首先给应用层任务发送一个消息,调用osal_set_event(SDApp_TaskID,SYS_EVENT_MSG);这样应用层就会进入SYS_EVENT_MSG事件处理,在这个事件处理函数中判断刚刚引发产生SYS_EVENT_MSG事件的是哪一种消息,然后根据消息类型做相应的处理,而消息的类型可以自己无限定义,这样应用层可以处理的事情就很多了。

注:某些硬件可能会与TI官方定义的板子硬件初始化冲突,所以一方面我们要把自己的初始化程序放在官方初始化程序之后,然后也一定要把初始化工作做全面,比如LED设置io口时,模式、输入输出一定要都定义一下。

4、按键的相关修改

这里不建议修改官方的宏定义,而是建立自己的初始化函数放在官方初始化函数之后即可,要注意的是按键有延时,协议栈中进入中断应该尽快出去,所以在按键中断中不要用延时函数,改为使用osal_start_timerEx函数,定时25ms之后进入一个时间中处理按键事件。

 

二、OSAL操作系统原理

1、应用层是一个任务,有一个系统分配给它的数值唯一的编号——任务ID。

2、任务可以处理事件,处理事件的这些代码都在一个函数中,这个函数叫做任务事件处理函数。

3、应用层任务还有一个2个字节的变量,叫任务事件变量。任务事件变量与应用层定义的事件的关系是:如果事件变量和某个事件的宏值与操作为1,那么表示应用层任务将要处理这个事件。系统在运行时会不断的读应用层任务事件变量,当它发现这个变量为0就认为应用层任务当前没有事件需要去处理,如果发现这个变量不为0,它就认为应用层任务有事件将要去处理,就会调用应用层任务事件处理函数SDApp_ProcessEvent( byte task_id, UINT16 events ),并且把任务事件变量的值传给events,在事件处理函数中,events会分别和应用层定义的所有事件宏宏值进行与操作,如果发现哪个为0,那么就去执行这个事件处理对应的代码。

4、调用osal_set_event(SDApp_TaskID,SYS_EVENT_MSG)函数时,SDApp_TaskID就会去执行SYS_EVENT_MSG事件相应的代码。这是由于这个函数的本质是把SDApp_TaskID(应用层任务)的任务事件变量中对应于SYS_EVENT_MSG宏值为1的那一位变为 1,这样的话首先这个任务事件变量就变成非0,系统在检测到任务事件变量为非0时,就会去调用任务事件处理函数SDApp_ProcessEvent,在这个函数中,任务事件变量肯定和SYS_EVENT_MSG宏值与操作为1,所以必定会执行这个事件相关的代码。

几乎每个层都是一个任务,那么每一个层都有一个任务ID,任务处理函数,任务事件变量。

协议栈将各个层的所有任务处理函数都放在一个函数数组中,将所有的任务事件变量也都放到一个变量数组中。

任务ID是系统根据数组下标分配的,我们可以通过这个值立即找到这个任务自己的任务事件处理函数和事件变量,应用层任务的任务ID是8,taskArr[8]就是应用层事件处理函数,tasksEvents[8]就是应用层事件变量。

系统在osal_init_system()中的 osalInitTasks()中为各层分配任务ID。

5、osal_start_system(void )中会不断重复一个过程,在这个过程中,首先会不断轮询各层任务变量,如果发现哪一个任务变量不为0则会跳出轮询,然后通过这个不为0的任务变量找到对应的任务ID,从而进入对应任务ID的任务处理函数。处理完之后再继续这个过程。


猜你喜欢

转载自blog.csdn.net/x603560617/article/details/80212059