1-15 实验12 ZigBee无线传感器网络远程数据采集系统

ZigBee无线传感器网络远程数据采集系统

1、实验内容:协调器建立网络,路由器和终端节点加入网络,然后周期性地采集温度和电压发送给协调器,协调器通过串口发送给PC的串口调试助手

2、补充:(为了便于数据的传输和管理,传输的数据用一个结构体表示)如下

//NewCoordinator.h
typedef union h
{
 unsigned char databuf[18];
 struct RFRXBUF
 {
  unsigned char head[2];  //  "&&"
  unsigned char type[3];  //  "ROU"或 "END"
  unsigned char myNWK[4]; //  自身的网络地址
  unsigned char pNWK[4];  //  父节点的网络地址
  unsigned char value[4];  // value[0]表采集数据的类型  如:W表温度  V表电压 后面几位表数值
  unsigned char tail;     //"&"
 }BUF;
}RFTX;
上面是个联合结构体,便于数据的强制类型转换。

3、程序设计

     协调器程序设计(负责接收来自路由或终端节点发送来的数据,并通过串口发送到PC的串口助手进行显示)

/***************************
 * INCLUDES
 */
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "NewCoordinator.h"
//#include "GenericApp.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 "aps_groups.h"


#define SEND_TO_ALL_EVENT 0x01

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

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

// This is the Endpoint/Interface description.  It is defined here, but
// filled-in in GenericApp_Init().  Another way to go would be to fill
// in the structure here and make it a "const" (in code space).  The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t GenericApp_epDesc;

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
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;

/*********************************************************************
 * LOCAL FUNCTIONS
 */
//void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
//void GenericApp_HandleKeys( byte shift, byte keys );
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );//处理事件
void GenericApp_SendTheMessage( void );//发送数据
static void rxCB(uint8 port,uint8 envent);

/*********************************************************************
 * NETWORK LAYER CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      GenericApp_Init
 *
 * @brief   Initialization function for the Generic App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */
void GenericApp_Init( byte task_id )
{
  GenericApp_TaskID = task_id;
 // GenericApp_NwkState = DEV_INIT;   //这句不注释掉 会怎样???
  GenericApp_TransID = 0;

  // 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 );
  
  //串口的设置,并打开串口
  halUARTCfg_t uartConfig;
  uartConfig.configured =TRUE;
  uartConfig.baudRate   =HAL_UART_BR_115200;
  uartConfig.flowControl=FALSE;
  uartConfig.callBackFunc=NULL;//???????????????????????????????????
  //uartConfig.callBackFunc=rxCB;
  HalUARTOpen(0,&uartConfig);   //打开串口
}

/*********************************************************************
 * @fn      GenericApp_ProcessEvent
 *
 * @brief   Generic Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  none
 */
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  // HalLedBlink(HAL_LED_1,0,50,500);
  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
         case AF_INCOMING_MSG_CMD:  //天线接收到数据
        //  HalLedBlink(HAL_LED_2,0,50,500);
          GenericApp_MessageMSGCB( MSGpkt );   //接收数据并把数据发送到UART
         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;
}


/*********************************************************************
 * LOCAL FUNCTIONS
 */

/*********************************************************************
 * @fn      GenericApp_MessageMSGCB
 *
 * @brief   Data message processor callback.  This function processes
 *          any incoming data - probably from other devices.  So, based
 *          on cluster ID, perform the intended action.
 *
 * @param   none
 *
 * @return  none
 */
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  RFTX rftx;
  unsigned char changeline[2]={0x0A,0x0D};
  switch ( pkt->clusterId )
  {

    case GENERICAPP_CLUSTERID:
      osal_memcpy(&rftx,pkt->cmd.Data,sizeof(rftx));
      HalUARTWrite(0,rftx.databuf,sizeof(rftx));  //从这一行你就能看到联合体的作用、好处
      HalUARTWrite(0,changeline,2);  
      break;
  }
}
路由器节点或终端节点(共用的Sonsor.h、Sonsor.c、NewEnddevice.c文件)

//Sensor.h
#ifndef SENSOR_H
#define SENSOR_H
#include <hal_types.h>
extern int8 readTemp(void);
extern unsigned int getVddvalue(void);
#endif
Sensor.c主要用于传感器采集的实现

#include "Sensor.h"
#include <ioCC2530.h>

//你知道下面宏的具体含义是什么吗???
#define ADC_REF_115V 0x00
#define ADC_DEC_256  0x20
#define ADC_CHN_TEMP 0x0e
#define ADC_DEC_064      0x00
#define ADC_CHN_VDD3     0x0f

int8 readTemp(void)
{
 static uint16 reference_voltage;
 static uint8  bCalibrate=TRUE;
 
 unsigned char tmpADCCON3=ADCCON3;//????????
 uint16 value;
 int8 temp;

 ATEST=0x01;  //使能温度传感器
 TR0|=0x01;   //连接温度传感器
 ADCIF=0;     //?????

 ADCCON3=(ADC_REF_115V|ADC_DEC_256|ADC_CHN_TEMP);//???????
 
 while(!ADCIF)//???????
   ;
 ADCIF=0;
 
 value=ADCL;                   //这里应该是取低位
 value |=((uint16)ADCH)<<8;   //这里应该是取高位
 
 value>>=4;//除以16???
 
 if(bCalibrate)//记录第一次读取的温度值,用于校正温度数据
 {
   reference_voltage=value;
   bCalibrate=FALSE;   
 }
 
 temp=22+((value-reference_voltage)/4);//温度校正函数
 return temp;
 
}

