1-2 实验2 点对点通信

本文详细介绍了ZigBee无线传感器网络的设计与实现过程,包括实验内容、无线传感器类型、编程方法及代码分析。通过协调器与终端节点的交互,实现了点对点通信,并通过数据接收与LED闪烁的逻辑展示了网络的有效性。

1、实验内容:两个ZigBee节点进行点对点通信,ZigBee节点2(终端节点EndDevice,稍后,下载EndDeviceEB里的代码)发送“LED”三个字符,ZigBee节点1(协调器节点Coordinator,稍后,下载CoordinatorEB里的代码)接受数据后,判断接受到的数据是否为“LED”,是,则使板子上的LED灯闪烁。

2、简介

无线传感器主要有三种类型:协调器、路由器、终端节点。

协调器:负责网络的组件、维护、控制终端节点的加入

路由器:负责数据包的路由的选择

终端节点:负责数据的采集

(本实验不用路由器)

3、编程(主要使用的是C:\Texas Instruments\ZStack-CC2530-2.3.1-1.4.0\Projects\zstack\Samples\GenericApp\CC2530DB中的GenericApp.eww工程,并在此基础上,添加修改代码,在App文件夹移除掉GenericApp.c、添加Coordinator.h、Coordinator.c、Enddevice.c)

4、协调器编程(协调器工作流程:开始-》初始化-》建立网络(不用进行相关的编程)-》接收数据(没接收到数据时,一直等待接受数据)-》使得LED闪烁),此处的代码在GenericApp.c的基础上修改添加代码以实现数据的接受和LED闪烁。

//Coordinator.h
#ifndef COORDINATOR_H
#define COORDINATOR_H

#include "ZComDef.h"  //??????????????

#define GENERICAPP_ENDPOINT   10

#define GENERICAPP_PROFID     0x0F04    //?????
#define GENERICAPP_DEVICEID   0x0001  //????

#define GENERICAPP_DEVICE_VERSION 0 //?????
#define GENERICAPP_FLAGS          0 //??????

#define GENERICAPP_MAX_CLUSTERS   1 //????????
#define GENERICAPP_CLUSTERID      1 //???????

extern void GenericApp_Init(byte task_id);
extern UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 evens);

#endif

//Coordinator.c
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include <string.h>

#include "Coordinator.h"

#include "DebugTrace.h"

#if !defined(WIN32) //????
#include "OnBoard.h"
#endif

#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"

const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS]=
{
  GENERICAPP_CLUSTERID 
};

//简单设备描述符(描述一个ZigBee设备节点)
const SimpleDescriptionFormat_t GenericApp_SimpleDesc=
{
  GENERICAPP_ENDPOINT,
  GENERICAPP_PROFID,
  GENERICAPP_DEVICEID,
  GENERICAPP_DEVICE_VERSION,
  GENERICAPP_FLAGS,
  GENERICAPP_MAX_CLUSTERS,
 
 (cId_t*)GenericApp_ClusterList, //?????
  0,
  (cId_t *)NULL
};

endPointDesc_t GenericApp_epDesc;//节点描述符
byte GenericApp_TaskID;//任务优先级
byte GenericApp_TransID;//数据发送序列号。

void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pckt);//消息处理函数
void GenericApp_SendTheMessage(void);//数据发送函数

void GenericApp_Init(byte task_id)//任务初始化函数
{
  GenericApp_TaskID     =task_id;   //初始化任务优先级(任务优先级有协议栈的操作系统OSAL分配)
  GenericApp_TransID    =0;         //发送数据包的序号初始化为0
  
  //对节点描述符进行初始化
  GenericApp_epDesc.endPoint    =GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id     =&GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc   =(SimpleDescriptionFormat_t*)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq  =noLatencyReqs;
  
  afRegister(&GenericApp_epDesc);//afRegister()对节点的描述符进行注册。注册后,才能使用OSAL提供的系统服务。
}


//消息处理函数  
     
UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)
{
  afIncomingMSGPacket_t* MSGpkt;//MSGpkt用于指向接收消息结构体的指针
  if(events&SYS_EVENT_MSG)
  {
  // MSGpkt=(afIncomingMSGPacket_t*)osal_msg_reveive(GenericApp_TaskID);//osal_msg_receive()从消息队列上接收消息
     MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID);
   while(MSGpkt)
   {
     switch(MSGpkt->hdr.event)
    {
    case AF_INCOMING_MSG_CMD:          //接受到新数据的消息的ID是AF_INCOMING_MSG_CMD,这个宏是在协议栈中定义好的值为0x1A
                                       //接受到的是无线数据包
      GenericApp_MessageMSGCB(MSGpkt);//功能是完成对接受数据的处理
      break;
    default:
      break;
    }
    
    osal_msg_deallocate((uint8 *)MSGpkt);//接收到的消息处理完后,释放消息所占的存储空间
    
   // MSGpkt = (afIncomingMSGPacket_t *)osal_msg_reveive(GenericApp_TaskID);
     MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID);
    //处理完一个消息后,再从消息队列里接受消息,然后对其进行相应处理,直到所有消息处理完
   }
   return (events ^ SYS_EVENT_MSG);
  }
    return 0;
}


void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt)
{
 unsigned char buffer[4]= "    ";
 
 switch(pkt->clusterId)
 {
 case GENERICAPP_CLUSTERID:
   osal_memcpy(buffer,pkt->cmd.Data,3);
   
   if((buffer[0]=='L')&&(buffer[1]=='E')&&(buffer[2]=='D'))
   {
      HalLedBlink(HAL_LED_1,0,50,500);    //LED2 闪烁
       HalLedBlink(HAL_LED_2,0,50,500);    //LED2 闪烁
      HalLedBlink(HAL_LED_3,0,50,500);    //LED2 闪烁
      HalLedBlink(HAL_LED_4,0,50,500);    //LED2 闪烁
   }
   else
   {
     HalLedSet(HAL_LED_2,HAL_LED_MODE_ON);//其他内容 LED2 亮    这几个函数在哪里定义了呢????
     
   }
   
   break;
 }
}

5、终端节点编程(终端节点流程:开始-》初始化-》加入网络-》发送数据-》发送完数据后使LED闪烁)此处的代码在添加代码以实现数据的发送和LED闪烁。

//Enddevice.c

#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include <string.h>

#include "Coordinator.h"

#include "DebugTrace.h"

#if !defined(WIN32)
#include "OnBoard.h"
#endif

#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"

const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS]=
{
 GENERICAPP_CLUSTERID
};

const SimpleDescriptionFormat_t GenericApp_SimpleDesc=
{
  GENERICAPP_ENDPOINT,
  GENERICAPP_PROFID,
  GENERICAPP_DEVICEID,
  GENERICAPP_DEVICE_VERSION,
  GENERICAPP_FLAGS,
  0,
  (cId_t*)NULL,
  GENERICAPP_MAX_CLUSTERS,
  (cId_t*)GenericApp_ClusterList
  
};

endPointDesc_t GenericApp_epDesc;//节点描述符
byte GenericApp_TaskID;          //任务优先级
byte GenericApp_TransID;         //数据发送序列号
devStates_t GenericApp_NwkState;//保存节点状态

void GenericApp_MessageMSGCB(afIncomingMSGPacket_t* pckt);//消息处理函数的声明
void GenericApp_SendTheMessage(void); //数据发送函数的声明

//任务初始化函数
void GenericApp_Init(byte task_id)
{
  GenericApp_TaskID     = task_id;//初始化任务优先级
  GenericApp_NwkState   =DEV_INIT; //初始化为DEV_INIT,表节点没有连接到ZigBee网络
  GenericApp_TransID    =0;        //发送数据包的序列号初始化为0
  
  //对节点描述符进行初始化
  GenericApp_epDesc.endPoint=GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id =&GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc=(SimpleDescriptionFormat_t*)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq=noLatencyReqs;
  
  //afRegister()函数将节点描述符进行注册,注册后才可以使用OSAL提供的系统服务
  afRegister(&GenericApp_epDesc);
}

