BlinkToRadioAppC
tinyOS 2.x 的 App/tutorial/BlinkToRadio⽂件夹下⾯有demo:节点通信下⾯分析⼀下:
<
#include <Timer.h>
#include "BlinkToRadio.h"
configuration BlinkToRadioAppC {
}
implementation {
//
//基本配线,连线MainC.Boot, LedsC.Leds, Timer0.Timer
components MainC;
components LedsC;
components BlinkToRadioC as App;
components new TimerMilliC() as Timer0;
App.Boot -> MainC;
App.Leds -> LedsC;
App.Timer0 -> Timer0;
//
//通信模块的配线
components new AMSenderC(AM_BLINKTORADIOMSG);
components new AMReceiverC(AM_BLINKTORADIOMSG);
components ActiveMessageC;
App.AMSend -> AMSenderC.AMSend;
App.Receive -> AMReceiverC.Receive;
App.SplitControl -> ActiveMessageC.SplitControl;
}
注意,这个是简化版,真正的源代码多了⼀些接⼝,但都是没有必要的,we just need:
两个components: AMSenderC, AMReceiverC
三个interface:
AMSenderC.AMSend //发送信息全靠它了
AMReceiverC.Receive // 接收信息全靠它了
整理档案ActiveMessageC.SplitControl //这个⽤来开启节点的通信模块
<
#include <Timer.h>
#include "BlinkToRadio.h"
module BlinkToRadioC {
//基本的接⼝
us interface Boot;
us interface Leds;
us interface Timer<TMilli> as Timer0;
//通信接⼝
us interface AMSend;
us interface Receive;
us interface SplitControl;
}
implementation {
uint16_t counter; //这个count⽤来控制被Leds.Set()作为参数传⼊,控制节点的LED灯
胃火重有什么症状message_t pkt; //⼀个buffer,这个message_t变量⽤来存储发送或者接受的消息
等子bool busy = FALSE;// 表⽰节点当前的Radio是否繁忙,在AMSend.Send()时将其置为TRUE,
// 在AMSend.ndDone()时将其置为FALSE
event void Boot.booted() {
call SplitControl.start(); //先启动Radio,这个是Split-pha分阶段接⼝,
//在随后的SplitControl.startDone()中我们再处理
}
event void SplitControl.startDone(error_t err) {
/
/如果Radio成功打开,我们就设置定时器的周期否则继续尝试开启
if (err == SUCCESS) {
call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
}
el {
call SplitControl.start();
}
}
event void SplitControl.stopDone(error_t err) {
//stopDone()我们不需要管,因为不需要关闭Radio
}
/
/因为设置了定时器,在每个周期到来时,定时器会发送fired信号,因此我们在每次信号处理函数⾥⾯可以处理了! event void Timer0.fired() {
counter++; //让counter++,这样发送出去的counter有了变化,不同的LED灯都可以闪烁了!
if (!busy) {
/*如果信道不被暂⽤,那么...
获得你要操作的message_t也就是pkt内部那块payload(负载)的地址,
这样我就可以让message加上我⾃⼰的数据了
*/
BlinkToRadioMsg* btrpkt =
女微信名
(BlinkToRadioMsg*)(Payload(&pkt, sizeof(BlinkToRadioMsg)));
if (btrpkt == NULL) { //当然我要检测⼀下是不是失败了
return;
}
btrpkt->nodeid = TOS_NODE_ID; //将节点的ID与counter值填⼊message中等待发送
btrpkt->counter = counter;
/*⼀切准备就绪以后,我们使⽤AMSend提供的command:nd将该message发送出去,注意它的参数传递:
第⼀个参数表⽰⼀个地址,这⾥的意思是⼴播,其中AM_BROADCAST_ADDR是预先定义的:
在tinyos-2.x/tos/types.h/AM.h修篱种菊什么意思
第⼆个参数表⽰你要发送的消息的地址,也就是带发送消息buffer的地址
第三个参数指明你所要携带的数据的⼤⼩,这个BlinkToRadioMsg在头⽂件中有定义,随后将给出
*/
if (call AMSend.nd(AM_BROADCAST_ADDR,
&pkt, sizeof(BlinkToRadioMsg)) == SUCCESS) {
busy = TRUE; //当然,在发送过程中,我必须设置Radio状态为繁忙
浮食
}
}
}
event void AMSend.ndDone(message_t* msg, error_t err) {
if (&pkt == msg) {
/*如果发送完成,我就将Radio的状态切换为空闲,
这⾥之所以使⽤&pkt == msg表⽰当我发送完成后那么msg也就是
我要负载的那块buffer的地址了
*/
busy = FALSE;
}
}
/* 这个⽤来接收packet,对于我们接收下来的msg,
我们先检测⼀下合法性:简单地判断⼀下负载长度是否和我之前装载在message上的数据长度吻合
*/
event message_t* ive(message_t* msg, void* payload, uint8_t len){
if (len == sizeof(BlinkToRadioMsg)) {
//只要取下payload,并且将其转换为BlinkToRadioMsg的地址,那么就可以操作我们装载的信息了!
BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload;
call Leds.t(btrpkt->counter);
}
return msg;
}
这段代码同样被我删剪了⼀些,源代码中使⽤⾃定义函数 void SetLeds(uint16_t val);来操作LED灯,其实完全可以由Leds.Set()来替代.
BlinkToRadio.h
#ifndef BLINKTORADIO_H
#define BLINKTORADIO_H
什么饥什么渴enum {
AM_BLINKTORADIOMSG = 6, //消息的type
TIMER_PERIOD_MILLI = 250 //计时器的周期
};
typedef nx_struct BlinkToRadioMsg {
nx_uint16_t nodeid; //节点的TOS_NODE_ID
nx_uint16_t counter; //你懂的!
} BlinkToRadioMsg; //消息的负载类型
#endif
Makefile
COMPONENT=BlinkToRadioAppC
include $(MAKERULES)
辣椒炒豆皮这样,⼀个典型的mote与mote通信的应⽤程序就写好了, 注意这⾥我做了⼀些简化,和原来的有点不⼀样,但是这更容易理解。