大家好,欢迎来到IT知识分享网。
一、实验目的
通过本实验的课程教学,主要是让用户了解以下内容:
1..通过本实验了解节点与节点之间的无线通信。
2.通过本实验熟悉通信相关的组件及接口。
3.通过本实验学习数据包的发送和接收。
二、知识介绍
1.CC2420电路介绍
CC2420是Chipcon As公司推出的首款符合2.4GHz IEEE802.15.4标准的射频收发器。该器件包括众多额外功能,是第一款适用于ZigBee产品的RF器件。它基于Chipcon公司的SmartRF 03技术,以0.18um CMOS工艺制成,只需极少外部元器件,性能稳定且功耗极低。CC2420的选择性和敏感性指数超过了IEEE802.15.4标准的要求,可确保短距离通信的有效性和可靠性。利用此芯片开发的无线通信设备支持数据传输率高达250kbps,可以实现多点对多点的快速组网。
CC2420的主要性能参数如下:
1.工作频带范围:2.400~2.4835GHz;
2.采用IEEE802.15.4规范要求的直接序列扩频方式;
3.数据速率达250kbps码片速率达2MChip/s;
4.采用O-QPSK调制方式;
5.超低电流消耗(RX:19.7mA,TX:17.4mA)高接收灵敏度(-99dBm);
6.抗邻频道干扰能力强(39dB);
7.内部集成有VCO、LNA、PA以及电源整流器,采用低电压供电(2.1~3.6V);
8.输出功率编程可控;
9.IEEE802.15.4 MAC层硬件可支持自动帧格式生成、同步插入与检测、16bit CRC校验、电源检测、完全自动MAC层安全保护(CTR、CBC-MAC、CCM);
10.与控制微处理器的接口配置容易(4总线SPI接口);
11.采用QLP-48封装,外形尺寸只有7*7mm。
CC2420芯片的内部结构如图10-1所示。天线接收的射频信号经过低噪声放大器和I/Q下变频处理后,中频信号只有2MHz,此混合I/Q信号经过滤波、放大、AD变换、自动增益控制、数字解调和解扩,最终恢复出传输的正确数据。
图2-1 CC2420芯片结构
发射机部分基于直接上变频,要发送的数据先被送入128字节的发送缓存器中,头帧和起始帧是通过硬件自动产生的。根据IEEE802.15.4标准,所要发送的数据流的每4个比特被32码片的扩频序列扩频后送到DA变换器。然后,经过低通滤波和上变频的混频后的射频信号最终被调制到2.4GHz,并经放大后送到天线发射出去。
CC2420调制和扩频的过程如下图10-2。
图2-2 CC2420调制和扩频的过程
CC2420解调的过程如图10-3。
图2-3 CC2420解调模块图
CC2420典型电路:
CC2420只需要极少的外围元器件,其典型应用电路如图10-4所示。它的外围电路包括晶振时钟电路、射频输入/输出匹配电路和微控制器接口电路三个部分。CC2420可以通过4线SPI总线(SI、SO、SCLK、CSN)设置芯片的工作模式,并实现读/写缓存数据读/写状态寄存器等,通过控制FIFO和FIFOP管脚接口的状态可设置发射/接收缓存器。注意:在SPI总线接口上进行的地址和数据传输大多是MSB优先的。CC2420片内有33个16比特状态设置寄存器,在每个寄存器的读/写周期中,SI总线上共有24比特数据,分别为:1比特RAM/寄存器选择位(0:寄存器,1:RAM),1比特读/写控制位(0:写,1:读),6比特地址选择位、16比特数据位。在数据传输过程中CSN必须始终保持低电平。
另外,通过CCA管脚状态的设置可以控制清除通道估计,通过SFD管脚状态的设置可以控制时钟/定时信息的输入。这些接口必须与微处理器的相应管脚相连来实现系统射频功能的控制与管理。
图2-4典型电路
CC2420与Msp430F1611连接如图10-5。
图2-5连接图
三、实验步骤
1.上传编译代码
点击浏览按钮上传RadioCountToLeds代码,点击编译按钮编译实验代码,编译提示信息如下
图2-6 实验代码上传
图2-7 上传编译界面
2.烧录代码
选择0号、1号两个节点同时烧录RadioCountToLeds代码,烧录提示信息如下:
图2-8 烧录提示信息
3.结果观察
现象:2个节点亮灯,0号节点亮的是1号节点发送的counter值,1号节点亮的是0号节点的发送的counter值。如果只烧录一个节点,则该节点不亮灯。如果容易操作,可按住0号或者1号节点的Reset按钮,即可发现另外的节点灯停止闪烁。
四、实验分析
1.TinyOS编程模式分析
在这一讲中,我们接触到了TinyOS下的CC2420编程
RadioCountToLedsC组件图如下图所示,我们可以看到要实现RadioCountToLedsC相关功能,需要使用到MainC,AMReceiverC,AMSenderC,ActiveMessageC,LedsC,TimerMilliC组件,虚线框表明该组件使用的是虚拟资源。
图2-9 组件图
图中的箭头的方向表明了组件使用关系,例如MainC组件提供了Boot这个接口给RadioCountToLedsC组件使用。下面我们看下代码的具体实现过程,这个关系图体现在下列代码:
RadioCountToLedsAppC.nc
源码
/*----代码截取于RadioCountToLeds/RadioCountToLedsAppC.nc-----*/
configuration RadioCountToLedsAppC { }
implementation {
//组件定义
components MainC, RadioCountToLedsC as App, LedsC;
components new AMSenderC(AM_RADIO_COUNT_MSG);
components new AMReceiverC(AM_RADIO_COUNT_MSG);
components new TimerMilliC();
components ActiveMessageC;
// 组件关系连接
App.Boot -> MainC.Boot;
App.Receive -> AMReceiverC;
App.AMSend -> AMSenderC;
App.AMControl -> ActiveMessageC;
App.Leds -> LedsC;
App.MilliTimer -> TimerMilliC;
App.Packet -> AMSenderC;
}
组件定义,在该代码块中定义了MainC,RadioCountToLedsC,LedsC,AMSenderC,AMReceiverC,TimerMilliC,ActiveMessageC。代码中我们可以看到虚拟资源使用的方法,使用new关键字进行定义。其中可以使用as关键字进行组件重命名。
组件关系连接,在该代码块中可以看到组件图中箭头的具体定义。例如我们使用App作为RadioCountToLeds组件的替代词,使用了MainC组件提供的Boot接口。
下面我们看下具体的实现过程:
RadioCountToLedsC.nc
源码
/*----代码截取于RadioCountToLeds/RadioCountToLedsC.nc-----*/
#include "Timer.h"
#include "RadioCountToLeds.h"
module RadioCountToLedsC @safe() {
uses {
//接口使用声明:在该代码块中,我们可以看到组件RadioCountToLedsC使用的接口
interface Leds;
interface Boot;
interface Receive;
interface AMSend;
interface Timer< TMilli> as MilliTimer;
interface SplitControl as AMControl;
interface Packet;
}
}
implementation {
message_t packet //Message_t类型,详见下面解说
bool locked;
uint16_t counter = 0;
event void Boot.booted() {
call AMControl.start();
//AMControl这个接口作为控制CC2420模块启动和关闭,在下面网络协议中,我们经常会使用该接口。
}
//在CC2420启动完毕后,TinyOS会触发AMControl.startDone事件,该事件表示CC2420启动完毕,
//在程序里面我们在CC2420模块启动成功后,开启250ms的定时器,同样该定时器也以事件的形式告知。
event void AMControl.startDone(error_t err) {
if (err == SUCCESS) {
call MilliTimer.startPeriodic(250);
}
else {
call AMControl.start();
}
}
event void AMControl.stopDone(error_t err) {
// do nothing
}
event void MilliTimer.fired() {
counter++;
if (locked) { return; }
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet,
sizeof(radio_count_msg_t));
if (rcm == NULL) { return; }
rcm->counter = counter;
//发包的关键代码
if (call AMSend.send(AM_BROADCAST_ADDR, &packet,
sizeof(radio_count_msg_t)) == SUCCESS) {
dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter);
locked = TRUE;
}
}
}
//Receive事件,一旦CC2420接收到发送给自己的数据包的时候,就会触发该事件。
//通过解析数据包中counter位并使用板载的Led显示。
event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) {
dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
if (len != sizeof(radio_count_msg_t)) {return bufPtr;}
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
if (rcm->counter & 0x1) {
call Leds.led0On();
}
else {
call Leds.led0Off();
}
if (rcm->counter & 0x2) {
call Leds.led1On();
}
else {
call Leds.led1Off();
}
if (rcm->counter & 0x4) {
call Leds.led2On();
}
else {
call Leds.led2Off();
}
return bufPtr;
}
}
event void AMSend.sendDone(message_t* bufPtr, error_t error) {
if (&packet == bufPtr) { locked = FALSE; }
}
}
Message_t类型分析:
源码
/*----代码截取于RadioCountToLeds/RadioCountToLeds.h-----*/
typedef nx_struct message_t {
nx_uint8_t header[sizeof(message_header_t)];
nx_uint8_t data[TOSH_DATA_LENGTH];
nx_uint8_t footer[sizeof(message_footer_t)];
nx_uint8_t metadata[sizeof(message_metadata_t)];
} message_t;
//Makefile
COMPONENT=RadioCountToLedsAppC
CFLAGS += -DCC2420_DEF_CHANNEL=14
include $(MAKERULES)
//RadioCountToLeds.h
#ifndef RADIO_COUNT_TO_LEDS_H
#define RADIO_COUNT_TO_LEDS_H
typedef nx_struct radio_count_msg {
nx_uint16_t counter;
} radio_count_msg_t;
enum {
AM_RADIO_COUNT_MSG = 6,
};
#endif
在这里我们可以看到TinyOS定义的数据包的格式,用户其实只需要关心data这一数据位。
同时我们在这里介绍下使用message_t的接口:
Packet:该接口提供了基本的操作message_t的功能,例如清楚消息内容,获取payload长度以及获取payload的地址指针等。
Send:该接口提供了基本的不基于地址(address-free)的消息发送功能,例如发送一条消息以及取消一条待发消息的发送等。并且还提供了事件来提示发送是否成功。当然也提供了获取消息最大payload以及payload地址指针的功能。
Receive:该接口提供了基本消息接收功能和获取payload信息的功能。
PacketAcknowledgements:该接口提供了获取发送消息回执的机制。
AMPacket:这个接口和Packet类似,提供了获取与设置一个节点的AM地址,AM包的目的地址以及AM包的类型等功能。
AMSend:这个接口和Packet类似,提供了获取与设置一个节点的AM地址,AM包的目的地址以及AM包的类型等功能。
在250ms的定时器中,我们看到了发包的关键代码:
if (call AMSend.send(AM_BROADCAST_ADDR, &packet,sizeof(radio_count_msg_t)) == SUCCESS)
在这个函数的参数中,定义了发包的地址、发包起始位、数据包的长度。其中AM_BROADCAST_ADDR是一个宏定义表示0xFFFF,用户可以通过修改该值来达到发送指定节点ID的目的。节点ID在传感器网络中是作为唯一的标志,在烧写节点ID的时候,可以通过命令:make telosb install,ID
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32835.html