//消息处理函数
UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)
{
  afIncomingMSGPacket_t* MSGpkt;
  
  if(events&SYS_EVENT_MSG)
  {
    MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID);
    
    while(MSGpkt)
    {
      switch(MSGpkt->hdr.event)
      {
    case ZDO_STATE_CHANGE:
      GenericApp_NwkState=(devStates_t)(MSGpkt->hdr.status);//读取节点的设备类型
      if(GenericApp_NwkState==DEV_END_DEVICE)
      {
        GenericApp_SendTheMessage(); //终端节点类型,执行无线数据发送
      }
      break;
    default:
      break;
      }
    osal_msg_deallocate((uint8*)MSGpkt);
    MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID);
    }
    return (events^SYS_EVENT_MSG);
  }
  return 0;
  
}

void GenericApp_SendTheMessage(void)
{
  unsigned char theMessageData[4]="LED";//存放发送数据
  afAddrType_t my_DstAddr;    
  my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;//数据发送模式:可选 单播、广播、多播方式  这里选Addr16Bit表单播
  my_DstAddr.endPoint=GENERICAPP_ENDPOINT;   //初始化端口函
  my_DstAddr.addr.shortAddr=0x0000;  //标志目的地址节点的网络地址  这里是协调器的地址
  
  //下面是数据发送                                                  长度  数据发送缓冲区
  AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,GENERICAPP_CLUSTERID,3,theMessageData,
			&GenericApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS);

      HalLedBlink(HAL_LED_1,0,50,500);    //LED2 闪烁
      HalLedBlink(HAL_LED_2,0,50,500);    //LED2 闪烁
      HalLedBlink(HAL_LED_3,0,50,500);    //LED2 闪烁
      HalLedBlink(HAL_LED_4,0,50,500);    //LED2 闪烁
  
}


6、代码分析:(协调节点和终端节点交叉分析)

协调器工作流程:开始-》初始化-》建立网络(不用进行相关的编程)-》接收数据(没接收到数据时,一直等待接受数据)-》使得LED闪烁

终端节点流程:开始-》初始化-》加入网络-》发送数据-》发送完数据后使LED闪烁

可知,协调器工作流程:开始-》初始化-》建立网络

然后是终端节点流程:开始-》初始化-》加入网络

(1)初始化:完成各种硬件的初始设置,这里主要讲任务初始化:void GenericApp_Init(byte task_id),调用该函数的是由main()一直往下调用的,过程如下:

int main( void )
osal_init_system( void )
void osalInitTasks( void )
GenericApp_Init( taskID );

任务初始化:void GenericApp_Init(byte task_id)的主要功能:

  1. //任务初始化函数  
  2. void GenericApp_Init(byte task_id)  
  3. {  
  4.   GenericApp_TaskID     = task_id;//初始化任务优先级  
  5.   GenericApp_NwkState   =DEV_INIT; //初始化为DEV_INIT,表节点没有连接到ZigBee网络  
  6.   GenericApp_TransID    =0;        //发送数据包的序列号初始化为0  
  7.     
  8.   //对节点描述符进行初始化  
  9.   GenericApp_epDesc.endPoint=GENERICAPP_ENDPOINT;  
  10.   GenericApp_epDesc.task_id =&GenericApp_TaskID;  
  11.   GenericApp_epDesc.simpleDesc=(SimpleDescriptionFormat_t*)&GenericApp_SimpleDesc;  
  12.   GenericApp_epDesc.latencyReq=noLatencyReqs;  
  13.  
  14.   //afRegister()函数将节点描述符进行注册,注册后才可以使用OSAL提供的系统服务  
  15.   afRegister(&GenericApp_epDesc);  
  16. }  

其中上面的那个些变量都是本文件中的局部变量(定义如下,除了GenericApp_epDesc被afRegister(&GenericApp_epDesc); 直接应用后,其他的变量都在哪引用了呢?

  1. endPointDesc_t GenericApp_epDesc;//节点描述符  
  2. byte GenericApp_TaskID;          //任务优先级  
  3. byte GenericApp_TransID;         //数据发送序列号  
  4. devStates_t GenericApp_NwkState;//保存节点状态
上面的 void GenericApp_Init(byte task_id)函数在协调器和终端节点基本上是一样的,不同的是在终端节点中多了一句GenericApp_NwkState   =DEV_INIT; //初始化为DEV_INIT,表节点没有连接到ZigBee网络 

(2)消息处理函数UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events) ,这个函数在协调器和终端节点都是有的。

