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

来源:互联网 发布:sql两张表横向合并 编辑:程序博客网 时间:2024/04/29 21:50
                                                                                ZigBee无线传感器网络远程数据采集系统设计  

          原理:

 在实验中,协调器节点负责建立网络,路由器节点与终端节点申请加入网络,然后周期性地采集温度、电压等发送给协调器,协调器通过串口将数据发送给PC机。


         协调器与路由器、采集终端编码:(实验采用CC2530-EB开发板)

      

//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"  

#include "Sensor.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_tGenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS]= 

 GENERICAPP_CLUSTERID  

}; 

 

//简单设备描述符(描述一个ZigBee设备节点)  

const SimpleDescriptionFormat_tGenericApp_SimpleDesc= 

 GENERICAPP_ENDPOINT, 

 GENERICAPP_PROFID, 

 GENERICAPP_DEVICEID, 

 GENERICAPP_DEVICE_VERSION, 

 GENERICAPP_FLAGS, 

 GENERICAPP_MAX_CLUSTERS, 

 (cId_t*)GenericApp_ClusterList,  

 0, 

 (cId_t *)NULL 

}; 

 

endPointDesc_tGenericApp_epDesc;//节点描述符  

byte GenericApp_TaskID;//任务优先级  

byte GenericApp_TransID;//数据发送序列号。  

 

voidGenericApp_MessageMSGCB(afIncomingMSGPacket_t *pckt);//消息处理函数  

voidGenericApp_SendTheMessage(void);//数据发送函数  

 

void GenericApp_Init(bytetask_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提供的系统服务。  

 halUARTCfg_t uartConfig;//该结构体变量是实现 串口的配置

 

 //串口的初始化  

 uartConfig.configured  =TRUE; 

 uartConfig.baudRate    =HAL_UART_BR_115200;//波特率  

 uartConfig.flowControl =FALSE;             //流控制  

 HalUARTOpen(0,&uartConfig);                //串口是否打开  

   

//消息处理函数      

UINT16GenericApp_ProcessEvent(byte task_id,UINT16 events)

 afIncomingMSGPacket_t* MSGpkt;//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:          //接受到新数据的消息的ID是AF_INCOMING_MSG_CMD,这个宏是在协议栈中定义好的值为0x1A  

                                       //接受到的是无线数据包  

      GenericApp_MessageMSGCB(MSGpkt);//功能是完成对接受数据的处理  

      break; 

    default: 

      break; 

    }   

    osal_msg_deallocate((uint8 *)MSGpkt);//接收到的消息处理完后,释放消息所占的存储空间      

    MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID); 

    //处理完一个消息后,再从消息队列里接受消息,然后对其进行相应处理,直到所有消息处理完  

  } 

  return (events ^ SYS_EVENT_MSG); 

 } 

  return 0; 

 //数据处理函数

voidGenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt) 

 

RFTX rftx;

unsigned char changeline[2]={0x0A,0x0D};//回车换行符的ASICC码

 switch(pkt->clusterId) 

  { 

 case GENERICAPP_CLUSTERID: 

  osal_memcpy(&rftx,pkt->cmd.Data,sizeof(rftx));//把pkt->cmd.Data的数据复制到buffer  

  HalUARTWrite(0,rftx.databuf,sizeof(rftx));//向串口发送数据包

    HalUARTWrite(0,changeline,2);//输出回车换行符

  

  break; 

  } 

}  


//Coordinator.h

 

#ifndef COORDINATOR_H

#define COORDINATOR_H

 

#ifdef __cplusplus

extern "C"

{

#endif

 

#include "ZComDef.h"

 

#define GENERICAPP_ENDPOINT           10

 

#define GENERICAPP_PROFID             0x0F04

#define GENERICAPP_DEVICEID           0x0001

#defineGENERICAPP_DEVICE_VERSION     0

#define GENERICAPP_FLAGS              0

 

#defineGENERICAPP_MAX_CLUSTERS       1

#define GENERICAPP_CLUSTERID          1

 

#defineGENERICAPP_SEND_MSG_TIMEOUT   5000   

 

#defineGENERICAPP_SEND_MSG_EVT       0x0001

 

typedef union h

{

  unsigned char databuf[18];

 struct RFRXBUF{

  unsigned char head[2];

 unsigned char type[3];

 unsigned char myNWK[4];//存储本节点网络地址

 unsigned char pNWK[4];//存储父节点网络地址

 unsigned char value[4];

 unsigned char tail;//命令尾

 }BUF;

}RFTX;

 

extern void GenericApp_Init( bytetask_id );

 

extern UINT16GenericApp_ProcessEvent( byte task_id, UINT16 events );

 

#ifdef __cplusplus

}

#endif

 

#endif /* GENERICAPP_H */


//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 "Sensor.h"

#include "hal_uart.h"  

#define SEND_DATA_EVENT 0x01  //定义发送事件id为0x01 

 

 

const cId_tGenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS]= 

 GENERICAPP_CLUSTERID 

}; 

 //初始化端口描述符  

const SimpleDescriptionFormat_tGenericApp_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;//保存节点状态  

 

voidGenericApp_MessageMSGCB(afIncomingMSGPacket_t* pckt);//消息处理函数的声明  

void GenericApp_SendTheMessage(void); //数据发送函数的声明  

 voidsendTemp(void);

void sendVdd(void);

void To_string(uint8 *dest,char * src,uint8length);

 

