目录
在开发ZigBee无线传感器网络过程中,需解决以下几个问题:
网络拓扑结构
传感器数据采集
网络节点能量供应问题
数据传输距离
设计原理图如下:
协调器编程:
//Coordinator.h
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;
该联合体包括一个数组databuf和一个结构体BUF
//Coordinator.c
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 AF_INCOMING_MSG_CMD:
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;
}
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
RFTX rftx;
unsigned char changeline[2]={0x0A , 0x0D}; //定义温度的位数字节,回车换行符的ASCII码
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;
}
}
对收到的消息进行处理和发送到串口
终端节点和路由器编程:
//Sensor.c
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=ADCCON3;
ADCIF=0;
ADCCON3=(ADC_REF_115V | ADC_DEC_064 | ADC_CHN_VDD3);
while(!ADCIF);
value=ADCH;
ADCCON3=tmpADCCON3;
return (value);
}
分别是温度检测函数和电压检测函数,使用CC2530单片机内部自带的温度传感器进行温度检测,内部ADC对电压进行检测,VDD/3作为一个ADC输入通道,对通道进行检测
//Enddevice.c
void sendTemp( void )
{
//unsigned char theMessageData[10] = "EndDevice";
uint16 tempvalue;
uint16 nwk;
RFTX rftx;
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] = '*';
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; //协调器网络地址
AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
18,
(uint8 *)&rftx,
&GenericApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) ;
}
void sendVdd( void )
{
uint16 vddvalue;
uint16 nwk;
RFTX rftx;
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 ) ;
}
对于温度检测函数,调用readTem()函数,读取温度传感器数据,将网络地址,父节点网络地址以及数据头和数据尾信息填充到rftx相应的数据域,最后调用数据发送函数AF_DataRequest();对于电压检测函数,调用getVddvalue()函数,读取电压数据,将网络地址,父节点网络地址以及数据头和数据尾信息填充到rftx相应的数据域。
测试如下: