zigBee实验报告

zigBee实验报告
zigBee实验报告

ZIgBee学习心得

实验报告

项目名称基于无线传感器网络的采温实验专业班级软件1105

学号

姓名

目录

《计算机网络》............................................................................................. 错误!未定义书签。实验报告. (1)

一、实验目的 (3)

二、实验内容和报告简介 (3)

三、实验相关设备环境 (3)

四、实验内容 (7)

4.1.内容简介 (7)

4.2. 无线传感器网络采温系统实验 (7)

4.2.1实验简介 (7)

4.2.2 工程结构简介 (8)

4.2.3 设备功能及网络拓扑结构介绍 (10)

4.2.4 main()函数和OSAL (10)

4.2.5 设备相关功能主要函数介绍 (14)

4.3 ZigBee协议和ZStack分析 (26)

4.3.1 ZigBee协议和ZStack简介 (27)

4.3.2 OSAL原理分析和实现 (28)

4.3.3IEEE 802.15.规定的PHY层 (35)

4.3.4IEEE 802.15.规定的MAC层 (37)

4.3.5 ZigBee2007的网络层。 (40)

4.3.6 ZigBee2007的应用层 (45)

五、实验结果 (46)

六、实验结论 (47)

七、实验小结 (47)

7.1 短距离无线通信网络的现状和发展 (47)

7.2 ZigBee通信技术的应用 (48)

7.3 学习ZigBee开发的心得体会 (48)

7.4 下一步可能的学习计划 (49)

实验《基于无线传感器网络的采温实验》实验学时:1 实验地点:201 实验日期: 5.10

一、实验目的

1. 设计并实现一套无线传感器网络的采温系统。

2. 较为详细的分析ZigBee协议栈。

二、实验内容和报告简介

完成采集器、传感器设备的设计和实现。

对ZigBee2007协议和Zstack进行较为详细的分析。

三、实验相关设备环境

介绍了开发板、CC2530和协议栈

四、实验内容

第一部分详细描述了开发的工作,附上了关键代码和注释。

第二部分分析了ZIgBee协议操作系统,描述了其运行机制;以及PHY 层、MAC层、网络层、应用层。在网络层描述了其网络拓扑结构,并针对Ad-Hoc 路由算法提出了一个我自己的一个想法。

五、实验结果

通过照片展示了实验效果。

六、实验结论

说明了温度数据偏差的原因。

六、实验小结

谈了些无线通信的现状;学习的心得,不足和未来的能力方向。

三、实验相关设备环境

1. 主要的硬件环境

ZigBee开发板(两个)本实验利用的开发板是在淘宝上买的。应该是一个小店参考TI公司产品生产的。

外形如图1所示:

图1:ZigBee开发板外形图

本开发板采用TI公司的CC2530芯片,外有晶振、RS232串口、按键、电源灯外围电路及元件。本实验利用CC2530芯片集成的片上温度传感器采集温度。

部分核心板电路如图2所示:

图2:部分核心板电路图

部分底板电路图如图3所示:

图3:部分底板电路图

CC2530芯片

CC2530 是用于2.4-GHz IEEE 802.15.4、ZigBee 和RF4CE 应用的一个真正的片上系统(SoC)解决方案。它能够以非常低的总的材料成本建立强大的网络节点。CC2530 结合了领先的RF 收发器的优良性能,业界标准的增强型8051 CPU,系统内可编程闪存,8-KB RAM 和许多其他强大的功能。CC2530 具有不同的运行模式,使得它尤其适应超低功耗要求的系统。运行模式之间的转换时间短进一步确保了低能源消耗。

图4:CC2530框图

CC2530 具有一个IEEE 802.15.4 兼容无线收发器。RF 内核控制模拟无线模块。另外,它提供了MCU 和无线设备之间的一个接口,这使得可以发出命令,读取状态,自动操作和确定无线设备事件的顺序。无线设备还包括一个数据包过滤和地址识别模块。

CC2530的硬件设计也支持ZigBee协议所要求的各种协议和算法。

2. 主要的软件环境

TI公司的ZStack-CC2530-2.2.2-1.3.0。ZStack是TI公司为开发者提供的符合ZigBee2007的协议栈,是开发ZigBee模块必不可少的环境(当然你也可以选择其他协议栈或自己开发一个协议栈)。ZStack是一个免费半开源的产品。

注:ZigBee协议是ZigBee联盟给出的一个短距离无线传输协议。

ZigBee协议栈是ZigBee协议的具体实现。

ZStack是TI公司开发的ZigBee协议栈。

四、实验内容

4.1.内容简介

本节内容主要分为以下两方面:1. 无线传感器网络采温系统实验 2. ZigBee协议(ZigBee2007版,下同)和ZStack分析。

无线传感器网络采温系统实验部分是对本次开发的一个描述。在商业的ZigBee模块开发中是都利用了ZigBee协议栈,其为开发提供了必要的接口。开发者所做的代码工作主要是相关的硬件驱动和应用程序。本实验室基于TI官方实例SimpleAPI所做,并对这个实例进行了必要的改写。

虽然ZigBee协议栈为开发者提供了所需的API,使得开发者不必关心ZigBee 协议的具体实现,便可开发出产品,但是要想更好的开发ZigBee产品,我想还必须对ZigBee协议和协议栈进行研究分析。本段内容的另一个部分便是对此的描述。

4.2. 无线传感器网络采温系统实验

4.2.1实验简介

本实验基于ZigBee网络设计了一个无线传感器网络,可以完成无线的采温功能。

设备类型简介:

协调器(作为采集器)

协调器是一个ZB网络的第一个开始的设备,或者是一个ZB网络的启动或建立网络的设备。协调器节点选择一个信道和网络标志符(也叫PAN ID),然后开始建立一个网络。协调器设备在网络中还可以有其他作用,比如建立安全机制、网络中的绑定的建立等等。

注意:协调器主要的作用是建立一个网络和配置该网络的性质参数。一旦这些完成,该协调器就如同一个路由器,网络中的其他操作并不依赖该协调器,因为ZB是分布式网络。

路由器(作为传感器)

一个路由器的功能有(1)作为普通设备加入网络(2)多跳路由(3)辅助其它的子节点完成通信。

终端设备(作为传感器)

为了维持网络最基本的运行,对于终端设备没有指定的责任。也就是说,在一个基本网络中,终端设备没有必不可缺少性。所以它可以根据自己功能需要休

眠或唤醒,因此为电池供电设备。一般来说,该设备需要的内存较少(特别是内部RAM)

网络的拓扑结构

网状结构(无线mesh网络)

图5:网络拓扑结构图

黑色的为协调器节点,作为采集器,接收温度信息,并通过串口发送到PC 机上。红色的和白色的为传感器节点,采集温度数据发送到采集器。红色的具有路由功能。网络从功能上讲是基于ad hoc 网络的,具有自组织,多跳等特点。因此可扩展性、健壮性都很有优势。

4.2.2 工程结构简介

工程结构如图5所示:

图6:工程的工作空间

说明:

APP(Application Programming):应用层目录,这是用户创建各种不同工程的区域,在这个目录中包含了应用层的内容和这个项目的主要内容,在协议栈里面一般是以操作系统的任务实现的。

HAL(Hardware (H/W) Abstraction Layer):硬件层目录。

MAC:介质接入控制子层目录,包含了MAC 层的参数配置文件及其MAC 的LIB 库的函数接口文件。实现的功能有:1、能产生网络信标。2、支持PAN的连接和断开连接。3、同信标保持同步。4、在对等的MAC实体之间提供一个可靠的通信链路。5、处理和维护GTS机制。6、信道接入采用CSMA-CA接入机制。7、支持设备的安全性。介质访问控制层(MAC)帧被称为MAC协议数据单元(MPDU),其长度不超过127个字节。它具有四种不同的帧形式,即信标帧、数据帧、确认帧和命令帧。

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 自动生成的。

4.2.3 设备功能及网络拓扑结构介绍

ZigBee设备可分为全功能设备(FFD)和简化功能设备(RFD)。全功能设备可以作为协调器(路由器)节点,可以进行数据的转发等功能。简化功能设备只能作为终端节点发送和接受数据。

ZigBee协议支持多种网络拓扑结构,包括星型结构,树形结构,网状结构等。关于ZIgBee网络拓扑结构的较为详细的介绍,将在本段3节中给出。

由于我暂时只买了两个模块,所以网络拓扑结构也很简单了。一个是协调器节点,作为采集器模块通过串口同我的笔记本相连。另一个是终端节点作为传感器模块测量温度并传输数据。需要指出的是,只要有足够多的节点,本实验完全能够根据实际需要设计出有效的网络拓扑结构。

4.2.4 main()函数和OSAL

这部分是Zstack的程序,与我们编程工作密切相关,所以进行简单说明。一个程序是从main()函数开始运行的。在ZStack中main()函数主要完成了各种初始化任务,以及操作系统OSAL的启动。

相关的函数代码如下:

/**************************************************************** *****

* @fn main

* @brief First function called after startup.

* @return don't care

*/

int main( void )

{

// Turn off interrupts

osal_int_disable( INTS_ALL );

// Initialization for board related stuff such as LEDs

HAL_BOARD_INIT();

// Make sure supply voltage is high enough to run

zmain_vdd_check();

// Initialize board I/O

InitBoard( OB_COLD );

// Initialze HAL drivers

HalDriverInit();

// Initialize NV System

osal_nv_init( NULL );

// Initialize the MAC

ZMacInit();

// Determine the extended address

zmain_ext_addr();

// Initialize basic NV items

zgInit();

#ifndef NONWK

// Since the AF isn't a task, call it's initialization routine afInit();

#endif

// Initialize the operating system

osal_init_system();

// Allow interrupts

osal_int_enable( INTS_ALL );

// Final board initialization

InitBoard( OB_READY );

// Display information about this device

zmain_dev_info();

/* Display the device info on the LCD */

#ifdef LCD_SUPPORTED

zmain_lcd_init();

#endif

#ifdef WDT_IN_PM1

/* If WDT is used, this is a good place to enable it. */

WatchDogEnable( WDTIMX );

#endif

osal_start_system(); // No Return from here

return 0; // Shouldn't get here.

} // main()

OSAL即Operating System (OS) Abstraction Layer,是一个基于事件驱动的轮询式的操作系统。它主要提供了任务切换,内存管理等功能。我们在实验中也主要是通过它来开发并管理应用程序。

在main()函数的最后,调用了osal_start_system(),此函数是OSAL的灵魂,也体现了协议栈的工作方式和流程。其主要方法就是:不断查看事件表,如果有事件发生就调用相应的事件处理函数。

相关代码如下:

/**************************************************************** *****

* @fn osal_start_system

*

* @brief

*

* This function is the main loop function of the task system. It

* will look through all task events and call the task_event_processor()

* function for the task with the event. If there are no events (for

* all tasks), this function puts the processor into Sleep.

* This Function doesn't return.

*

* @param void

*

* @return none

*/

void osal_start_system( void )

{

#if !defined ( ZBIT ) && !defined ( UBIT )

for(;;) // Forever Loop

#endif

{

uint8 idx = 0;

osalTimeUpdate();

Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer().

do {

if (tasksEvents[idx]) // Task is highest priority that is ready.

{

break;

}

} while (++idx < tasksCnt);

if (idx < tasksCnt)

{

uint16 events;

halIntState_t intState;

HAL_ENTER_CRITICAL_SECTION(intState);

events = tasksEvents[idx];

tasksEvents[idx] = 0; // Clear the Events for this task.

HAL_EXIT_CRITICAL_SECTION(intState);

events = (tasksArr[idx])( idx, events );

HAL_ENTER_CRITICAL_SECTION(intState);

tasksEvents[idx] |= events; // Add back unprocessed events to the current task.

HAL_EXIT_CRITICAL_SECTION(intState);

}

#if defined( POWER_SAVING )

else // Complete pass through all task events with no activity?

{

osal_pwrmgr_powerconserve(); // Put the processor/system into sleep

}

#endif

}

}

在OSAL中提供了开发所用的API。主要有消息管理、任务同步、时间管理、终端管理、任务管理等。下面对其进行简单的介绍。

