郑州轻工业学院校内实习
实习名称:物联网技术工程实践
姓名:
院(系):计算机与通信工程学院
专业班级:
学号:
指导教师:
成绩:
时间:2016年9月1日至2017 年1月8日
实习成绩评定表
目录
1
说明 (1)
2系统功能描述 (1)
2.1Z-stack
栈 (1)
2.2CC2530芯片 (2)
2.3功能组成 (3)
3系统设计及实现 (3)
3.1程序设计 (3)
3.1.1发送与接收端程序设计 (3)
3.1.2工程初始化OSAL任务运行方式函数 (5)
3.2硬件操作过程 (5)
4实训心得 (7)
5附录(代码) (7)
1设计说明
在Zigbee网络里,模块之间要进行通信,发射模块明确知道接收模块的网络地址,用这个地址发送数据给接收模块,实现单播通信。单播是以单个端口的短地址或长地址作为目标发送消息的,这样就只有一个端点会接收到,在TI公司的Z-stack协议栈以及提供的工程文件的基础上,配置Zigbee组网的PANID和加入网络添加按键控制数码管完成整个通信过程。
2系统功能描述
2.1Z-stack协议栈
TI公司在提供Zigbee无线单片机CC2530的同时,也提供了Z-Stack协议栈源代码,以方便设计人员将Z-Stack直接移植到CC2530上使用,使其支持IEEE802.15.4/ZigBee 协议。TI也提供比较多的工具软件,如CC2530的FLASH编程软件,包监视分析软件,以及一些在协议之上的应用案例,简单点对点通信软件、智能家居应用软件等。
为了使我们自己的系统稳定可靠运行,必须保证硬件的设计稳定可靠,满足需要的功能要求外,软件的设计也是同样重要的。为了使整个系统能很好的正常工作,必须让软硬件协同操作,在TI的Z-Stack协议栈之上开发我们自己的软件系统,不愧为一种很好的、省力的方式。自己去写Z-Stack协议栈代码并让其稳定运行是不现实的,不是投入太大就是时间太长。这样,对TI的Z-Stack协议栈代码进行必要的了解是非常必要的。
图 2.1-1 协议栈工程页面
第一次打开工程印象最深刻的就是左边一排文件夹,非常多,很庞杂,感觉无从下手。我们先不深入目录之下,先了解每个目录放的是什么内容,那么知道各个文件夹大概是什么功能,分布在 ZIGBEE 的哪一层,那么在以后的工作中无论是查询某些功能函数还是修改某些功能函数,甚至是添加或删除某些功能函数就能顺利的找到在什么地方了,方便对Z-Stack协议栈软件的更深入的学习了解。
下面对Z-Stack协议栈的文件夹进行介绍:
APP(ApplicationProgramming):应用层目录,这是用户创建各种不同工程的区域,在这个目录中包含了应用层的内容和这个项目的主要内容,在协议栈里面一般是以操作系统的任务实现的。
APP:用户应用程序及接口,包括串口数据处理、无线接收数据处理、用户LCD 显示处理、传感器数据读取和发送等。
HAL(Hardware (H/W) Abstraction Layer):硬件层目录,包含有与硬件相关的配置和驱动及操作函数。
MAC:MAC 层目录,包含了 MAC 层的参数配置文件及其 MAC 的 LIB 库的函数接口文件。
MT(Monitor Test):实现通过串口可控各层,于各层进行直接交互。
NWK(ZigBee Network Layer):网络层目录,含网络层配置参数文件及网络层库的函数接口文件,APS 层库的函数接口。
OSAL(Operating System (OS) Abstraction Layer):协议栈的操作系统。
Profile:AF(Application work)层目录,包含 AF 层处理函数文件。
Security:安全层目录,安全层处理函数,比如加密函数等。
Services:地址处理函数目录,包括着地址模式的定义及地址处理函数。
Tools:工程配置目录,包括空间划分及 ZStack 相关配置信息。
ZDO(ZigBee Device Objects):ZDO 目录。
ZMac: MAC 层目录,包括 MAC 层参数配置及 MAC 层 LIB 库函数回调处理函数。
ZMain:主函数目录,包括入口函数及硬件配置文件。
Output:输出文件目录,这个是EW8051 IDE 自动生成的。
2.2CC2530芯片
CC2530 是用于2.4-GHz IEEE 802.15.4、ZigBee和RF4CE(电子遥控射频)应用的一个真正的片上系统(SoC)解决
。它能够以非常低的总的材料成本建立强大的网络
温馨推荐
您可前往百度文库小程序
享受更优阅读体验
不去了
立即体验
节点。CC2530 结合了领先的RF 收发器的优良性能,业界
的增强型8051 CPU,系统内可编程闪存,8-KB RAM 和许多其它强大的功能。CC2530 有四种不同的闪存版本:CC2530F32/64/128/256,分别具有32/64/128/256KB的闪存。CC2530 具有不同的运行模式,使得它尤其适应超低功耗要求的系统。运行模式之间的转换时间短进一步确保了低能源消耗。
2.3 功能组成
利用IAR编译器编程,基于Zigbee CC2530通过对发送端定义三个按键来控制字符串的无线发送,用于接收端数码管的数字显示,完成无线单播通信功能。
图 2.3-1 程序流程图
3系统设计及实现
3.1 程序设计
3.1.1发送与接收端程序设计
(1)从消息队列里取出来引发系统事件的消息。
(2)如果本模块成为了协调器,会进入到这里,然后定义某个按钮改变的消息。之后给这个消息填写类型是按钮状态改变KEY_CHANGE相关的值,把发送给应用层SDApp_TaskID的消息投到消息队列。
(3)如果作为路由器或者终端。
(4)当按下按键3时。
(5)配置数码管程序。
3.1.2工程初始化OSAL任务运行方式函数
3.2 硬件操作过程
左侧为发送端,右侧为接收端,当发送端与接收端数码管分别显示大写字母“E”和“C”时,表示已经配对,准备就绪。
图 3.2-1 入网
之后依次点击按键3按键4和按键5,接收端分别显示“3”“4”“5”。
图 3.2-2 显示“3”
图 3.2-3 显示“4”
图 3.2-4 显示“5”
4实训心得
经过几个月的校内实习,终于圆满完成了实习内容。虽然以前课上学了不少相关的知识,但实际操作起来还是觉得非常复杂,尤其是协议栈相关的代码,起初只能看懂一部分,之后才懂了不同层和不同函数的功能和作用。
期间遇到几个困难,一是如何修改工程代码,让它变成自己的工程,在网上查阅了相关资料才知道,Z-stack协议栈工程程序的主函数不是需要更改的地方,需要改的地方是应用层的.C文件和.h头文件,在这里面写自己的代码。
二是程序出现错误怎么更改,这是最麻烦的地方,只能一点一点去搜错误信息和相关函数的应用,好在在自己的努力下,终于零错误完成程序。
三是特殊功能寄存器的应用,这个算是比较容易的,通过查阅手册,用到那个查哪个,花点时间就能应用其功能。
总之,经过这次校内实习,学到很多知识,不仅是程序和硬件知识,还增强了自己的学习能力和动手能力。最后,再次感谢杜老师的悉心指导,在学习中,老师严谨的治学态度、丰富渊博的知识、敏锐的学术思维、精益求精的工作态度以及侮人不倦的师者风范是我终生学习的楷模,老师的高深精湛的造诣与严谨求实的治学精神,将永远激励着我!
5附录(代码)
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "SDApp.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
#include"74LS164_8LED.h"
// This list should be filled with Application specific Cluster IDs.
const cId_t SDApp_ClusterList[SDApp_MAX_CLUSTERS] =
{
SDApp_CLUSTERID
};
const SimpleDescriptionFormat_t SDApp_SimpleDesc = {
SDApp_ENDPOINT, // int Endpoint; SDApp_PROFID, // uint16 AppProfId[2];
SDApp_DEVICEID, // uint16 AppDeviceId[2];
SDApp_DEVICE_VERSION, // int AppDevVer:4;
SDApp_FLAGS, // int AppFlags:4;
SDApp_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)SDApp_ClusterList, // byte *pAppInClusterList;
SDApp_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)SDApp_ClusterList // byte *pAppInClusterList;
};
// This is the Endpoint/Interface description. It is defined here, but
// filled-in in SDApp_Init(). Another way to go would be to fill
// in the structure here and make it a "const" (in code space). The
// way it's defined in this sample app it is define in RAM. endPointDesc_t SDApp_epDesc;
byte SDApp_TaskID; // Task ID for internal task/event processing
// This variable will be received when
// SDApp_Init() is called. devStates_t SDApp_NwkState;
byte SDApp_TransID; // This is the unique Message ID (counter)
afAddrType_t SDApp_DstAddr;
void SDApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
void SDApp_HandleKeys( byte shift, byte keys );
void SDApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void SDApp_SendTheMessage( void );
void SDApp_Init( byte task_id )
{
SDApp_TaskID = task_id;
SDApp_NwkState = DEV_INIT;
SDApp_TransID = 0;
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main().
SDApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
SDApp_DstAddr.endPoint = 0;
SDApp_DstAddr.addr.shortAddr = 0;
// Fill out the endpoint description.
SDApp_epDesc.endPoint = 11;//SDApp_ENDPOINT; SDApp_epDesc.task_id = &SDApp_TaskID;
SDApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;
SDApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF afRegister( &SDApp_epDesc );
// Register for all key events - This app will handle all key events
RegisterForKeys( SDApp_TaskID );
// Update the display
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "SDApp", HAL_LCD_LINE_1 ); #endif
ZDO_RegisterForZDOMsg( SDApp_TaskID, End_Device_Bind_rsp );
ZDO_RegisterForZDOMsg( SDApp_TaskID, Match_Desc_rsp );
}
UINT16 SDApp_ProcessEvent( byte task_id, UINT16 events )
{
afIncomingMSGPacket_t *MSGpkt;
afDataConfirm_t *afDataConfirm;
// Data Confirmation message fields
byte sentEP;
ZStatus_t sentStatus;
byte sentTransID; // This should match the value sent
(void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SDApp_TaskID );//从消息队列里取出来引发系统事件的消息
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case ZDO_CB_MSG:
SDApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
case KEY_CHANGE:
SDApp_HandleKeys( ((keyChange_t *)MSGpkt)->State, ((keyChange_t *)MSGpkt)->keys );
break;
case AF_DATA_CONFIRM_CMD:
// This Message is received as a confirmation of a data packet sent.
// The status is of ZStatus_t type [defined in ZComDef.h]
// The message fields are defined in AF.h
afDataConfirm = (afDataConfirm_t *)MSGpkt;
sentEP = afDataConfirm->endpoint;
sentStatus = afDataConfirm->hdr.status;
sentTransID = afDataConfirm->transID;
(void)sentEP;
(void)sentTransID;
// Action taken when confirmation is received.
if ( sentStatus != ZSuccess )
{
// The data wasn't delivered -- Do something
}
break;
case AF_INCOMING_MSG_CMD:
SDApp_MessageMSGCB( MSGpkt );
break;
case ZDO_STATE_CHANGE:
SDApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SDApp_NwkState == DEV_ZB_COORD)
|| (SDApp_NwkState == DEV_ROUTER)
|| (SDApp_NwkState == DEV_END_DEVICE) )
{
// Start sending "the" message in a regular interval.
// osal_start_timerEx( SDApp_TaskID,
//
SDApp_SEND_MSG_EVT,
//
SDApp_SEND_MSG_TIMEOUT );
}
if(SDApp_NwkState == DEV_ZB_COORD)
{
LS164_BYTE(11);
keyChange_t *msgPtr;
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );
if ( msgPtr )
{
msgPtr->hdr.event = KEY_CHANGE;
msgPtr->keys=3;//消息里面的内容是3
osal_msg_send( SDApp_TaskID, (uint8 *)msgPtr );
}
osal_start_timerEx(SDApp_TaskID,SDApp_MY_EVT,300 0);
}
if(SDApp_NwkState == DEV_ROUTER)
{//成为了路由器
LS164_BYTE(12);
}
if(SDApp_NwkState == DEV_END_DEVICE)
{//成为了终端
LS164_BYTE(13);
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SDApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Send a Message out - This event is generated by a timer
// (setup in SDApp_Init()).
if ( events & SDApp_SEND_MSG_EVT )
{
// Send "the" message
// SDApp_SendTheMessage();
//
// // Setup to send message again
// osal_start_timerEx( SDApp_TaskID,
// SDApp_SEND_MSG_EVT, //
SDApp_SEND_MSG_TIMEOUT );
P0DIR |=0X02;
P0_1=0;
// return unprocessed events
return (events ^ SDApp_SEND_MSG_EVT);
}
if ( events & SDApp_MY_EVT )
{
// P0SEL &=0XEF;//1110 1111
// P0DIR |=0X10;
// P0_4 ^=1;
if(0==P1_1)
{
char theMessageData[] ={3};
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;
SDApp_DstAddr.endPoint = 7;
AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0001,
1,
(byte
*)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
}
if(0==P2_0)
{//按钮4按下
char theMessageData[] ={4};
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint = 7;
AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0002,
1,//(byte)osal_strlen( theMessageData ) + 1,
(byte
*)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
}
if(0==P0_5)
{//按钮5按下
char theMessageData[] ={5};
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;
SDApp_DstAddr.endPoint = 8;
AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0001,
1,
(byte
*)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
}
return (events ^ SDApp_MY_EVT);
}
// Discard unknown events
return 0;
}
void SDApp_ProcessZDOMsgs( zdoIncomingMsg_t
*inMsg )
{
switch ( inMsg->clusterID )
{
case End_Device_Bind_rsp:
if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
{
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
#if defined(BLINK_LEDS)
else
{
// Flash LED to show failure
HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
}
#endif
break;
case Match_Desc_rsp:
{
ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
if ( pRsp )
{
if ( pRsp->status == ZSuccess && pRsp->cnt )
{
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint = pRsp->epList[0];
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
osal_mem_free( pRsp );
}
}
break;
}
}
void SDApp_HandleKeys( byte shift, byte keys )
{
LS164_BYTE(keys);
}
void SDApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case SDApp_CLUSTERID:
// "the" message
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
#elif defined( WIN32 )
WPRINTSTR( pkt->cmd.Data );
#endif
break;
}
}
void SDApp_SendTheMessage( void )
{
char theMessageData[] = "Hello World";
if ( AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
SDApp_CLUSTERID,
(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
// Successfully requested to be sent.
}
else
{
// Error occurred in request to send.
}
}