lesson7-2 Zigbee协议栈的使用

目录

Zigbee协议栈的使用

事件产生函数osal_set_event

事件定时器触发函数osal_start_timerEx

消息处理事务:osal_msg_send&osal_msg_receive

协议栈按键实验


Zigbee协议栈的使用

事件产生函数osal_set_event

uint8 osal_set_event( uint8 task_id, uint16 event_flag );

para1是任务ID,para2是任务类型

在Zstack中的程序代码按照功能来划分,分成不同的层,比如硬件操作相关叫做硬件层,网络相关的代码叫做网络层,自己写应用程序的部分叫做应用层。

几乎每一个层都是一个任务,系统为每一给任务分配一个字节的唯一数值编号,每一个任务都能处理一些它们能够处理的事务。我们把这个数值编号叫做任务ID,而它们能够处理的事务叫做事件。

(1)首先我们进入应用层APP中的任务事件处理函数中的SYS_EVENT_MSG任务中

(2)将应用层初始化函数中的应用层任务ID StarryApp_TaskID拿到

(3)然后再随便选择一个其它的任务,这里我选择StarryApp_SEND_MSG_EVT,并将原先的任务函数内容注释

(4)将这个两个作为osal_set_event的参数,并在协调器中调用

(5)在StarryApp_SEND_MSG_EVT任务中设置一个点亮LED2的操作

(6)下载调试

执行到断点1

再Go,执行到断点2

完成后灯成功点亮

这里补充一点,外设的初始化过程一定要全,比如初始化LED,如果缺少配置为普通IO模式这一步骤,可能会导致LED无法使用。这是因为在启动osal之前main函数中还初始化调用了TI的一些硬件实验,其中很多引脚的功能已经被初始化为片上外设了,所以我们使用时要自己修改,不能漏步骤。如果添加自己的一些外设初始化要放在osal_start_system函数前面,WatchDogEnable之后,如数码管等等

事件定时器触发函数osal_start_timerEx

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

第一个参数是任务编号,第二个参数是要处理的事务,第三个参数是时间(毫秒),指多长时间之后来处理这个事务

这个函数的作用是设置一个软件定时器定时一定时间,时间到了之后自动调用osal_set_event函数来处理相应事件(注意定时只能用一次)

具体使用过程不做介绍

如何自定义事件

跳转到头文件可以,找到事件定义处

定义一个自己的事件,事件宏定义的特点是二进制16位里面只能有1位为1。注意只能按位来定义,只能一个位为1,其余位为0,最多定义16个事件。也就是一个任务最多只能够处理16个不同的事件。

下面使用自定义事件+osal_start_timerEx来实现2s后点亮LED3

消息处理事务:osal_msg_send&osal_msg_receive

在Zstack里,任务事件定义的特点决定了,每一个任务最多只能处理16种不同的事件,而系统在运行的时候有许多事物需要处理,如果每一个事物处理都定义成一个事件,那么16种事件是肯定不够用的,所以引入了消息。

消息处理事务的原理:

定义了一个事件#define SYS_EVENT_MSG 0x8000 // A message is waiting event

当需要应用层任务来处理某个事务的时候,首先通过osal_msg_send函数给应用层任务发送一个消息,调用osal_set_event(StarryApp_TaskID,SYS_EVENT_MSG);

那么一来,应用层就会进入SYS_EVENT_MSG中处理,在这个事件处理里判断到底刚刚引发我们产生SYS_EVENT_MSG事件到底是哪一种类型的消息,然后根据消息的类型做相应的处理。

而消息的类型可以自己定义,这样一来消息的类型可以很多,那么应用层任务处理的事务种类就很多了。

我们以一个消息收发的过程为例。

keyChange_t *msgPtr;
msgPtr = (KeyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );//定义一个按钮状态改变的消息
if( msgPtr )
{
  msgPtr->hdr.event = KEY_CHANGE;//给这个消息填写类型
  msgPtr->keys=3;//赋值
  
  osal_msg_send( StarryApp_TaskID, (uint8 *)msgPtr );//把发送给应用层StarryApp_TaskID的消息发送到消息队列
}

