|
心理学专家告诉我们,一个贴子不能写得太长,否则会让读者有疲劳感。。。(背景音:哪个专家说的?--自己百度去,肯定不是奥特曼~~~)按照专家的指点,我们把设备“对话”专题,又分了个part 2,就这样,还不知道能不能把这部分说得清楚呢,汗自己一个。。。
在第一部分中,我们只是做了下基础的工作,从“壹”开始,搭建了一个属于自己的工作平台,虽然和主题有点相去甚远,但我认为这对我们后面的理解很有必要,这能帮助我们排除一些非重要因素的干扰,把复杂的事情变得简单--这也是我们网站的宗旨所在!
[注:本文源自www.feibit.com--“飞比”Zigbee论坛,为尊重劳动者成果,如需转载请保留此行]
下面我们要继续第一部分的工作,由于之前我们只是完成了一个设备(Coordinator)的项目搭建,对一个最小化的Zigbee网络,在笔记一中已经做过介绍,至少要一个Coordinator和一个End Device,不过为了方便以后的应用,在这里我们把Coordinator、Router和End Device这三种设备一起添加到项目中。具体的做法如下:
在“project ==> edit configurations”中,分别建立“Coordinator”“Router”及“EndDevice”三种设备的项目设置,注意在"based on configuration"下拉框中要选择之前做过配置的“debug”,然后删除“debug”与“release”。
同时,有几个地方是“Router”及“EndDevice”与“Coordinator”设置有所差异,我们必须要按照“GenericApp”的设置手动修改的
(1)C/C++ compiler ==> preprocessor ==> defined symbols
(2)C/C++ compiler ==>Extra Options
(3)linker ==>Extra Options
这三点对我们理解到整个项目的结构也是非常有帮助的。因为这样我们就知道了,在workspace中选择不同的设备时,到底有哪些具体的不同。
至此,我们就有了具有三种设备的一个基础项目,终于可以开始让机器“说话”啦。。。是不是“铺垫”铺得太长了,不知道还有没有人有耐心看到这里,对我的写作思路有异议的同学,欢迎批评啊~~~
-- 2010.5.9 by outman from Feibit
言归正传,“说话”首先要明确要跟谁说?是对某个人,一组人,所有人,还是自言自语?在Zigbee协议中,有五种类型的地址:
AddrNotPresent = 0,
AddrGroup = 1,
Addr16Bit = 2,
Addr64Bit = 3,
AddrBroadcast = 15
其中,64位的地址是一个“全地址”,就像你的手机在国外打要拨008613XXXXXXXXX,此地址全球唯一,64位的地址理论上可以支持2^64=1.8*10^19个设备,8个0是一个亿,那就是1800亿亿,天哪,这是多少啊~~~~~
16位地址相当于我们的集团短号了(一个Coordinator下的唯一地址),而当地址类型为Group与Broadcast时,分别对应一组设备和所有设备。
作为第一个“对话”的例子,我们从最简单的广播式开始--老张和老王都在大声讲话,所有人都听得到。然后,在此基础上,再探讨一下如何进行“私聊”。
明确了“跟谁说”和“说什么”的问题之后,从大脑到神经系统再到肌肉组织等等一系列的复杂的协调动作,已经由Zigbee组织给我们规定好,并且由TI公司给我们完成了,虽然很多同学可能对这个更感兴趣,但介于目前的水平,我们还是先来看看“嘴”在哪里,和怎么用吧?
afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,
uint16 cID, uint16 len, uint8 *buf, uint8 *transID,
uint8 options, uint8 radius )
这个就是我们要用的“嘴”--把它研究清楚了,我们就有了学习说话的基础了。
这里面的数据结构有点复杂,不过还是让我们来一条条地逐一研究吧。
在这之前,先说几个在这个复杂的数据表中几个比较重要的概念。
[子问题]10.3 Short address, Profile ID, Endpoint, Cluster ID都代表什么意思?区别在哪里?
要说明这个问题,举个“智能家居”里的“无线开关”的例子,可能会更直观点
在这个例子里,左边是两个开关(可能装在走廊里),两个开关共用一个Zigbee节点“Z1”(相当于开发板上的两个按键,这点应该不难理解吧),他们一起控制右边的三个灯泡(也是接在同一个节点上的--“Z2”)。Z1的key1控制Z2的lamp1,而key2则控制Z2的lamp2与lamp3。
OK,回到这个问题
1. short address,16位的短地址,由Coordinator/Router来分配(注:这里留个伏笔,地址分配的问题后面会专门做个专题来讲)
2. Profile ID, 这个是由Zigbee组织来分配的应用ID号,比如无线开关用0x0001,智能电表用ox0002,万用遥控器用0x0003等等。在这个例子里,这个ID号是专门用来做电灯开关的。为什么要这么做呢?这里就体现了“标准”的意义,不同厂家功能的设备,由于有了这个ID就能互相间使用了,正泰的开关一样可以控制Philips的灯。。。
3. Endpoint,这个名字看起来容易误解,以为是设备的序号了,其实不然。在这个例子中,Z1有key1/key2两个Endpoint,分别做不同的事情。其对应了同一个"application"中的0-240个不同的“子应用”,其中0号endpoint是用"ZDO"预留的,不能占用。
4. Cluster ID,这个怎么叫呢?叫信息簇ID吧。。。我的理解是,“这是个哪类的信息”,发送端和接收端一定要对应,但是具体这个“类”怎么分,是我们可以自己决定的。比如说这个例子,我可以这样定:Cluster ID=1代表开关一次,Cluster ID=2代表连续闪烁。。。或者定义Cluster ID=1代表点对点控制,而Cluster ID=2代表全部控制,等等。。。
-- 2010.5.12 00:24 by outman from Feibit
[子问题]10.4 什么是Beacon?
Beacon我们可以简单地理解为一个“指挥棒”,在有beacon的传输中,发送与接收设备是按照一个固定的节奏来进行数据传输的。
好了,现在我们就把要控制这个“嘴”的所有参数列出来,把最重要的一个个来说。这次就不上图了,换个方式。
注:{}中的数据为本例的“广播”式传输的设置值
/*****************************************************************************/
*dstAddr ........................目标地址
shortAddr ................................... 16位短地址{0xFFFF--代表“广播”}
addrMode .................................... 地址类型,上文已做过阐述{AddrBroadcast}
endPoint ..................................... 目标“EndPoint”序号,其意义见上文{20}
/*****************************************************************************/
*srcEP ...........................源“EndPoint”描述
endPoint .................................... 源“EndPoint”序号{20}
*task_id ..................................... 所要调用的任务ID{BeginApp_TaskID}
*simpleDesc
EndPoint ..................... 源“EndPoint”序号(为什么又有一个?--等搞明白了再补充){20}
AppProfId ................... profile ID号,其意义见上文{0x0F08}
AppDeviceId ............... 16位的设备ID号{0x0001}
AppDevVer ................. 设备版本号{0}
Reserved .................... AppFlags(此上三项,具体用处以后再补充){0}
AppNumInClusters ....... 输入Cluster的总数目,Cluster的意义见上文{1}
*pAppInClusterList ...... 输入Cluster的列表{BeginApp_ClusterList}
AppNumOutClusters ..... 输出Cluster的总数目{1}
*pAppOutClusterList .... 输出Cluster的列表{BeginApp_ClusterList}
latencyReq ................................. Beacon的使用情况,本例中没有用到。{noLatencyReqs}
/*****************************************************************************/
cID ........................................................... 本次要发送的Cluster ID号{1}
len ............................................................ 本次要发送的数据长度{发送字符串长度}
*buf .......................................................... 本次要发送的数据的存放地址{字符串地址}
*transID .................................................... 数据传输“排队”号{0}
options ...................................................... 发送选项,如是否要ACK,加密,是否跳过路由等等
{AF_DISCV_ROUTE}
radius ........................................................ 最大“折射”次数/“多跳”级别{10}
/*****************************************************************************/
由于本例中,每个节点都只对应一个endpoint,所以只要保证设为同一个值,可以去不理会。重点设置红色部分项目。
至此,我们基本认识了这个“嘴”的每一根控制神经,下面就要正式说话了~~~
不记得在OSAL中如何读取按键,如何响应事件的同学请复习下“日记(二)”中的内容,这里只简单地把最重要的代码贴出来。
1. 按键 Hal_key.c HalKeyPoll函数,增加
if (!(P0 & HAL_KEY_SW_1))
{
ksave0 |= HAL_KEY_SW_1;
}
以读取按键IO口状态,判断按键,当然在成熟的产品中需要做一个“消抖”算法
2. 响应按键,发送数据
BeginApp.c 的KEY_CHANGE函数中:
#ifdef IAMZHANG
char say_hello[] = "LAO ZHANG: lao wang, chi le mei?";
#else
char say_hello[] = "LAO WANG: lao zhang, chi le mei?";
#endif
BeginApp_SendP2PMessage(say_hello);
此函数将调用AF_DataRequest,其参数按上述设置即可
3. 接收数据并回复
BeginApp.c 的接受信息函数BeginApp_MessageMSGCB中添加
rec_msg = pkt->cmd.Data;
//reply after 2 seconds
osal_start_timerEx( BeginApp_TaskID,
BEGINAPP_SEND_REPLY_MSG_EVT,
BEGINAPP_SEND_MSG_TIMEOUT );
4. 另外,添加一个LED闪烁的函数BeginApp_BlinkLED与串口发送数据函数UART_Send_String,在发送或接收时进行必要的显示。
此处只进行重点部分的讲解,需要源文件的同学请跟帖,如有必要,则会以附件形式共享出来。
好了,终于舒了一口气,剩下最后一个小问题了~
[子问题]10.5 如何知道当前设备的短地址?它是怎么分配的?
试下在程序的某个位置调用一下NLME_GetShortAddr这个函数,看看不同的设备会返回什么值?这个就是为节点分配的short address,有点像路由器给电脑分配IP的感觉。知道了这个,我们做一个小实验,把前面“老张”和“老王”的聊天变成“私聊”。
其实只需要在上面的设置参数里,改变一下这两个就可以了
shortAddr ................................... {Coordinator:0 /EndDevice:0x796F}
addrMode .................................... {Addr16Bit}
这两个设备地址,我们都只是通过实验的方法找到的,但究竟why?是谁在按什么标准分的?
呃。。。我还不清楚,估计得专门有个专题能讲得清楚了~~~
-- 2010.5.12 by outman from Feibit
附件:老王、老张打招呼例程全部源代码: |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|