基于zigbee光照感应系统之节点单播通信
在上一篇博客已经介绍了如和配置协调器与路由器之间的广播通信,本文将介绍路由器与协调器之间的单播通信。
本项目在路由器节点上外加了一个GL7516光照传感器,在路由器节点上不断采集光照传感器的光照强度,然后路由器将光照传感器的信号通过单播的方式发送给协调器,同时将串口助手上打印出来。
首先,来介绍一下GL7516光照传感器:
光敏电阻式一种半导体材料制成的电阻,其电导率随着光照度的变化而变化。利用这一特性可以制成不同形状和受光面积的光敏电阻。GL7516 就是其中的一种,光越强阻值越小。光敏电阻广泛应用于玩具、灯具、照相机等行业。
通过光敏电阻的电路图我们可以看出,当有光照是光敏电阻的阻值变小,P0.1引脚为高电平;没有光照是光敏电阻的阻值为大P0.1引脚为低电平。
在协议栈里配置光照传感器引脚:
#define LIGHT P0_1 //光敏为P0.1口控制
P0DIR&=~0X02; //配置p0.1为输出口
第二步,配置接收方(协调器)的配置:
在void SampleApp_Init( uint8 task_id )函数配置接收放为点播
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0000;
通信方式位16位单播,目标地址为0x0000(协调器的地址)
第三步,在事件处理函数里uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )启动定时器,我们需要自动不断采集P0.1引脚的电平:
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if (
// (SampleApp_NwkState == DEV_ZB_COORD)||
(SampleApp_NwkState == DEV_ROUTER)
// || (SampleApp_NwkState == DEV_END_DEVICE)
)
{
//LS164_BYTE(8);//数码管显示0-9
// Start sending the periodic message in a regular interval.
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
//路由器双闪五次
HalLedBlink(0x03,5,50,1000);
HalUARTWrite(0,"I am RouterEB\n",sizeof("I am RouterEB\n"));
}
else
{
// Device is no longer in the network
}
break;
第四步,因为定时器函数是指向的是SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,然后我在SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件里定义了一个路由器发送函数: SampleApp_SendRouterMessage()通过定时器指向一个事件而在一个事件里定义一个发送函数;通过这个简单的步骤就可以使发送函数不断执行也就是 SampleApp_SendRouterMessage()函数
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
//SampleApp_SendPeriodicMessage();
SampleApp_SendRouterMessage();
// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
// Discard unknown events
return 0;
}
第五步,在发送函数SampleApp_SendRouterMessage()里
void SampleApp_SendRouterMessage(void)
{
uint8 islight[1];
if(P0_1==1)//强光
osal_memcpy(islight,"1",1);
else //弱光
osal_memcpy(islight,"0",1);
if( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
1,
islight,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS )==afStatus_SUCCESS)
{
HalUARTWrite(0,"send light",10);
HalUARTWrite(0,"\n",1);
}
else{
}
定义一个8位的数组uint8 islight[1],通过if语句判断P0.1引脚是否为1,如果为1的话 通过osal_memcpy函数,将字符1赋值给数组islight[1];然后通过 AF_DataRequest函数通过单播的方式将islight发送出去
if( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
1,
islight,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS )==afStatus_SUCCESS)
{
HalUARTWrite(0,"send light",10);
HalUARTWrite(0,"\n",1);
}
else{
}
第六步,协调器接收路由器的数据:
在SampleApp_MessageMSGCB函数
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
uint8 islight[8];
switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
if(osal_memcmp(pkt->cmd.Data,"1",1)){//强光
HalLedSet (0x03, HAL_LED_MODE_ON);
osal_memcpy(islight,"light",sizeof("light"));
HalUARTWrite(0,"light",5);
HalUARTWrite(0,"\n",1);
}
else{ //弱光
HalLedSet (0x03, HAL_LED_MODE_OFF);
osal_memcpy(islight,"dark",sizeof("dark"));
HalUARTWrite(0,"dark",4);
HalUARTWrite(0,"\n",1);
}
HalUARTWrite(0,islight,sizeof(islight));
break;
协调器接收数据代码比较简单我就不在多讲了
通过以上几步就可以实现路由器不断采集光照传感器的信号,通过单播的方式发送给协调器。