首先定义一个按钮状态改变的消息,然后给这个消息填写相关的值,类型是按钮状态改变KEY_CHANGE,然后把发送给应用层StarryApp_TaskID的消息发送到消息队列,并且在osal_msg_send( StarryApp_TaskID, (uint8 *)msgPtr );函数中调用了osal_set_event(StarryApp_TaskID,SYS_EVENT_MSG);

所以一旦消息发送出,就会在系统事件中通过(afIncomingMSGPacket_t *)osal_msg_receive( StarryApp_TaskID );函数取出引发系统事件的消息

然后判断得出是按键改变的消息,然后在按键改变的情况中调用StarryApp_HandleKeys函数

这是协议栈自带的处理函数,我们可以根据需要更改

协议栈按键实验

首先添加我们自己的板级支持包

#include "iocc2530.h"
#define uint unsigned int
#define uchar unsigned char

//定义控制LED灯的端口
#define LED1 P1_0    //定义LED1
#define KEY1 P0_0       //中断口
#define LED2 P1_1
#define KEY2 P0_1

//函数声明
void Delayms(uint);        //延时函数
void InitLed(void);        //初始化P1 P2口
void KeyInit();                // 按键初始化
uchar KeyValue=0;



#include "Starry_key.h"

//延时函数

void Delayms(uint xms)  // i=xms 即延时i毫秒
{
 uint i,j;
 for(i=xms;i>0;i--)
   for(j=587;j>0;j--);
}


//LED初始化程序

void InitLed(void)
{
  P1SEL &= ~0x01;
  P1DIR |= 0x01;    // P1_0定义为输出
  P1INP |= 0X01;    //打开下拉 
  LED1 = 0;       //  LED1灯熄灭    
  
  P1SEL &= ~0x02;
  P1DIR |= 0x02;
  P1INP |= 0X02;
  LED2 = 0;
}


//KEY初始化程序--外部中断方式

void InitKey()
{
  /*配置输入IO口*/
  P0SEL &= 0xFE;//1111 1110 P0_0 普通IO模式
  P0DIR &= 0xFE;//输入模式
  P0INP &= 0xFE;//上下拉模式
 
  
  P0SEL &= 0xFD;
  P0DIR &= 0xFD;//输入模式
  P0INP &= 0xFD;//上下拉模式
  P2INP &= 0xDF;//上拉
  /*配置外部中断*/
  P0IE=1;//开启组开关
  P0IEN |= 0x01;//开启P0_0中断使能
  P0IEN |= (0x01<<1);//开启P0_1中断使能
  EA=1;//开启总中断
  PICTL |= 0x01;//把P0组配置为下降沿触发
}

 
      //中断处理函数 
 
#pragma vector = P0INT_VECTOR    //格式:#pragma vector = 中断向量,紧接着是中断处理程序
  __interrupt void P0_ISR(void) 
 { 
  if(KEY2==0)//P0_1引发了外部中断
  {
    Delayms(10);           // 去除抖动
    LED2=~LED2;            // 改变LED2状态
  }
  if(KEY1==0)//P0_0引发了外部中断
  {
    Delayms(10);           // 去除抖动
    LED1=~LED1;            // 改变LED1状态
  }

  P0IFG = 0;             //清中断标志 
  P0IF = 0;             //清中断标志 
 } 

然后把协议栈自带的hal_key.c中的外部中断有关部分代码全部注释掉,否则会出现重定义

在zmain.c中调用测试

下面正式进行协议栈按键实验的编写

(1)首先自定义按键事件#define StarryApp_My_KEY_EVT 0x0008

(2)然后在StarryApp_ProcessEvent中编写处理操作

(3)对外部中断内容进行修改,换成osal_start_timerEx(StarryApp_TaskID,StarryApp_MY_KEY_EVT,100);还要注意变量和函数的外部调用

修改后的按键C文件内容

#include "Starry_key.h"
#include "StarryApp.h"
extern byte StarryApp_TaskID;
extern uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value );
//延时函数

void Delayms(uint xms)  // i=xms 即延时i毫秒
{
 uint i,j;
 for(i=xms;i>0;i--)
   for(j=587;j>0;j--);
}