先以终端节点的说:

int main( void )
{
  // Initialize the operating system
  osal_init_system();
...
  osal_start_system(); // No Return from here
  return 0;  // Shouldn't get here.
} // main()
//OSAL_Tasks.h 
typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );

//OSAL_GenericApp.c 
// The order in this table must be identical to the task initialization calls below in osalInitTask.
const pTaskEventHandlerFn tasksArr[] = {
...
  GenericApp_ProcessEvent
};
void osal_start_system( void )
{
  for(;;)  // Forever Loop
  {
  ...  
    do {
      if (tasksEvents[idx])  // Task is highest priority that is ready.
      {
        break;
      }
    } while (++idx < tasksCnt);

    if (idx < tasksCnt)
    {
      uint16 events;
      halIntState_t intState;
      HAL_ENTER_CRITICAL_SECTION(intState);
      events = tasksEvents[idx];
      tasksEvents[idx] = 0;  // Clear the Events for this task.
      HAL_EXIT_CRITICAL_SECTION(intState);
      events = (tasksArr[idx])( idx, events ); //调用了tasksEvents[idx]指向的函数
      HAL_ENTER_CRITICAL_SECTION(intState);
      tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
      HAL_EXIT_CRITICAL_SECTION(intState);
    }
    ...
  }
}
//Cooperation.h/Cooperation.c/Endevice.c
UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)

UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)中,

终端的代码是

  1. switch(MSGpkt->hdr.event)  
  2.       {  
  3.     case ZDO_STATE_CHANGE:  
  4.       GenericApp_NwkState=(devStates_t)(MSGpkt->hdr.status);//读取节点的设备类型  
  5.       if(GenericApp_NwkState==DEV_END_DEVICE)  
  6.       {  
  7.         GenericApp_SendTheMessage(); //终端节点类型,执行无线数据发送  
  8.       }  

之后是发送数据(要注意发送数据之前要做的一系列事情,比如端口函、对方的的网址、广播、单播还是多播)

  1. void GenericApp_SendTheMessage(void)  
  2. {  
  3.   unsigned char theMessageData[4]="LED";//存放发送数据  
  4.   afAddrType_t my_DstAddr;      
  5.   my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;//数据发送模式:可选 单播、广播、多播方式  这里选Addr16Bit表单播  
  6.   my_DstAddr.endPoint=GENERICAPP_ENDPOINT;   //初始化端口函  
  7.   my_DstAddr.addr.shortAddr=0x0000;  //标志目的地址节点的网络地址  这里是协调器的地址  
  8.   //下面是数据发送                                                  长度  数据发送缓冲区  
  9.   AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,GENERICAPP_CLUSTERID,3,theMessageData,&GenericApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS);  

协调器的是

  1.   switch(MSGpkt->hdr.event)  
  2.     {  
  3.     case AF_INCOMING_MSG_CMD:          //接受到新数据的消息的ID是AF_INCOMING_MSG_CMD,这个宏是在协议栈中定义好的值为0x1A  
  4.                                        //接受到的是无线数据包  
  5.       GenericApp_MessageMSGCB(MSGpkt);//功能是完成对接受数据的处理  
  6.       break;  

之后就是接受信息

  1. void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt)  
  2. {  
  3.  unsigned char buffer[4]= "    ";  
  4.  switch(pkt->clusterId)  
  5.  {  
  6.  case GENERICAPP_CLUSTERID:  
  7.    osal_memcpy(buffer,pkt->cmd.Data,3);  


本文参考自:《ZigBee无线传感器网络设计与实现》      王小强等人编著化学工业出版社


评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gdliweibing

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

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

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

打赏作者

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

抵扣说明:

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

余额充值