// Do more configuration if necessary and then restart device with auto-start bit set
// write endpoint to simple desc...dont pass it in start req..then reset
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
如果按下S1(UP),那么作为协调器启动。
if ( keys & HAL_KEY_SW_2 )
{
if ( myAppState == APP_INIT )
{
// In the init state, keys are used to indicate the logical mode.
// Key 2 starts device as a router
zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
{
logicalType = ZG_DEVICETYPE_ROUTER;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
}
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
如果按下S2(RIGHT),设备作为路由器启动。
这里由于是第一个启动的设备,所以作为协调器启动,就按下UP,此时灯会有状态变化,最终结果是:LED2常亮,标示建立网络成功。如果您还有另外的灯设备就可以按下RIGHT让他们都作为路由器启动,由于本人这里只有两个节点,所以就只能有个协调器。
现在就来启动开关设备的电源,同样LED2会闪烁让您选择设备,但是在ZIGBEE中除了协调器和路由器就剩下终端设备了,所以开关就只能作为终端被启动,但是也需要通过按键来控制,从程序中可以看出:
if ( keys & HAL_KEY_SW_1 )
{
if ( myAppState == APP_INIT )
{
// In the init state, keys are used to indicate the logical mode.
// The Switch device is always an end-device
logicalType = ZG_DEVICETYPE_ENDDEVICE;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
// Do more configuration if necessary and then restart device with auto-start bit set
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
else
{
// Initiate a binding with null destination
zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL);
}
}
if ( keys & HAL_KEY_SW_2 )
{
if ( myAppState == APP_INIT )
{
// In the init state, keys are used to indicate the logical mode.
// The Switch device is always an end-device
logicalType = ZG_DEVICETYPE_ENDDEVICE;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
else
{
// Send the command to toggle light
zb_SendDataRequest( 0xFFFE, TOGGLE_LIGHT_CMD_ID, 0,
(uint8 *)NULL, myAppSeqNumber, 0, 0 );
}
}
无论是按下S1还是S2(UP或者RIGHT),开关设备均作为终端设备启动。
启动之后呢,灯的状态同样会发生一些变化,最终结果是:LED2快速闪烁,表明此时开关已经成功加入刚才灯设备建立的那个网络了。
那么接下来就要看这个例子的核心部分----------绑定!
首先按下灯设备(这里为协调器,如果有路由器也可以)的UP,那么程序中调用了:
zb_AllowBind( myAllowBindTimeout );
函数,允许绑定,这个允许的时间据说只有10S,当然这个时间是可以调整的,因为这里的参数为:static uint8 myAllowBindTimeout = 10;至于这个时间怎么计算的就需要到某个函数zb_AllowBind里去分析了。zb_AllowBind规定这个参数为1~64,如果为0,表示为假,就是不允许绑定的意思。如果大于64的话,就一直为真,就是一直都允许绑定。好像似乎是这个意思。至于这个10S是怎么制定的呢,在这个函数内部调用了:
osal_start_timerEx(sapi_TaskID, ZB_ALLOW_BIND_TIMER, timeout*1000);
因为osal_start_timerEx定时函数最小单位为mS,所以*1000就表示S了。
而在SAPI_ProcessEvent事件处理函数中ZB_ALLOW_BIND_TIMER事件处理如下:
if ( events & ZB_ALLOW_BIND_TIMER )
{
afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);
return (events ^ ZB_ALLOW_BIND_TIMER);
}
也就是定时取消绑定状态!!!
如果有人看着这些看不明白,那就把这个例子多看几遍,多跑几遍。一般如果您每天花费4个小时看这个例子,那么只需要一周事件,我想到时比我还精通明白的!
所以在10S之内,开关必须发起绑定,此时同样按下开关设备的UP,那么开关设备就调用了函数:zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL);发送一个绑定请求去寻求绑定设备。
一个设备允许绑定,一个设备发起绑定请求,两个是您情我愿的,所以就一拍即合,相当的登对!当然没有这么简单的哈,就如同两个人谈恋爱,至少也需要是一男一女啊,两个都是男或女那就太不正常了,ZIGBEE是个国际化的标准,当然不能有这种变态行为,所以也需要两个命令的属性是相反的,就例如这里的控制灯开关的命令,对于灯来说这个命令为输入,而对于开关来说这个命令是输出。所以一入一出刚好就登对。呵呵!!
绑定成功的表象是:开关设备的LED1快速闪烁。
void zb_AllowBindConfirm( uint16 source )
{
// Flash LED
HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK );
}
绑定成功了就可以发送灯控制命令了。按下RIGHT,调用了函数:
zb_SendDataRequest( 0xFFFE, TOGGLE_LIGHT_CMD_ID, 0,
(uint8 *)NULL, myAppSeqNumber, 0, 0 );
可以看出发送了一个数据请求,显然是广播发送的,而命令为切换灯状态的TOGGLE_LIGHT_CMD_ID。当灯收到这命令,就有处理函数了:
void zb_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )
{
if (command == TOGGLE_LIGHT_CMD_ID)
{
// Received application command to toggle the LED
HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE);
}
}
所以LED1显示状态发生改变。
此时这个例子已经接近尾声了,因为绑定成功开关能够控制灯了,但是既然可以绑定那么也可以接触绑定的,如果按下开关的DOWN,那么同样调用了发送绑定请求函数:
zb_BindDevice(FALSE, TOGGLE_LIGHT_CMD_ID, NULL);
只是这里第一个参数为FALSE,所以就能解除绑定。如果某个开关被解除了绑定,那么此时就不能控制灯了。
在这个例子最后做个小结------绑定的好处。
绑定了之后,发送数据或者命令,就不需要设备的地址,因为这个命令只能在建立绑定间的设备中传输。------------绝对是我的理解!
还有,一个开关可以绑定多个灯,同样,一个灯可以同时与多个开关发生绑定。这个不代表本人观点,本人强力反对脚踏N只船!!!!!!
现在来简单分析下传感器的例子,由于前面灯的例子说的比较多,这里我就说少点。
中心节点对应SimpleCollectorEB ,传感器节点对应SimpleSensorEB。这里用到了EB,主要是因为DB没有串口硬件,而EB有,这个例子需要用到串口。
传感器的例子效果是:协调器可以收集传感器节点的温度信息并通过串口传输到PC机,如下图所示:
可以看到能够看到节点的温度和电源电压。
具体实现与灯的例子稍区别,但是本质的原理是一样的,先选择设备类型,然后建立绑定,最后收集信息。这里建立绑定的区别在于,只要中心节点允许绑定(与前面操作一样),然后传感器节点是自动发送绑定请求的:
osal_start_timerEx( sapi_TaskID, MY_FIND_COLLECTOR_EVT, myBindRetryDelay );
定时去产生发MY_FIND_COLLECTOR_EVT事件:
if ( event & MY_FIND_COLLECTOR_EVT )
{
// Find and bind to a collector device
zb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL );
}
这个事件就是发送绑定请求的。
至于绑定后的现象与前面一样了。
最后通过串口调试工具就能看到前面那个图的效果了!!!!!!!!!!!!!
这里的温度为42,这个肯定不可能的,不然我就被蒸发掉了哈!因为采用的是芯片内部集成的温度传感器,这个传感器做实验还可以,因为可以看见温度的变化,但是其准确性是在不敢恭维。TI也是的,做了温度传感器,还超级不准确,还不如不做,只有还可以降低硬件成本,几乎没有任何使用价值!!!
不知道各位看官看到这里有何感想,我想都会觉得我写的乱七八糟,因为我也是兴之所至,毫无章法的。有任何疑问欢迎来函交流:peterpanjy@163.com。建议有以书面的形式集中提出交流意见、问题等。本人晚上回家与大家一起学习进步!!!
今天完成的比较早,这个要归功于昨天晚上的功劳。不过还是到此结束,我也需要一点私人空间,看会电影!!!!!!!!!!!!!!
文章评论(0条评论)
登录后参与讨论