//LED初始化程序

void InitLed(void)
{
  P1SEL &= ~0x01;
  P1DIR |= 0x01;    // P1_0定义为输出
  P1INP |= 0X01;    //打开下拉 
  LED1 = 0;       //  LED1灯熄灭    
  
  P1SEL &= ~0x02;
  P1DIR |= 0x02;
  P1INP |= 0X02;
  LED2 = 0;
}


//KEY初始化程序--外部中断方式

void InitKey()
{
  /*配置输入IO口*/
  P0SEL &= 0xFE;//1111 1110 P0_0 普通IO模式
  P0DIR &= 0xFE;//输入模式
  P0INP &= 0xFE;//上下拉模式
 
  
  P0SEL &= 0xFD;
  P0DIR &= 0xFD;//输入模式
  P0INP &= 0xFD;//上下拉模式
  P2INP &= 0xDF;//上拉
  /*配置外部中断*/
  P0IE=1;//开启组开关
  P0IEN |= 0x01;//开启P0_0中断使能
  P0IEN |= (0x01<<1);//开启P0_1中断使能
  EA=1;//开启总中断
  PICTL |= 0x01;//把P0组配置为下降沿触发
}

 
      //中断处理函数 
 
#pragma vector = P0INT_VECTOR    //格式:#pragma vector = 中断向量,紧接着是中断处理程序
  __interrupt void P0_ISR(void) 
 { 
  osal_start_timerEx(StarryApp_TaskID,StarryApp_MY_KEY_EVT,100);

  P0IFG = 0;             //清中断标志 
  P0IF = 0;             //清中断标志 
 } 

对于事件处理,我们还可以进一步添加按钮状态改变消息,从而使用消息发送osal_msg_send函数来通过消息队列的方法进一步优化。

按键消息创建:

按键消息处理:

使用协议栈的osal_start_timerEx(StarryApp_TaskID,StarryApp_MY_KEY_EVT,100);函数来代替中断里的延时的意义是避免了延时函数在中断里浪费过多时间,从而最终影响通信。使用后,即使按键抖动带来误触,也只是将里的触发时间重新置为100ms,并不会导致osal_start_timerEx中的osal_set_event函数被重复执行。不仅避免了按键抖动的问题还大大提高了代码的执行效率。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Zigbee协议栈是一种通信协议栈,用于在无线网络设备之间进行通信。它基于IEEE 802.15.4标准,并提供了一组高协议,用于管理节点之间的通信和网络形成。Zigbee协议栈由物理、MAC、网络和应用组成,其中物理和MAC一起被称为Zigbee PRO,网络和应用被称为Zigbee应用。物理使用ISM频段,支持多种无线信道,MAC实现透明的数据传输和网络管理,网络提供多种路由和协议选择,应用包括多种应用程序和服务。Zigbee协议栈被广泛应用于智能家居、工业自动化、医疗健康和农业等领域。 使用Zigbee协议栈,需要先选择一个合适的芯片或模块,然后将其集成到应用中。通常,芯片或模块供应商提供了与Zigbee协议栈兼容的开发工具和API,开发人员可以利用这些工具和API进行开发。开发过程中,需要根据具体应用的需求进行协议栈的配置和调试,以保证其正常工作。 Z-Stack是一种基于Zigbee协议栈的开发框架,提供了一套完整的工具和API,用于开发Zigbee应用程序。Z-Stack工作流程通常包括以下几个步骤: 1. 硬件设计:选择合适的芯片或模块,并进行硬件设计。 2. 软件开发:使用Z-Stack提供的API进行软件开发,包括协议栈的配置和应用程序的开发。 3. 调试测试:通过Z-Stack提供的调试工具和测试工具,对应用程序进行调试和测试,确保其正常工作。 4. 部署运营:将应用程序部署到实际设备中,进行运营和维护。 总的来说,Zigbee协议栈和Z-Stack提供了一套完整的开发框架,用于开发Zigbee应用程序,可以大大简化开发过程,并提高应用程序的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

竹烟淮雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值