//任务初始化函数  

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(bytetask_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_NwkState==DEV_ROUTER)) 

     { 

       //当中断节点加入网络后使用osal_set_envent()函数设置SEND_DATA_EVENT事件,当事件发生时,执行事件处理函数  

       osal_set_event(GenericApp_TaskID,SEND_DATA_EVENT);//添加用户自定义任务事件(以任务号对应事件的形式添加)  

      } 

     break; 

   default: 

     break; 

     } 

   osal_msg_deallocate((uint8*)MSGpkt); // 接收到的消息处理完后,释放消息所占的存储空间      

 

  MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(GenericApp_TaskID); 

   }  //处理完一个消息后,再从消息队列里接受消息,然后对其进行相应处理,直到所有消息处理完

   return (events^SYS_EVENT_MSG); 

 } 

   

if(events&SEND_DATA_EVENT)//(区分事件 ) 

 { 

   sendTemp();

   sendVdd();

  osal_start_timerEx(GenericApp_TaskID,SEND_DATA_EVENT,5000); 

   //定时器,三个参数:

 //一参:表定时事件到后,那个任务对其作出响应  

  //二参:表时间达到后,什么事件发生,该事件的处理函数中实现数据的发送(用户应用)。  

  //三参:定时的时间数量,单位毫秒。  

  return (events^SEND_DATA_EVENT);//清除事件标志(该事件已被处理)  

 } 

 return 0; 

//温度检测函数

void sendTemp()

{

 RFTX rftx;

 uint16 tempvalue ;

 uint16 nwk;

 tempvalue = readTemp();//读取温度数据

 rftx.BUF.value[0] = 'W';//表示温度数据

 rftx.BUF.value[1] = tempvalue /10+'0';

 rftx.BUF.value[2] = tempvalue %10+'0';//将温度数据转换为ASCII码

 rftx.BUF.value[3] = '*';

 

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

 

 rftx.BUF.tail = '&';//填充命令尾

 afAddrType_t my_DstAddr;

 my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;//使用单播格式

  my_DstAddr.endPoint=GENERICAPP_ENDPOINT;//目的端口号

 my_DstAddr.addr.shortAddr=0x0000;//协调器网络地址为0x0000

 AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,

                 GENERICAPP_CLUSTERID,//簇号

                 18,                 //发送的数据长度

                 (uint8 *)&rftx,     //发送数据缓冲区

                 &GenericApp_TransID,  //发送序列号

                 AF_DISCV_ROUTE,

                 AF_DEFAULT_RADIUS);//调用数据发送函数AF_DataRequest()进行数据发送

}

 

//电压检测函数

void sendVdd()

{

 RFTX rftx;

 uint16 vddvalue ;

 uint16 nwk;

 

 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';

 

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

 

 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 To_string(uint8 *dest,char * src,uint8length)

{

   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');

    }

}

 

 

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

   ADCCON3=tmpADCCON3;

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;

   

   ADCIF=0;

   ADCCON3=(ADC_REF_115V|ADC_DEC_064|ADC_CHN_VDD3 );

   while(!ADCIF);

   value=ADCH;

   ADCCON3=tmpADCCON3;

   return (value);

}

 

 

 

// Sensor.h

#ifndef SENSOR_H

#define SENSOR_H

#include <hal_types.h>

 

extern int8 readTemp(void);

extern unsigned int getVddvalue(void);

 

typedef struct  {

 char  Head;//命令头

 char value[2];

 char Tail;//命令尾

}BUFer;

typedef struct {

 BUFer BUF;

}TEMPERATURE;

#endif

 

 

 

 

 

// OSAL_GenericApp.c

#include "ZComDef.h"

#include "hal_drivers.h"

#include "OSAL.h"

#include "OSAL_Tasks.h"

 

#if defined ( MT_TASK )

 #include "MT.h"

 #include "MT_TASK.h"

#endif

 

#include "nwk.h"

#include "APS.h"

#include "ZDApp.h"

#if defined ( ZIGBEE_FREQ_AGILITY ) ||defined ( ZIGBEE_PANID_CONFLICT )

 #include "ZDNwkMgr.h"

#endif

#if defined ( ZIGBEE_FRAGMENTATION )

 #include "aps_frag.h"

#endif

#include "Coordinator.h"

// The order in this table must beidentical to the task initialization calls below in osalInitTask.

const pTaskEventHandlerFn tasksArr[] = {

 macEventLoop,

 nwk_event_loop,

 Hal_ProcessEvent,

#if defined( MT_TASK )

 MT_ProcessEvent,

#endif

 APS_event_loop,

#if defined ( ZIGBEE_FRAGMENTATION )

 APSF_ProcessEvent,

#endif

 ZDApp_event_loop,

#if defined ( ZIGBEE_FREQ_AGILITY ) ||defined ( ZIGBEE_PANID_CONFLICT )

 ZDNwkMgr_event_loop,

#endif

 GenericApp_ProcessEvent//任务的事件处理函数

};

 

const uint8 tasksCnt = sizeof( tasksArr ) /sizeof( tasksArr[0] );//定义变量保存任务总个数

uint16 *tasksEvents;//定义变量指向事件表首地址

 

void osalInitTasks( void )

{

 uint8 taskID = 0;

 

 tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);

 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

 

 macTaskInit( taskID++ );

 nwk_init( taskID++ );

 Hal_Init( taskID++ );

#if defined( MT_TASK )

 MT_TaskInit( taskID++ );

#endif

 APS_Init( taskID++ );

#if defined ( ZIGBEE_FRAGMENTATION )

 APSF_Init( taskID++ );

#endif

 ZDApp_Init( taskID++ );

#if defined ( ZIGBEE_FREQ_AGILITY ) ||defined ( ZIGBEE_PANID_CONFLICT )

 ZDNwkMgr_Init( taskID++ );

#endif

 GenericApp_Init( taskID );//任务的初始化函数

}

 

 


 


1 0
原创粉丝点击