unsigned int getVddvalue(void)
{
 unsigned int value;
 unsigned char tmpADCCON3=ADCCON3;
 ADCIF=0;
 ADCCON3=(ADC_REF_115V|ADC_DEC_064|ADC_CHN_VDD3);
 while(!ADCIF)
   ;
 value=ADCH;
 ADCCON3=tmpADCCON3;
 return (value);
}
NewEndDevice.c

/*********************************************************************
 * INCLUDES
 */
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"

#include "NewCoordinator.h"
//#include "GenericApp.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"

#define SEND_DATA_EVENT 0x01
#include "Sensor.h"
/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

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

// This is the Endpoint/Interface description.  It is defined here, but
// filled-in in GenericApp_Init().  Another way to go would be to fill
// in the structure here and make it a "const" (in code space).  The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t GenericApp_epDesc;

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
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;  //???????????????

/*********************************************************************
 * LOCAL FUNCTIONS
 */
//void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
//void GenericApp_HandleKeys( byte shift, byte keys );
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void GenericApp_SendTheMessage( void );

void SendInfo(void);
void sendVdd(void);
void sendTemp(void);

void To_string(uint8 *dest,char* src,uint8 length);//二进制书转化为十六进制数  


//static void rxCB(uint8 port,uint8 envent);

/*********************************************************************
 * NETWORK LAYER CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      GenericApp_Init
 *
 * @brief   Initialization function for the Generic App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */

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

  // 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 );  
}


/*********************************************************************
 * @fn      GenericApp_ProcessEvent
 *
 * @brief   Generic Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  none
 */
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_ROUTER)
              || (GenericApp_NwkState == DEV_END_DEVICE) )
          {
            osal_set_event(GenericApp_TaskID,SEND_DATA_EVENT);
          }
          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);
  }
   if ( events &  SEND_DATA_EVENT )
  {
    sendTemp();
    sendVdd();
         osal_start_timerEx( GenericApp_TaskID,
                        SEND_DATA_EVENT,    //事件
                           GENERICAPP_SEND_MSG_TIMEOUT );//定时时间
    return (events ^ SEND_DATA_EVENT);
  }
  // Discard unknown events
  return 0;
}

void sendTemp(void)
{
 RFTX rftx;
 uint16 nwk;
 osal_memcpy(rftx.BUF.head,"&&",2);
 if(GenericApp_NwkState==DEV_ROUTER)
   osal_memcpy(rftx.BUF.type,"ROU",3);
 if(GenericApp_NwkState==DEV_END_DEVICE)
   osal_memcpy(rftx.BUF.type,"END",3);
 nwk=NLME_GetShortAddr();
 To_string(rftx.BUF.myNWK,(uint8*)&nwk,2);
 nwk=NLME_GetCoordShortAddr();
 To_string(rftx.BUF.pNWK,(uint8*)&nwk,2);
 
 uint16 tempvalue;

 tempvalue=readTemp();
 rftx.BUF.value[0]='W';
 rftx.BUF.value[1]=tempvalue/10+'0';
 rftx.BUF.value[2]=tempvalue%10+'0';
 rftx.BUF.value[3]='*';
 
 rftx.BUF.tail='&';
 
 afAddrType_t my_DstAddr;
 my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;
 my_DstAddr.endPoint=GENERICAPP_ENDPOINT;
 my_DstAddr.addr.shortAddr=0x0000;
 AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,GENERICAPP_CLUSTERID,
                18,
                (uint8*)&rftx,
                &GenericApp_TransID,
                AF_DISCV_ROUTE,
                AF_DEFAULT_RADIUS); 
}

void sendVdd(void)
{
 RFTX rftx;
 uint16 nwk;
 osal_memcpy(rftx.BUF.head,"&&",2);
 if(GenericApp_NwkState==DEV_ROUTER)
   osal_memcpy(rftx.BUF.type,"ROU",3);
 if(GenericApp_NwkState==DEV_END_DEVICE)
   osal_memcpy(rftx.BUF.type,"END",3);
 nwk=NLME_GetShortAddr();
 To_string(rftx.BUF.myNWK,(uint8*)&nwk,2);
 nwk=NLME_GetCoordShortAddr();
 To_string(rftx.BUF.pNWK,(uint8*)&nwk,2);
 
 uint16 vddvalue;

 vddvalue=69*getVddvalue()/256;
 rftx.BUF.value[0]='V';
 rftx.BUF.value[1]=vddvalue/10+'0';
 rftx.BUF.value[2]='.';
 rftx.BUF.value[3]=vddvalue%10+'0'; 
 
 rftx.BUF.tail='&';
 
 afAddrType_t my_DstAddr;
 my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;
 my_DstAddr.endPoint=GENERICAPP_ENDPOINT;
 my_DstAddr.addr.shortAddr=0x0000;
 if(AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,GENERICAPP_CLUSTERID,
                18,
                (uint8*)&rftx,
                &GenericApp_TransID,
                AF_DISCV_ROUTE,
                AF_DEFAULT_RADIUS)== afStatus_SUCCESS )
  {
      HalLedBlink(HAL_LED_1,0,50,500);
  }
}

void To_string(uint8 *dest,char* src,uint8 length)//二进制书转化为十六进制数  
{  
  uint8* xad;  
  uint8 i=0;  
  uint8 ch;  
  xad=src+length-1;  
  for(i=0;i<length;i++,xad--)  
  {  
   ch=(*xad>>4)&0x0F;  //除以十六  
   dest[i<<1]=ch+((ch<10)?'0':'7');  
   ch=*xad&0x0F;  
   dest[(i<<1)+1]=ch+((ch<10)?'0':'7');  
  }  
}  
4、实验结果








     




  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gdliweibing

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

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

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

打赏作者

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

抵扣说明:

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

余额充值