第一篇:Zigbee心得体会
心得体会
本次实训之前,我就上网搜索了Zigbee的概念和相关信息。通过这次为期五周的无线通信技术综合训练,我对Zigbee无线通信技术,以及单片机CC2530开发板的硬件结构和功能有了初步的了解和认识。
实训的第一周,我们学习利用IAR Embedded Wordbench软件,建立工程,编写、调试和下载程序,通过CC2530开发板的现象来分析程序的功能。亲眼目睹了软件驱动硬件工作之后,我开始对这次实训产生了浓厚兴趣。在熟悉了软件和硬件的基本操作后,我们开始编写和调试相对复杂的程序。这个编写和调试的过程对我来说是个很大的挑战,因为我的C51基础很薄弱,所以很多看似简单的程序,我都要去查资料或者请教老师同学。最后一周的综合实验,是小组合作共同完成的。我体会到了Zigbee技术的功能强大,也体会到了团队合作的快乐和价值。
现实和理想总是有差距的,或多或少都会出现一些问题。对于通信方面的实训来说更是如此。在这次实训过程中,我遇到了各种问题:某句程序不理解,程序调试不成功,节点指示灯不闪烁,液晶屏显示乱码,实验现象和预期要求不符等。通过查阅相关资料、小组成员探讨和请教老师等途径,这些问题得到了及时有效的解决。解决问题的过程不是一帆风顺的,是要付出汗水和努力的,但这个过程很值得。
通过这次实训,我认识和了解了热门的Zigbee技术,提高了C51的程序编写和调试能力。更重要的是,这次实训提高了我们通信专业所必需的实践能力和职场所需的团队合作能力,培养了我们认真严谨的科学态度。这些东西将让我们终身受益!
第二篇:zigbee学习自我总结!!!!!
1.Zigbee网络节点类型
Zigbee网络有三类节点类型:即协调器Coordinator、路由器Router和终端设备EndDevice,其中协调器和路由器均为全功能设备,而终端设备选用精简功能设备。
2.Zigbee协议栈各层主要功能模块
3.Zigbee网络节点地址
Zigbee网络协议的每一个节点皆有两个地址:64位的IEEE MAC地址及16位网络地址.EUI-64(64-bit extended unique identifier)
1)64-bit地址,又称为MAC地址或IEEE地址。
每个ZigBee节点都应该有全球唯一的64位IEEE地址。这个地址需要向IEEE组织申请才能使用。通信时,将待发送的数据包的目的地址设为此64位IEEE地址,从而实现数据包的正确投递。
2)16-bit地址,即网络地址,或称为短地址。当一个ZigBee网络形成后,ZigBee网络内的每个节点,都会分配到一个16位的网络地址。通信时,将待发送的数据包的目的地址设为此16位网络地址。
4.Zigbee协议术语
配置文件(profile):Zigbee协议的配置文件是对逻辑组件及其相关接口的描述,是面向某个应用类别的公约、准则.通常没有程序代码与配置文件相关联.
属性(attribute):设备之间通信的每一种数据像开关的状态或温度计值等皆可称为属性.每个属性可得到唯一的ID值.
簇(cluster):多个属性的汇集形成了簇,每个簇也拥有一个唯一的ID。虽然个体之间传输的通常是属性信息,但所谓的逻辑组件的接口指的却是簇一级的操作,而非属性一级.
终端(endpoint):每个支持一个或多个簇的代码功能块称为终端。不同的设备通过它们的终端及所支持的簇来进行通信。
PAN IDs:PAN IDs是用来在逻辑上分离在同一领域内的多个节点组。这样不同组之间节点通信就不会干扰,且可以在同一通道channel上(zigbee2007不行,因为它通信时可以改变频率的)Pan id是16位,范围是0x0000~03fff。当建立或加入网络时没有指定PAN ID的话,就会根据default PAN ID确定。它是个常量。
Extended PAN ID:zigbee 增加了一个8字节的扩展PAN ID,便于提供服务和PAN ID冲突检测。5.Zigbee协议结构
●物理层(PHY)物理层定义了物理无线信道和MAC子层之间的接口,提供物理层数据服务和 物理层管理服务。物理层内容: 1)ZigBee的激活;2)当前信道的能量检测;3)接收链路服务质量信息;4)ZigBee信道接入方式;5)信道频率选择;6)数据传输和接收。●介质接入控制子层(MAC)MAC层负责处理所有的物理无线信道访问,并产生网络信号、同步信号;支持PAN连接和分离,提供两个对等MAC实体之间可靠的链路。
MAC层功能:
1)网络协调器产生信标; 2)与信标同步;
3)支持PAN(个域网)链路的建立和断开; 4)为设备的安全性提供支持;
5)信道接入方式采用免冲突载波检测多址接入(CSMA-CA)机制; 6)处理和维护保护时隙(GTS)机制;
7)在两个对等的M AC实体之间提供一个可靠的通信链路。●网络层(NWK)
ZigBee协议栈的核心部分在网络层。网络层主要实现节点加入或离开网络、接收或抛弃其他节点、路由查找及传送数据等功能。网络层功能: 1)网络发现;2)网络形成;3)允许设备连接;4)路由器初始化;5)设备同网络 连接;6)直接将设备同网络连接;7)断开网络连接;8)重新复位设备;9)接收机 同步;10)信息库维护。●应用层(APL)
ZigBee应用层框架包括应用支持层(APS)、ZigBee设备对象(ZDO)和制造商所定义的应用对象。应用支持层的功能包括:维持绑定表、在绑定的设备之间传送消息。
ZigBee设备对象的功能包括:定义设备在网络中的角色(如ZigBee协调器和终端设备),发起和响应绑定请求,在网络设备之间建立安全机制。ZigBee 设备对象还负责发现网络中的设备,并且决定向他们提供何种应用服务。ZigBee应用层除了提供一些必要函数以及为网络层提供合适的服务接口外,一个重要的功能是应用者可在这层定义自己的应用对象。●应用程序框架(AF)
运行在ZigBee协议栈上的应用程序实际上就是厂商自定义的应用对象,并且遵循规范(profile)运行在端点1---240上。在ZigBee应用中,提供2种标准服务类型:键值对(KVP)或报文(MSG)。●Zigbee设备对象(ZDO)
远程设备通过ZDO请求描述符信息,接收到这些请求时,ZDO会调用配置对象获取相应描述符值。另外,ZDO提供绑定服务。
6.Z-Stack软件构架
Z-Stack由main()函数开始执行,main()函数共做了2件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统,如下图所示:
7.Z-Stack 系统运行流程图
8.Z-Stack在项目中的目录结构
(1)App:应用层目录,这个目录下的文件就是创建一个新项目时自己要添加的文件,(2)HAL:硬件层目录,Common目录下的文件是公用文件,基本上与硬件无关,其中hal_assert.c是断言文件,用于调用,hal_drivers.c是驱动文件,抽象出与硬件无关的驱动函数,包含有与硬件相关的配置和驱动及操作函数。Include目录下主要包含各个硬件模块的头文件,而Target目录下的文件是跟硬件平台相关的,可能看到有两个平台,分别是Cc2430DB平台和一个CC2430EB平台。后面的DB和EB表示的是TI公司开发板的型号,其实还有一种类型是BB的,BB: Battery Board DB: Development Board EB: Evaluation Board 分别对应TI公司开发的三种板型,其功能按上顺序依次变强。可以参看“Z-Stack User's Guide for CC2430”的图片,可以获得更直观的认识。
(3)MAC:MAC层目录,High Level和Low Level两个目录表示MAC层分为了高层和底层两层,Include目录下则包含了MAC层的参数配置文件及基MAC的LIB库函数接口文件,这里的MAC层的协议是不开源的,以库的形式给出
(4)MT:监制调试层目录,该目录下的文件主要用于调试目的,即实现通过串口调试各层,与各层进行直接交互。
(5)NWK:网络层目录,含有网络层配置参数文件及网络层库的函数接口文件,及APS层库的函数接口
(6)OSAL:协议栈的操作系统抽象层目录
(7)Profile:AF层目录,Application Farmework 应用框架,包含AF层处理函数接口文件。
(8)Security:安全层目录,包含安全层处理函数接口文件
(9)Services:ZigBee和802.15.4设备地址处理函数目录,包括地址模式的定义及地址处理函数
(10)Tools:工作配置目录,包括空间划分及Z-Stack相关配置信息
(11)ZDO:指ZigBee设备对象,可认为是一种公共的功能集,文件用户用自定义的对象调用APS子层的服务和NWK层的服务
(12)ZMAC:其中Zmac.c是Z-StackMAC导出层接口文件,zmac_cb.c是ZMAC需要调用的网络层函数
(13)Zmain:Zmain.c主要包含了整个项目的入口函数main(),在OnBoard.c包含硬件开始平台类外设进行控制的接口函数
(14)Output:输出文件目录,这个是EW8051 IDE自动生成的
9.Z-stack 中实现自己的任务
在Zstack(TI的Zigbee协议栈)中,对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括: ①用于初始化的函数
如:SampleApp_Init(),这个函数是在osalInitTasks()这个osal(Zstack中自带的小操作系统)中去调用的,其目的就是把一些用户自己写的任务中的一些变量,网络模式,网络终端类型等进行初始化;②用于引起该任务状态变化的事件发生后所需要执行的事件处理函数
如:SampleApp_ProcessEvent(),这个函数是首先const pTaskEventHandlerFn tasksArr[ ]中进行设置(绑定),然后在osalInitTasks()中如果发生事件进行调用绑定的事件处理函数。
1)用户自己设计的任务代码在Zstack中的调用过程
main()执行(在Zmain目录中ZMain.c)-osal_init_system()(在OSAL目录中的OSAL.c 中)-调用osalInitTasks()(在APP目录中的OSAL_SerialApp.c)-调用SerialApp_Init(),(在APP目录中的SerialApp.c中)。
在osalInitTasks()中实现了多个任务初始化的设置,其中macTaskInit(taskID++)到ZDApp_Init(taskID++)的几行代码表示对于几个系统运行初始化任务的调用,而用户自己实现的SampleApp_Init()在最后,这里taskID随着任务的增加也随之递增.所以用户自己实现的任务的初始化操作应该在osalInitTasks()中增加。(在APP目录中的OSAL_SerialApp.c中增加)。2)任务处理调用的重要数据结构
在Zstack里,对于同一个任务可能有多种事件发生,那么需要执行不同的事件处理,为了方便,对于每个任务的事件处理函数都统一在一个事件处理函数中实现,然后根据任务的ID号(task_id)和该任务的具体事件(events)调用某个任务的事件处理函数,进入了该任务的事件处理函数之后,再根据 events 再来判别是该任务的哪一种事件发生,进而执行相应的事件处理。
pTaskEventHandlerFn 是一个指向函数(事件处理函数)的指针,这里实现的每一个数组元素各对应于一个任务的事件处理函数,比如SampleApp_ProcessEvent对于用户自行实现的事件处理函数 uint16 SampleApp_ProcessEvent(uint8 task_id,uint16 events),所以这里如果我们实现了一个任务,还需要把实现的该任务的事件处理函数在这里添加。
注意,tasksEvents(在APP目录中的OSAL_SerialApp.c的osalInitTasks(void)函数中)和tasksArr[](在APP中的OSAL_SerialApp.c中)里的顺序是一一对应的,tasksArr[]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件。
3)对于不同事件发生后的任务处理函数的调用
osal_start_system()很重要,决定了当某个任务的事件发生后调用对应的事件处理函数(在Zmain目录中ZMain.c)。
10.Z-stack 添加一个新的任务
在osalInitTasks()和tasksArr[]添加相应的项就可以了。osalInitTasks()为初始化系统的任务,tasksArr[ ]为任务处理事件矩阵。在 osalInitTasks()和 tasksArr[]添加相应的项就可以。
1)修改 osalInitTasks()void osalInitTasks(void){ ……
OuhsApp_Init(taskID++);PhotoApp_Init(taskID);} 2)修改 tasksArr[] const pTaskEventHandlerFn tasksArr[] = { ……
OuhsApp_ProcessEvent PhotoApp_ProcessEvent };3)添加_Init()和_ProcessEvent()void PhotoApp_Init(uint8 task_id){ PhotoApp_TaskID=task_id;PhotoInit();RegisterForPhoto(PhotoApp_TaskID);} uint16 PhotoApp_ProcessEvent(uint8 task_id uint16 events){ afIncomingMSGPacket_t *MSGpkt;if(events &SYS_EVENT_MSG){ MSGpkt =(afIncomingMSGPacket_t *)osal_msg_receive(PhotoApp_TaskID);while(MSGpkt){ switch(MSGpkt->hdr.event){ case PHOTO_CHANGE: HalLedblink(HAL_LED_1 3 30 300);//P0IE=1;break;} // Release the memory osal_msg_deallocate((uint8 *)MSGpkt);// Next0 if not set */
uint16 clusterId;
/* Message's cluster ID */
afAddrType_t srcAddr;
/* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,it's an InterPAN message */
uint16 macDestAddr;
/* MAC header destination short address */
uint8 endPoint;
/* destination endpoint */
uint8 wasBroadcast;
/* TRUE if network destination was a broadcast address */
uint8 LinkQuality;
/* The link quality of the received data frame */
uint8 correlation;
/* The raw correlation value of the received data frame */
int8 rssi;
/* The received RF power in units dBm */
uint8 SecurityUse;
/* deprecated */
uint32 timestamp;
/* receipt timestamp from MAC */
afMSGCommandFormat_t cmd;/* Application Data */ } afIncomingMSGPacket_t;typedef struct {uint8 event;
uint8 status;} osal_event_hdr_t;typedef struct {
byte
TransSeqNumber;
uint16 DataLength;
// Number of bytes in TransData
byte *Data;} afMSGCommandFormat_t;
第三篇:Zigbee读书日记(七)
原文链接:
Zigbee读书日记
(七)--基于Contiki的开源Zigbee-freakz研究(前言)
此系列笔记已经很长时间没更新了,主要是在忙着2530开发板的事情,项目规划、例程、文档甚至元件采购,实在有太多事情要忙了。还好,不是一个人在战斗~~这两天因为有些工作要等手样出来才能继续,所以就空出一点时间,想把开源Zigbee的项目先启动起来。
本来是没时间写这个贴的,但是想把自己最近做的事情跟大家做个交代,同时也希望能寻找些有共同爱好的朋友能一起来做这个事情。废话不说了,先说说我的想法,我想论坛会按照开源操作系统+开源Zigbee,然后扩展到TCP/IP这个方向去走。之前选择的平台是msstatePAN,但是最近一段时间的了解,虽然msstatePAN可以直接支持CC2430,用起来相对会容易些。但毕竟这个协议还很初级,很多功能没有完成。程序写得也不是太规范,而且作者最近几年都没有更新了。而freakz这个协议,用的是开源的contiki操作系统,其扩展性会好很多,因为在contiki基础上,已经有很多不错的应用了,甚至是开源的IPV6。而且针对Zigbee来说,其协议虽然离产品化还有距离,但是要完整很多,唯一的缺点就是硬件还不支持TI系列。
我们能不能自己去做这部分工作呢?我相信有TI详细的技术资料支持跟几个开源的MAC层代码,应该是可以的。这就是我接下来一段时间准备要做的事情,希望能在2530开发板的手样出来(大概到下个周末)前,能做出个大概,如果有网友有兴趣,非常渴望您的加入!
第四篇:zigbee入网退网机制分析
Zstack入网退网代码分析
网络初始化和路由:
网络初始化:
协调器(Coordinator)首先在某个频段发起一个网络,网络频段的定义放在DEFAULT_CHANLIST配置文件里。如果ZDAPP_CONFIG_PANID定义的PAN ID是0xFFFF(代表所有的PAN ID),则协调器根据它的IEEE地址随机确定一个PAN ID。否则,根据ZDAPP_CONFIG_PANID的定义建立PAN ID。当节点为Router或者End Device时,设备将会试图加入DEFAULT_ CHANLIST所指定的工作频段。如果ZDAPP_CONFIG_PANID没有设为0xFFFF,则Router或者End Device会加入ZDAPP_CONFIG_PANID所定义的PAN ID。设备上电之后会自动的形成或加入网络,如果想设备上电之后不马上加入网络或者在加入网络之前先处理其他事件,可以通过定义HOLD_AUTO_START来实现。通过调用ZDOInitDevice(int startdelay)来手动定义多久时间(startdelay)之后开始加入网络。
设备如果成功的加入网络,会将网络信息存储在非易失性存储器(NV Flash)里,掉电后仍然保存,这样当再次上电后,设备会自动读取网络信息,这样设备对网络就有一定的记忆功能。
如果需要使用NV Flash的设置,可以通过定义NV_RESTORE宏和关闭SW_BYPASS_NV来使用。
有关网络参数的设置大多保存在协议栈Tools文件夹的f8wConfig.cfg里。路由:
Z-Stack采用无线自组网按需平面距离矢量路由协议AODV,建立一个Hoc网络,支持移动节点,链接失败和数据丢失,能够自组织和自修复。当一个Router接受到一个信息包之后,NMK层将会进行以下的工作:首先确认目的地,如果目的地就是这个Router的邻居,信息包将会直接传输给目的设备;否则,Router将会确认和目的地址相应的路由表条目,如果对于目的地址能找到有效的路由表条目,信息包将会被传递到该条目中所存储的下一个hop地址;如果找不到有效的路由表条目,路由探测功能将会被启动,信息包将会被缓存直到发现一个新的路由信息。
ZigBee End Device不会执行任何路由函数,它只是简单的将信息传送给前面的可以执行路由功能的父设备。因此,如果End Device想发送信息给另外一个End Device,在发送信息之间将会启动路由探测功能,找到相应的父路由节点。初始化流程图:
ZStack代码中的设备初始化流程图如下:
其中根据宏的设置可以达到扩展panID的效果,并且所有设备类型都集中处理。
退网: 协调器和路由器上层使用ZDP_MgmtLeaveReq()进行设备退网申请,会通过ZDO的Mgmt消息处理函数ZDO_ProcessMgmtLeaveReq()来调用NLME_LeaveReq()函数,实现退网申请,主要用来申请给其他设备退网。
当前设备直接使用NLME_LeaveReq()来进行退网申请,并且注意LeaveReq的addr必须为NULL!当前设备申请后,会在网络层发送一个LeaveInd给协调器(路由器),协调器根据LeaveInd执行结果返回LeaveRsp。
因此协调器可以通过ZDO_RegisterZDOCB的函数来注册LeaveInd后处理,比如删除自制表项等等。
寻址:
为了在网络中发送数据到一个设备,应用层一般用AF_DataRequest()函数。typedef enum { afAddrNotPresent = AddrNotPresent, afAddr16Bit = Addr16Bit, afAddr64Bit = Addr64Bit, afAddrGroup = AddrGroup, afAddrBroadcast = AddrBroadcast } afAddrMode_t;
地址模式参数是需要的,因为在ZB中,数据包能被点传输、多点传输或者广播传输。点传输被发送到单个设备,多点传输一定发送到一组设备,广播传输一般被发送到网络中的所有设备。如下是更详细的说明。
点到传输(Unicast):这是标准地址模式,被用于发送一个数据包到网络中单个已知地址的设备。这个addrMode参数被设置为Addr16Bit或者Addr64Bit,目的网络地址在数据包中一同被发送。其中一个是64位IEEE地址(也可以叫MAC地址或扩展地址),一个是16位网络地址(也可以叫逻辑地址或短地址)。64位地址是全球唯一的,作为设备(产品)的终生地址被分配。它通常被开发商或安装的时候被指定。该地址由IEEE分配指定。16位地址在设备加入网络的时候被分配,由这个网络自动分配。该地址只能用与本网络中,标志不同的设备间传递信息。
间接寻址:数据包中的最终目的地址不识别的时候使用。该模式被AddrNotPresent设置,而且目的地址没有被指定。代替目的地址的是:一个存储在发送设备协议栈的“绑定表格”,该表格中有被绑定设备的地址。这个特性被调用是源于绑定。当被发送的信息包下载到协议栈时,从这个绑定表格中寻找使用的目的地址。然后该信息包被有规则的处理为点对点数据包。如果有多个(大于1)目的地址在绑定表格中被发现,那么该数据包将被拷贝成对应的份数分别发送给他们。
广播传输:该模式在应用层想发送一个数据包到所有网络中的所有设备时被使用。该地址模式被AddrBroadcast被设置,目的地址被设置为下列值之一: NWK_BROADCAST_SHORTADDR_DEVALL(0xFFFF)-信息将被发送到网络中的所有设备(包括休眠的设备)。对于休眠的设备,这个信息将被保持在它的父节点,直到该休眠设备获得该信息或者该信息时间溢出(在f8wConfig.cfg 中的NWK_INDIRECT_MSG_TIMEOUT选项)。
NWK_BROADCAST_SHORTADDR_DEVRXON(0xFFFD)–该信息将被发送到网络中有接收器并处于IDLE(RXONWHENIDLE)状态下的所有设备。也就是说,除了休眠模式设备的所有设备。NWK_BROADCAST_SHORTADDR_DEVZCZR(0xFFFC)–该信息被发送到所有路由器(包括协调器)。
组地址:该模式用于应用层想发送一个数据包到一个设备组的时候。该地址模式被afAddrGroup设置这个组标志符。用该特性之前,在网络中,组不得不被定义[看ZStack API文档中的] aps_AddGroup()注意:组能与间接寻址一起结合使用。该目的地址在绑定表格中发现,可以作为点对点或一个组地址。也要注意广播地址可以当作是组被提前设置,一个简单的组寻址的特例。例子代码对于一个设备添加它自己到一个组标志符1: aps_Group_t group;// Assign yourself to group 1 group.ID = 0x0001;group.name[0] = 0;// This could be a human readable string aps_AddGroup(SAMPLEAPP_ENDPOINT, &group);
一个应用可以能想知道它自身和父节点的地址,用下面的函数可以得到设备的地址(被定义在ZStack API文档中):
NLME_GetShortAddr()– 返回该设备的 16 位网络地址 NLME_GetExtAddr()–返回该设备的64 位扩展地址.用下面的函数可以得到该设备的父节点的地址(被定义在ZStack API文档中)。注意该函数在协调器中不被涉及到,但是被设备父节点代替(MAC协调器): NLME_GetCoordShortAddr()– returns this device’s parent’s 16 bit short address.NLME_GetCoordExtAddr()– returns this device’s parent’s 64 bit extended address.
第五篇:Zigbee基础实验(6)—简单通信编程
Zigbee基础实验(6)—简单通信编程
2011-07-25 20:06:19|分类: |字号 订阅
实验中两节点分别充当开关和电灯,通过在开关节点上的操作来控制电灯节点。
源代码: #include
#include “basic_rf.h”
#define RF_CHANNEL25// 信道选择。
// 定义各个参数的值
#define PAN_ID0x2007//网络ID
#define SWITCH_ADDR0x2520//开关节点的地址
#define LIGHT_ADDR0xBEEF//电灯节点的地址
#define APP_PAYLOAD_LENGTH1//负载字节的长度,信息的长度。#define LIGHT_TOGGLE_CMD0//被传送的开关命令。
//节点状态。0为空闲
#define IDLE0
#define SEND_CMD1
// 定义该节点所承担的任务(开关或电灯)
#define NONE0
#define SWITCH1
#define LIGHT2
#define APP_MODES2
static uint8 pTxData[APP_PAYLOAD_LENGTH];//发送数组
static uint8 pRxData[APP_PAYLOAD_LENGTH];//接收数组
static basicRfCfg_t basicRfConfig;
// 模式选择菜单 static menuItem_t pMenuItems[] = {
“Switch”,SWITCH,“Light”,LIGHT
};static menu_t pMenu = {
pMenuItems,N_ITEMS(pMenuItems)
};
static void appLight();//实现电灯功能
static void appSwitch();//实现远程开关功能
static uint8 appSelectMode(void);//功能选择
static void appLight()//实现电灯功能 {
halLcdWriteLine(HAL_LCD_LINE_1, “Light”);
halLcdWriteLine(HAL_LCD_LINE_2, “Ready”);
// 初始化射频模块
basicRfConfig.myAddr = LIGHT_ADDR;//网络地址
if(basicRfInit(&basicRfConfig)==FAILED){
HAL_ASSERT(FALSE);//初始化错误处理
}
basicRfReceiveOn();//打开接收功能。
//死循环
while(TRUE){
while(!basicRfPacketIsReady());
if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)>0){//如果接收到数据
if(pRxData[0] == LIGHT_TOGGLE_CMD){
halLedToggle(1);//开关改变状态
}
}
}
}
static void appSwitch()//实现远程开关 {
halLcdWriteLine(HAL_LCD_LINE_1, “Switch”);//屏幕输出
halLcdWriteLine(HAL_LCD_LINE_2, “Joystick Push”);
halLcdWriteLine(HAL_LCD_LINE_3, “Send Command”);
pTxData[0] = LIGHT_TOGGLE_CMD;//需要发送的数据
// 初始化
basicRfConfig.myAddr = SWITCH_ADDR;
if(basicRfInit(&basicRfConfig)==FAILED){
HAL_ASSERT(FALSE);//出错处理
}
basicRfReceiveOff();//关闭接收机
// 死循环
while(TRUE){
if(halJoystickPushed()){//当按键按下时触发
basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH);//发送命令
}
}
}void main(void)
{
uint8 appMode = NONE;//模式变量
// 设置网络ID和信道
basicRfConfig.panId = PAN_ID;
basicRfConfig.channel = RF_CHANNEL;
basicRfConfig.ackRequest = TRUE;
//初始化其他设备
halBoardInit();
halJoystickInit();
// 初始化射频模块
if(halRfInit()==FAILED){
HAL_ASSERT(FALSE);
}
halLedSet(1);//LED1灯亮,提示节点已上电
utilPrintLogo(“Light Switch”);
// 等待用户按下S1进入菜单
while(halButtonPushed()!=HAL_BUTTON_1);
halMcuWaitMs(350);//延时
halLcdClear();//清屏
// 设置该节点是开关还是电灯
appMode = appSelectMode();
halLcdClear();
// 模块开始工作
if(appMode == SWITCH){
appSwitch();
}
else if(appMode == LIGHT){
appLight();
}
//如果没有定义该节点的功能,则LED灯不断闪烁
HAL_ASSERT(FALSE);
}
static uint8 appSelectMode(void)//模式选择 {
halLcdWriteLine(1, “Device Mode: ”);
return utilMenuSelect(&pMenu);//通过调用头文件实现功能选择
}
实验总结:
这个实验虽然功能非常简单,只是通过按下开关节点的按键来控制电灯节点LED的亮或灭,但是通过这个实验可以了解节点间通信的基本思路。
原代码中有许多可有可无的冗余代码,上面的代码经过代码中很多都是调用头文件,在这里就不在一一罗列,只在代码注释中注明该调用的功能。这些调用都是一些非常简单的操作,写入头文件调用是为了增加代码可读性。
baseRF通信基本流程
1.初始化网络地址,打开接收机或关闭接收机。
2.初始化basicRfConfig,确定网络ID、信道、是否需要应答、是否采用加密机制等。
3.初始化周边设备,如时钟、各个I/O口等。
4.事件的处理,如发送报文或接受报文后的数据处理等。