目录
TinyOS下的CC2420编程
编程语言介绍
代码实现
Makefile
RadioCountToLeds.h
RadioCountToLedsAppC.nc
RadioCountToLedsC.nc
头文件
implementation
implementation
正文
TinyOS下的CC2420编程
RadioCountToLedsC组件图如下图所示,我们可以看到要实现RadioCountToLedsC相关功能,需要使用到MainC,AMReceiverC,AMSenderC,ActiveMessageC,LedsC,TimerMilliC组件,虚线框表明该组件使用的是虚拟资源。
编程语言介绍
本次实验所用的编程语言为nesC,在本篇里笔者就不过多赘述啦
代码实现
我们直接进入正题,看代码来理解节点与节点之间无线通信的具体实现。
一下代码的效果是,通过无线通信完成每个节点LED灯都按同一种频率闪烁。
Makefile
Makefile文件,就是定义代码的书写规则
CFLAGS += -DCC2420_DEF_CHANNEL=14, 这句话是非常重要的,是无线通信里的频段设置
COMPONENT=RadioCountToLedsAppC
CFLAGS += -DCC2420_DEF_CHANNEL=14
CFLAGS += -I$(TOSDIR)/lib/printf
COMPONENT=RadioCountToLedsAppC CFLAGS += -DCC2420_DEF_CHANNEL=14 CFLAGS += -I$(TOSDIR)/lib/printf 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
RadioCountToLedsAppC.nc
implementation函数里,就是 .C 文件里要用到的一直组件的声明和连接。每个模块我都分开放置并添加了注释。
#include "RadioCountToLeds.h" #include "printf.h" configuration RadioCountToLedsAppC {} implementation { //main,leds components MainC, RadioCountToLedsC as App, LedsC; App.Leds -> LedsC; App.Boot -> MainC.Boot; //radio components new AMSenderC(AM_RADIO_COUNT_MSG); components new AMReceiverC(AM_RADIO_COUNT_MSG); components ActiveMessageC; App.Receive -> AMReceiverC; App.AMSend -> AMSenderC; App.AMControl -> ActiveMessageC; App.Packet -> AMSenderC; //timer components new TimerMilliC(); App.MilliTimer -> TimerMilliC; //print components PrintfC; components SerialStartC; }
RadioCountToLedsC.nc
头文件
#include "Timer.h" #include "RadioCountToLeds.h" #include "printf.h"
implementation
模块的声明,这里对应的是TestNetworkAppC.nc里的implementation这个函数
module RadioCountToLedsC @safe() { uses { interface Leds; interface Boot; interface Receive; interface AMSend; interface Timer<TMilli> as MilliTimer; interface SplitControl as AMControl; interface Packet; } }
implementation
接下来implementation函数里的代码解释,笔者都写在代码注释里啦,代码不算很长,也还是很好理解的啦,大家耐心看吧~😁😁
implementation { message_t packet; //定义一个在RadioCountToLeds.h里定义的一个结构体的包 bool locked; //锁机制,默认false uint16_t counter = 0; event void Boot.booted() { call AMControl.start(); //打开无线通信 } event void AMControl.startDone(error_t err) { if (err == SUCCESS) { //如果无线通信打开成功 call MilliTimer.startPeriodic(1000); //打开1000毫秒定时器,1000毫秒后,执行event void MilliTimer.fired() } else { call AMControl.start(); //打开失败,则重复打开 } } event void AMControl.stopDone(error_t err) { //对应call AMControl.start() // do nothing } event void MilliTimer.fired() { counter++; //记秒数 if (locked) { //锁机制的实现AMSend.sendDone判断发包正确后,会解除锁机制 return; } else { radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t)); //rcm指向packet的负载 if (rcm == NULL) { return; } //如果负载不为空,就将counter的值赋值给rcm->counter rcm->counter = counter; //AM_BROADCAST_ADDR:无线通信中,代表广播 //如果改成 0x01,那就是向1号节点发送单播 if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) { //无线发包 locked = TRUE; //打开锁机制 ,锁住后,转到senddone } } } event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) { //节点接收数据,无线收包 if (len != sizeof(radio_count_msg_t)) {return bufPtr;} //判断是否是我想要的包 else { //如果是我想要的包 radio_count_msg_t* rcm = (radio_count_msg_t*)payload; //rcm指向包的负载 //如果rcm->counter == 1,那么 1 & 0x1 == 0x1,所以LED0会亮,以下同理 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; } } }