(1)消息管理类API 主要用于处理任务间的消息的交换,主要包括任务分配消息缓存、释放消息缓存、接受消息和发送消息等。

Uint8 *osal_msg_allocate(unit16 len) 为消息分配缓存空间。

Uint8 osal_msg_deallocate(uint8 *msg_ptr) 释放消息的缓存空间。

Uint8 osal_msg_send(unit8 destination-task, uint8 *msg_ptr )

一个任务发送消息到消息队列

Uint8 osal_msg_receive(uint8 task_id)

一个任务从消息队列接受属于自己的消息。

(2)任务同步API 用于任务的同步,允许一个任务等待某个事件的发生。

Uint8 osal_set_event(uint8 task_id,uint16 event_flag)

运行一个任务设置某个事件。

(3 时间管理API 开启和关闭定时器,

Uint8 osal_start_timerEx(uint8 task_id,uint16 event_id,uint16 timeout_value) 设置一个定时时间,到后,相应的事件被设置。

Uint8 osal_stop_timerEx(uint8 task_id,uint16 event_id)

停止已经启动的定时器。

OSAL提供的API还有很多,这里仅列出了较为常用的,完整API介绍TI公司提供了相应的用户手册。

关于OSAL的较为详细的介绍,将在本段3节中给出。

4.2.5 设备相关功能主要函数介绍

(1)协调器(采集器)编程协调器主要完成网络的建立维护等功能,这些功能由协议栈提供,其原理在此暂且不描述(下节将有较为详细的描述)。

在其编程过程中,我主要完成的是具体应用的开发。就是将数据接收并发送到串口。函数如下:

void zb_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )

这是协调器最主要的功能函数,处理的是接受到另一个数据后执行的操作。简单来说就是数据归类处理后发送到串口。

函数的代码如下:

/************************************************************ ******************

* @fn zb_ReceiveDataIndication

*

* @brief The zb_ReceiveDataIndication callback function is called * asynchronously by the ZigBee stack to notify the application

* when data is received from a peer device.

*

* @param source - The short address of the peer device that sent the data

* command - The commandId associated with the data

* len - The number of bytes in the pData parameter

* pData - The data sent by the peer device

*

* @return none

*/

CONST uint8 strDevice[] = "Device:0x";

CONST uint8 strTemp[] = "Temp: ";

CONST uint8 strBattery[] = "Battery: ";

void zb_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )

{

uint8 buf[32];

uint8 *pBuf;

uint8 tmpLen;

uint8 sensorReading;

if (command == SENSOR_REPORT_CMD_ID)

{

// Received report from a sensor

sensorReading = pData[1];

// If tool available, write to serial port

// 下面的功能是把发数据的设备号(网络地址)写入缓存

tmpLen = (uint8)osal_strlen( (char*)strDevice );

pBuf = osal_memcpy( buf, strDevice, tmpLen );

_ltoa( source, pBuf, 16 );

pBuf += 4;

*pBuf++ = ' ';

if ( pData[0] == BATTERY_REPORT )

{

// 当传输的数据是电压时,进行如下处理。

tmpLen = (uint8)osal_strlen( (char*)strBattery );

pBuf = osal_memcpy( pBuf, strBattery, tmpLen );

*pBuf++ = (sensorReading / 10 ) + '0'; // 高位转换

*pBuf++ = '.'; // 小数点

*pBuf++ = (sensorReading % 10 ) + '0'; // 低位转换

*pBuf++ = ' ';

*pBuf++ = 'V';

}

else

{

// 当传输的数据时温度时,进行如下处理。

tmpLen = (uint8)osal_strlen( (char*)strTemp );

pBuf = osal_memcpy( pBuf, strTemp, tmpLen );

*pBuf++ = (sensorReading / 10 ) + '0'; // 高位转换

*pBuf++ = (sensorReading % 10 ) + '0'; //低位转换

*pBuf++ = ' ';

*pBuf++ = 'C';

}

*pBuf++ = '\r';

*pBuf++ = '\n';

*pBuf = '\0';

#if defined( MT_TASK )

// debug_str( (uint8 *)buf );

// 张温刚修改5.6

// 写入串口

HalUARTWrite(0, buf, (byte)osal_strlen( (void*)buf ));

HalUARTWrite(0,"\n",1);

#endif

// can also write directly to uart

}

}

