基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验

基于TI CC2530的 zigbee 开发(二)简单的无线传输组网例程

ZStack版本:ZStack-CC2530-2.5.1a
下载和调试器:SmartRF04EB
IDE开发软件:IAR Embedded Workbench IDE - 8051 10.20.1
本例程的基本功能是实现两个zigbee节点的点对点通信功能。其中节点1作为协调器建立zigbee网络,节点2作为终端设备,加入网络,然后节点2发送“test”四个字符,如果节点1收到数据后,确认是“test”数据,则点亮开发板上的LED灯。
一、打开工程
进入ZStack-CC2530-2.5.1a\Projects\zstack\Samples\GenericApp\CC2530DB目录,双击GenericApp.eww,即可打开工程。
打开工程后,出现如下界面:
在这里插入图片描述
这是因为该工程是基于ZStack-CC2530-2.5.1a版本的,相较于IDE工具IAR来说版本太老,需要进行版本转换,我们只需选择"yes",IAR会自动帮我们进行转换。转换完成后,右击左上角的
在这里插入图片描述
选项,选择"Rebuild All” 进行编译,会发现有好多错误。
首先,我们仍然右击左上角的那个工程选项,选择“options”,出现如下界面,
在这里插入图片描述
将界面中圈出的数字“16”,更改成8。然后,下载新版的Z-Stack,我下载的是Z-Stack 3.0.2,将Z-Stack 3.0.2\Projects\zstack\ZMain\TI2530DB文件夹下的chipcon_cstartup.s51代替ZStack-CC2530-2.5.1a\Projects\zstack\ZMain\TI2530DB下的相同文件,重新编译,发现没有任何错误。
二、节点1协调器代码的开发
在左侧的项目导航栏选择APP下的GenericApp.c文件,右击,选择"Remove"。
如下图所示:
在这里插入图片描述
新建一个文件,保存为Coordinator.c,选择App行,右击选择Add,Add“Coordinator.c”,即可将该文件添加到App下。同理,新建Endevice.c文件,添加到App下。
选中新添加的Endevice.c文件,右击,选中“Options”,出现如下界面:
在这里插入图片描述
点击上图红色圈中的框,出现对勾后,然后点击下方"ok"按钮,则Endevice.c文件变成灰色。因为这个文件是终端设备的文件,而现在我们要编译的是协调器的程序,所以将该文件排除编译。
Coordinator.c的代码如下:

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

#include "DebugTrace.h"

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

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"

#include "OSAL_Nv.h"

#include "GenericApp.h"

/*********************************************************************
 * GLOBAL VARIABLES
 */

// This list should be filled with Application specific Cluster IDs.
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
  GENERICAPP_CLUSTERID
};

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;
  0,          //  byte  AppNumInClusters;
  (cId_t *)NULL   //  byte *pAppInClusterList;
};


endPointDesc_t GenericApp_epDesc;

byte GenericApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // GenericApp_Init() is called.
byte GenericApp_TransID;  // This is the unique message ID (counter)

static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void GenericApp_Init( uint8 task_id )
{
  
  GenericApp_TaskID = task_id;
  GenericApp_TransID = 0;
  // Device hardware initialization can be added here or in main() (Zmain.c).
  // If the hardware is application specific - add it here.
  // If the hardware is other parts of the device add it in main().
  
  // Fill out the endpoint description.
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id = &GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &GenericApp_epDesc );
}

uint16 GenericApp_ProcessEvent( uint8 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 AF_INCOMING_MSG_CMD:
            GenericApp_MessageMSGCB( MSGpkt );
        break;

        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );

      // Next
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }
  return 0;

}

static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  
  unsigned char buffer[4];
  unsigned char LEDState = 0;
  osal_memcpy(buffer,pkt->cmd.Data,4);
  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID:
        if((buffer[0] == 't') && (buffer[1] == 'e') && (buffer[2] == 's') && (buffer[3] == 't'))
        {
          LEDState++;
          if(LEDState%2 == 0)
              HalLedSet(HAL_LED_1,HAL_LED_MODE_ON);
          else
              HalLedSet(HAL_LED_1,HAL_LED_MODE_OFF);  
        }        
      break;
  }
}

上述代码,大部分为从我们移除的GenericApp.c文件复制得到的,只是为了实现两个节点的无线通信,对代码进行了裁剪,以使代码看起来简单明了。
const SimpleDescriptionFormat_t GenericApp_SimpleDesc 数据结构是用来描述一个zigbee的设备节点。
代码中定义了三个全局变量,
1、endPointDesc_t GenericApp_epDesc; 节点描述符变量。
2、byte GenericApp_TaskID; 任务优先级变量。
3、byte GenericApp_TransID; 数据发送序号变量。
void GenericApp_Init( uint8 task_id ) 任务初始化函数;
uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events ) 事件处理函数;
static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) 消息处理函数;
协调器的处理流程如下,首先初始化任务GenericApp_Init,然后循环处理是否有事件发生,如果有事件发生,则调用GenericApp_ProcessEvent事件处理函数,因为有可能发生的事件很多,但是本实现我们只关心是否有新的无线接收数据事件的发生,所以我们只判断AF_INCOMING_MSG_CMD该事件即可,如果是,则调用该事件的消息处理函数GenericApp_MessageMSGCB,本例中,我们是判断接收到的消息是“test”,如果是则将LED灯翻转一次。
二、节点2设备端代码的开发
点击Project菜单,选择Edit Configurations,出现如下界面:
在这里插入图片描述
选择EndDeviceEB,点击"OK"按钮。然后选择Coordinator.c文件,点右键,选择options,选择Exclude from build,点击下方"OK"按钮。则Coordinator.c文件变灰。
在这里插入图片描述
设备端软件的编译,同样需要将上图的数字16,变成8。
Endevice.c的代码如下:

#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"


#include "DebugTrace.h"

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

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"

#include "GenericApp.h"

#define SEND_DATA_EVENT 0x01

/*********************************************************************
 * GLOBAL VARIABLES
 */

// This list should be filled with Application specific Cluster IDs.
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
  GENERICAPP_CLUSTERID
};

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;
  0,                                //  byte  AppNumInClusters;
  (cId_t *)NULL,  //  byte *pAppInClusterList;
  GENERICAPP_MAX_CLUSTERS,          //  byte  AppNumInClusters;
  (cId_t *)GenericApp_ClusterList   //  byte *pAppInClusterList;
};

endPointDesc_t GenericApp_epDesc;

byte GenericApp_TaskID;   // Task ID for internal task/event processing
                          // This variable will be received when
                          // GenericApp_Init() is called.
devStates_t GenericApp_NwkState;

byte GenericApp_TransID;  // This is the unique message ID (counter)

afAddrType_t GenericApp_DstAddr;

static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
static void GenericApp_SendTheMessage( void );

void GenericApp_Init( uint8 task_id )
{
  GenericApp_TaskID = task_id;
  GenericApp_NwkState = DEV_INIT;
  GenericApp_TransID = 0;

  // Device hardware initialization can be added here or in main() (Zmain.c).
  // If the hardware is application specific - add it here.
  // If the hardware is other parts of the device add it in main().
  
  // Fill out the endpoint description.
  GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
  GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_DstAddr.addr.shortAddr = 0xFFFF;
 
  
  GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
  GenericApp_epDesc.task_id = &GenericApp_TaskID;
  GenericApp_epDesc.simpleDesc
            = (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
  GenericApp_epDesc.latencyReq = noLatencyReqs;

  // Register the endpoint description with the AF
  afRegister( &GenericApp_epDesc );
  
}

uint16 GenericApp_ProcessEvent( uint8 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))
          {
            // Start sending "the" message in a regular interval.
            GenericApp_SendTheMessage();
          }
       break;
        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );

      // Next
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }
  return 0;
}

static void GenericApp_SendTheMessage( void )
{
  unsigned char theMessageData[4] = {'t','e','s','t'};
  AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       4,
                       theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
}

设备端的软件和协调器的代码差不多,大部分也是从GenericApp.c文件复制得到的。
不同之处有以下几处:
1、afAddrType_t GenericApp_DstAddr; 目标地址,用来描述目标地址的地址模式、地址、端点等参数。
2、ZDO_STATE_CHANGE 事件处理函数中,变为检测到设备状态为设备,则调用消息发送函数。
3、static void GenericApp_SendTheMessage( void ) 消息发送函数,将要发送的“test”消息发送出去。
三、让编译软件生成可烧写的hex文件
1、打开工程的"Options”选项。
2、点击"Linker"下的“Output”,如下图所示:

在这里插入图片描述
勾选红色圈中的选项。
3、点选“Extra Output”项,界面如下:
在这里插入图片描述
勾选前两个红色圈的方框,第二个圈为灰色,当勾选第一个框后,第二个框会变正常。然后将第三个红色圈中的字符更换成Enddevice.hex,最后将该界面下方的Output format:有“simple-code”,变成"inter-extended",最后点击"OK"按钮。
在这里插入图片描述
如上图,打开“f8w2530.xcl”,将红色209,210两行前面的注释去掉。
设置完成后,重新编译即可生成hex文件。
重点:需要将EndDeviceCB和CoordinatorEB两个工程都要如此设置,不同之处是,生成的hex文件名不同。
四、生成可在线调试的文件:
1、打开工程的"Options”选项。
2、点击"Linker"下的“Output”,如下图所示:
在这里插入图片描述
勾选红色框,即可生成用于在线调试的.d51文件。
五、程序烧写
在这里插入图片描述
点击上图红色圈中的三角形,进入下载和调试界面
在这里插入图片描述
下载完成后,光标停留在main函数的入口处,如果需要调试,则进行调试否则,点击下图
在这里插入图片描述
红色X按钮,退出调试。下载成功。

  • 10
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值