对应的代码包:https://download.csdn.net/download/mchen_6431/11536608
硬件采用:深联智达公司产品: https://tb.am/ronna
ZigBee技术建立在IEEE802.15.4标准之上,ZigBee联盟对网络层协议和API进行了标准化。ZigBee协议栈架构基于OSI七层模型,但只定义了与其应用息息相关的几个层,如下图所示。IEEE 802.15.4标准定义了物理层和MAC子层,ZigBee标准在这个基础之上扩展了网络层(network layer,NWK)和应用层框架,其中包括应用支持子层(application support sub-layer,APS)、ZigBee设备对象(ZigBee device object,ZDO)以及设备商自定义的应用组件。
ZigBee协议栈模型图
ZigBee标准确定了三种设备:ZigBee协调器、ZigBee路由器和ZigBee终端设备。每个网络都必须包括一台ZigBee协调器。协调器的主要功能是为建立和启动网络这一过程设置参数,其中包括选择一个射频信道、唯一的网络标识符以及一系列操作参数。ZigBee路由器作为远程设备之间的中继器来进行通信,能够用来拓展网络的范围。ZigBee终端设备不参与路由选择。
ZigBee所制定的网络层主要负责网络拓扑得搭建和维护,以及设备寻址、路由等,属于通用的网络层功能范畴,应用层负责业务数据流的汇聚、设备发现、服务发现、安全与鉴权等。
其中temp_humid.c temp_humid.h为温湿度传感器的驱动文件。
SendTest.c中为温湿度采集程序:
当终端节点加入到网络时,启动温度采集事件
ENSOR_TEMPERATURE_EVT:
case ZDO_STATE_CHANGE:
SendTest_NwkState = (devStates_t)(MSGpkt->hdr.status);
if (SendTest_NwkState == DEV_END_DEVICE) ////只在设备为终端节点时,才发送数据
{
// Start sending "the" message in a regular interval.
osal_set_event(SendTest_TaskID, SENSOR_TEMPERATURE_EVT);//启动温度采集
}
break;
下次系统轮询时,将调用ENSOR_TEMPERATURE_EVT事件,并处理该事件:
if ( events & SENSOR_TEMPERATURE_EVT )
{
Temperature_Measure();
osal_start_timerEx( SendTest_TaskID, SENSOR_HUMIDITY_EVT, MEASURE_PERIOD );//启动湿度采集
return ( events ^ SENSOR_TEMPERATURE_EVT );
}
处理该事件中,首先调用Temperature_Measure();采集并发送数据;另外又启动了SENSOR_HUMIDITY_EVT事件进行湿度采集;
下次系统轮询时,将调用SENSOR_HUMIDITY_EVT事件,并处理该事件
if ( events & SENSOR_HUMIDITY_EVT )
{
Humidity_Measure();
osal_start_timerEx( SendTest_TaskID, SENSOR_TEMPERATURE_EVT, MEASURE_PERIOD );//启动温度采集
return ( events ^ SENSOR_HUMIDITY_EVT );
}
处理该事件中,首先调用Humidity_Measure ();采集并发送数据;另外又启动了SENSOR_TEMPERATURE_EVT事件进行温度采集;
从上面的表述中可以得知,系统对温湿度分别采样,调用,其中采样时间为MEASURE_PERIOD,3秒钟一次。
在IAR环境中,workspace里面有三种类型的设备设置,请参考:
如图显示的EndDevice设备,这事编译的程序为enddevice节点使用,在workspace里面还可以选择Coordinator,该程序为协调器程序
还可以选择Router,该程序为路由节点程序
一般来说,路由节点只是转发数据,不涉及用户操作。在项目中,可以不对该部分程序进行更改。
协调器在收到终端发送过来的数据时,进行温湿度数据转换,转换程序如下:
static void SendTest_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case SENDTEST_CLUSTERID:
// "the" message
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
#elif defined( WIN32 )
WPRINTSTR( pkt->cmd.Data );
#endif
if(pkt->cmd.Data[0]==0x01) {
result=(float)(((pkt->cmd.Data[1]<<8)+(pkt->cmd.Data[2]))*0.01-39.67);
sprintf(temperature, (char *)"%fC", result);}
else if(pkt->cmd.Data[0]==0x02){
result=-0.00000028*((pkt->cmd.Data[1]<<8)+(pkt->cmd.Data[2]))*((pkt->cmd.Data[1]<<8)+(pkt->cmd.Data[2]))+0.0405*((pkt->cmd.Data[1]<<8)+(pkt->cmd.Data[2]))-4.0;
sprintf(temperature, (char *)"%fH", result);}
HalUARTWrite( HAL_UART_PORT_0,(unsigned char*)temperature, (byte)osal_strlen( temperature ) + 1);//将接收到的数打印到串口上
break;
}
}
温度公式:
t是上报的温度数据值,两个字节,高位在前,低位在后
T=-39.67+0.01t,把1A DE带入该公式可得到当前温度值。
湿度公式:
h是上报的湿度数据值,两个字节,高位在前,低位在后
H=-0.00000028hh+0.0405h-4.0,把05 EE带入该公式可得到当前湿度值。