传感器编程主要工作是通过相应的片上传感器读取数据,然后发送的指定的采集器。

传感器相关数据的读取,分为电压值的读取uint8 myApp_ReadBattery( void )与温度值的读取uint8 myApp_ReadTemperature( void )。

代码如下

说明:1. 函数中用到了大量的条件编译,也就是说根据具体的条件,很多代码并没有参与编译,这也是嵌入式开发编程的特点。为了展现原有的代码特点,我并没有对此进行省略。

2. 温度传感器采用了一个效验的算法。

/**************************************************************** **************

* @fn myApp_ReadBattery

*

* @brief Reports battery sensor reading

*

* @param

*

* @return

********************************************************************* *********/

uint8 myApp_ReadBattery( void )

{

#if defined (HAL_MCU_CC2430) || defined (HAL_MCU_CC2530)

// 以下是本次使用CC2530片上电压传感器的条件下读取相应的数据

uint16 value;

/* Clear ADC interrupt flag */

ADCIF = 0;

ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3);

/* Wait for the conversion to finish */

while ( !ADCIF );

/* Get the result */

value = ADCL;

value |= ((uint16) ADCH) << 8;

/*

* value now contains measurement of Vdd/3

* 0 indicates 0V and 32767 indicates 1.25V

* voltage = (value*3*1.25)/32767 volts

* we will multiply by this by 10 to allow units of 0.1 volts

*/

value = value >> 6; // divide first by 2^6

value = (uint16)(value * 37.5);

value = value >> 9; // ...and later by 2^9...to prevent overflow during multiplication

return value;

#endif // CC2430 or CC2530

// 下面不是用此芯片的处理,条件编译,不用管它

#if defined HAL_MCU_MSP430

uint16 value;

/*

There are more than MSP430 board now. Idealy, ADC read should be called */

#if defined (HAL_BOARD_F5438)

value = HalAdcRead (HAL_ADC_CHANNEL_VDD, HAL_ADC_RESOLUTION_14);

value = value * 50;

value = value / 4096;

#else

ADC12CTL0 = ADC12ON+SHT0_2+REFON; // Turn on and set up ADC12

ADC12CTL1 = SHP; // Use sampling timer ADC12MCTL0 = SREF_1+INCH_11; // Vr+=Vref+

ADC12CTL0 |= ENC | ADC12SC; // Start conversion

while ((ADC12IFG & BIT0)==0);

value = ADC12MEM0;

/*

* value now contains measurement of AVcc/2

* value is in range 0 to 4095 indicating voltage from 0 to 1.5V

* voltage = (value*2*1.5)/4095 volts

* we will multiply by this by 10 to allow units of 0.1 volts

*/

value = value >> 1; // value is now in range of 0 to 2048

value = value * 30;

value = value >> 11;

#endif

return ( value );

#endif // MSP430

#if defined HAL_MCU_AVR

// If platform doesnt support a battery sensor, just return random value

uint8 value;

value = 20 + ( osal_rand() & 0x000F );

return ( value );

#endif // AVR

/**************************************************************** **************

* @fn myApp_ReadTemperature

*

* @brief Reports temperature sensor reading

*

* @param

*

* @return

********************************************************************* *********/

uint8 myApp_ReadTemperature( void )

{

#if defined (HAL_MCU_CC2430) || defined (HAL_MCU_CC2530)

// 以下是本次使用CC2530片上电压传感器的条件下读取相应的数据

uint16 value;

/* Clear ADC interrupt flag */

ADCIF = 0;

ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_512 | HAL_ADC_CHN_TEMP);

/* Wait for the conversion to finish */

while ( !ADCIF );

/* Get the result */

value = ADCL;

value |= ((uint16) ADCH) << 8;

/*

* value ranges from 0 to 0x8000 indicating 0V and 1.25V

* VOLTAGE_AT_TEMP_ZERO = 0.743 V = 19477

* TEMP_COEFFICIENT = 0.0024 V/C = 62.9 /C

* These parameters are typical values and need to be calibrated

相关主题
相关文档
最新文档