欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-09 14:39:26
...

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

ZStack版本:ZStack-CC2530-2.5.1a
程序下载和调试软件:TI SmartRF Flash Programmer
下载和调试器: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,即可打开工程。
打开工程后,出现如下界面:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
这是因为该工程是基于ZStack-CC2530-2.5.1a版本的,相较于IDE工具IAR来说版本太老,需要进行版本转换,我们只需选择"yes",IAR会自动帮我们进行转换。转换完成后,右击左上角的
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
选项,选择"Rebuild All” 进行编译,会发现有好多错误。
首先,我们仍然右击左上角的那个工程选项,选择“options”,出现如下界面,
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
将界面中圈出的数字“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"。
如下图所示:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
新建一个文件,保存为Coordinator.c,选择App行,右击选择Add,Add“Coordinator.c”,即可将该文件添加到App下。同理,新建Endevice.c文件,添加到App下。
选中新添加的Endevice.c文件,右击,选中“Options”,出现如下界面:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
点击上图红色圈中的框,出现对勾后,然后点击下方"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,出现如下界面:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
选择EndDeviceEB,点击"OK"按钮。然后选择Coordinator.c文件,点右键,选择options,选择Exclude from build,点击下方"OK"按钮。则Coordinator.c文件变灰。
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
设备端软件的编译,同样需要将上图的数字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”,如下图所示:

基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
勾选红色圈中的选项。
3、点选“Extra Output”项,界面如下:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
勾选前两个红色圈的方框,第二个圈为灰色,当勾选第一个框后,第二个框会变正常。然后将第三个红色圈中的字符更换成Enddevice.hex,最后将该界面下方的Output format:有“simple-code”,变成"inter-extended",最后点击"OK"按钮。
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
如上图,打开“f8w2530.xcl”,将红色209,210两行前面的注释去掉。
设置完成后,重新编译即可生成hex文件。
重点:需要将EndDeviceCB和CoordinatorEB两个工程都要如此设置,不同之处是,生成的hex文件名不同。
四、生成可在线调试的文件:
1、打开工程的"Options”选项。
2、点击"Linker"下的“Output”,如下图所示:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
勾选红色框,即可生成用于在线调试的.d51文件。
五、程序烧写
1、点开SmartRF Flash Programmer界面如下:
基于TI CC2530的 zigbee 开发(二)简单的无线传输组网实验
上面红色圈选择要烧写的hex文件。
下面红色圈为状态提示,烧写完成后,会提示如上图所示。

相关标签: Zigbee