TinyOS - 点对点通信
文章目录
- 一、基础知识
- 1.1 组件:AMSenderC
- 1.1.1 AMSenderC组件接口:AMSend
- cancel命令
- getPayload命令
- send命令
- sendDone事件
- maxPayloadLength命令
- 1.1.2 AMSenderC组件接口:Packet
- clear 命令 清理packet
- getPayload命令 获取有效负载
- 1.2 组件:AMReceiverC
- 1.2.1 AMReceiverC组件接口:Receive
- receive 事件
- 1.3 ActiveMessageC
- 1.3.1 接口SplitControl
- 命令 start()
- 命令 stop()
- 事件 startDone
- 事件 stopDone
- 二、源码分析
- Makefile
- RadioCountToLeds.h
- RadioCountToLedsAppC.nc
- RadioCountToLedsC.nc
一、基础知识
1.1 组件:AMSenderC
虚拟化的活动消息发送抽象。 AMSenderC的每个实例都有其自己的深度为1的队列。 因此,它不必与队列空间的其他AMSenderC实例竞争。 基础实现使用某种形式的公平共享队列来调度这些队列中的数据包。
1.1.1 AMSenderC组件接口:AMSend
cancel命令
- error_t cancel(message_t *msg)
- 功能:取消请求的传输。
- 参数:需取消传输的message_t 类型的数据包的地址。
- 返回值:取消成功返回SUCCESS
- 示例:无
getPayload命令
- void *getPayload(message_t *msg, uint8_t len)
- 功能:返回一个指向包中协议有效负载区域的指针。
- 参数:*msg - 需获取负载的message_t 类型的数据包的地址;len - 数据包的长度
- 返回值:获取成功返回指向有效负载的指针;获取失败返回NULL
- 补充说明:
他的命令的行为与Packet.getPayload相同(减去length参数),并且为方便起见包含在此接口中。 - 示例:
//App.Packet -> AMSenderC;
//interface Packet;
typedef nx_struct radio_count_msg {nx_uint16_t counter;
} radio_count_msg_t;message_t packet;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;//修改payload的值
send命令
- error_t send(am_addr_t addr, message_t *msg, uint8_t len)
- 功能:将数据有效载荷为len的数据包,发送到地址addr。
- 参数:
addr - 包发送到的目标地址;
*msg - 指向需要发送的消息包的指针;
len - 有效负载的长度。 - 返回值:发送成功返回SUCCESS
- 详细说明:
将数据有效载荷为len的数据包发送到地址addr。 要确定最大可用大小,请使用提供AMSend的组件的Packet接口。 如果send返回SUCCESS,则该组件将在将来发出sendDone事件的信号;否则,该组件将发出信号。 如果发送返回错误,则不会发出事件信号。 注意,一个组件可以接受一个发送请求,后来发现它不能满足要求。 在这种情况下,它将用错误代码向sendDone发出信号。 - 示例:
// App.AMSend -> AMSenderC;
//interface AMSend;
typedef nx_struct radio_count_msg {nx_uint16_t counter;
} radio_count_msg_t;message_t packet;//定义packetradio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));//获取指向packet中有效负载的指针
rcm->counter = counter;//设定有效负载的值
if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) //发送数据包packet
{//do something ...
}
sendDone事件
- event void sendDone(message_t *msg, error_t error)
- 功能:发送成功后触发的一个事件
- 参数:
msg - 已经发送成功的包
error - 指示发送是否出现小错误而导致的发送失败。 - 返回值:
如果成功发送,则为SUCCESS ;
如果未成功,则为FAIL ;
如果已取消,则为ECANCEL - 示例:
// App.AMSend -> AMSenderC;//interface AMSend;message_t packet;//省略了对packet的一些操作event void AMSend.sendDone(message_t* bufPtr, error_t error) {if (&packet == bufPtr) {locked = FALSE;}}
maxPayloadLength命令
- uint8_t maxPayloadLength()
- 功能:返回此通信层可以提供的最大有效载荷长度。
- 参数:无
- 返回值:最大负载长度
- 示例:无
1.1.2 AMSenderC组件接口:Packet
简介:基本消息数据类型访问器。 协议可以将附加的分组接口用于其协议特定的数据/元数据。
clear 命令 清理packet
- void clear(message_t *msg)
- 功能:清空这个packet
- 参数:
*msg - 需清空的message_t 类型的数据包的地址; - 返回值:无
- 详细说明:
这是一个深层操作和全部操作:在任何层上调用clear()将完全清除数据包。
getPayload命令 获取有效负载
- void *getPayload(message_t *msg, uint8_t len)
- 功能:返回一个指向包中协议有效负载区域的指针。
- 参数:
*msg - 包的指针
len - 所需负载的长度 - 返回值:获取成功返回指向有效负载的指针;获取失败返回NULL
- 示例:
//interface Packet;
typedef nx_struct radio_count_msg {nx_uint16_t counter;
} radio_count_msg_t;message_t packet;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;//修改payload的值
1.2 组件:AMReceiverC
1.2.1 AMReceiverC组件接口:Receive
receive 事件
- event message_t *receive(message_t *msg, void *payload, uint8_t len)
- 功能:接收一个包缓存
- 参数:
*msg - 接收到的数据包
*payload- 指向数据包有效负载的指针;
len - 指向有效负载的数据区域的长度 - 返回值:堆栈的数据包缓冲区,用于下一个接收到的数据包。
- 示例:
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;//复制有效负载的值} }
1.3 ActiveMessageC
1.3.1 接口SplitControl
这是StdContol接口的分相副本。 它应用于在提供它的组件的打开和关闭电源状态之间切换。 对于每个start()或stop()命令,如果该命令返回SUCCESS,则必须发出相应的startDone()或stopDone()事件的信号。
命令 start()
启动此组件及其所有子组件。
命令 stop()
停用此组件及其所有子组件。
事件 startDone
- event void startDone(error_t error)
- 功能:通知调用方(Notify caller)该组件已启动并准备接收其他命令。
- 参数:
error_t error :SUCCESS 说明成功开启;FAIL表示失败。 - 返回值:无
事件 stopDone
略
二、源码分析
Makefile
这里面定义了频段CFLAGS += -DCC2420_DEF_CHANNEL=14
,设置自己的频段避免与其他的设备造成冲突干扰
COMPONENT=RadioCountToLedsAppC
CFLAGS += -DCC2420_DEF_CHANNEL=14
include $(MAKERULES)
RadioCountToLeds.h
- 定义了一个名为 radio_count_msg_t 的结构体类型,作为我们的数据包类型。
- AM_RADIO_COUNT_MSG,定义标识号为6
#ifndef RADIO_COUNT_TO_LEDS_H
#define RADIO_COUNT_TO_LEDS_Htypedef nx_struct radio_count_msg {nx_uint16_t counter;
} radio_count_msg_t;enum {AM_RADIO_COUNT_MSG = 6,
};#endif
RadioCountToLedsAppC.nc
#include "RadioCountToLeds.h"configuration RadioCountToLedsAppC {}
implementation {//main ledscomponents MainC, RadioCountToLedsC as App, LedsC;App.Boot -> MainC.Boot;App.Leds -> LedsC;//timercomponents new TimerMilliC();App.MilliTimer -> TimerMilliC;//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;
}
RadioCountToLedsC.nc
发送流程:
- 开机上电后,去开启我们的无线通信控制器
call AMControl.start(); - 开启无线通信控制器成功后会开启1S为周期的定时器,失败则重新开启无线通信控制器。
- 定时器到达定时时间,广播发送一个定义的不断自增的计数器count的数据。
接收流程:
- 开机上电后,去开启我们的无线通信控制器
call AMControl.start(); - 编写接收事件函数
首先过滤有效负载长度不正确的数据
然后给有效负载的数据起个别名rcm,并转化成我们定义的结构体类型。
最后根据rcm->counter 的方式读出counter值,并根据counter执行相应操作。
#include "Timer.h"
#include "RadioCountToLeds.h"module RadioCountToLedsC @safe() {uses {interface Leds;interface Boot;interface Receive;interface AMSend;interface Timer<TMilli> as MilliTimer;interface SplitControl as AMControl;interface Packet;}
}
implementation {message_t packet;bool locked;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);}else {//失败重新开启控制器call AMControl.start();}}event void AMControl.stopDone(error_t err) {// do nothing}event void MilliTimer.fired() {counter++;dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter);
//没有锁上,就进行发送数据if (locked) {return;}else {//rcm指向有效负载的地址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;//AM_BROADCAST_ADDR = 0xffff,表示广播// 0x0001,表示发送给1号节点if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) {dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter); locked = TRUE;}}}//发送成功解锁event void AMSend.sendDone(message_t* bufPtr, error_t error) {if (&packet == bufPtr) {locked = FALSE;}}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;}}}
TinyOS - 点对点通信相关推荐
- TinyOS下TOSSIM仿真
TOSSIM仿真实现过程如下所示: 1.进入cygwin应用程序,进入目录 c:/cygwin/opt/tinyos-1.x/apps/TestTinyViz (最后一级的目录为应用程序,自己可以选择 ...
- Powerup tinyos接口实现
// tos启动时点亮Led module PowerupC @safe() { // 使用Boot接口,Boot接口中只有一个事件booted,模块使用接口时,要实现接口中的事件 // 根据提供接口 ...
- node.js当中net模块的简单应用(基于控制台的点对点通信)
我们可以使用node.js当中内置的net模块来创建socket服务端和socket客户端,实现一个简单的基于控制台的点对点通信. 一.利用net模块建立socket客户端 1.引包 const ne ...
- 安装TinyOS需要六个步骤
2019独角兽企业重金招聘Python工程师标准>>> 安装TinyOS需要六个步骤 安装TinyOS需要六个步骤. 1.Installing a Java 1.5 JDK. ...
- 嵌入式系统TinyOS学习资源
2019独角兽企业重金招聘Python工程师标准>>> 本文总结了有关TinyOS学习的资源,以便查找使用. 目录 [隐藏] 1 TinyOS官方资源 2 WSN相关实验室 3 Ti ...
- 数据链路层点对点通信
点对点通信 1.当主机H1向主机H2发送数据时,从协议的层次看,数据进入路由器后要先从物理层上升到网络层,在转发表中找到下一跳的地址后,再下到物理层转发出去. 点对点信道的数据链路层在进行通信时的主要 ...
- tinyos环境安装
我用的是XP,第一步,我先在TINYOS的网站登记下载TINYOS安装包tinyos-1.1.0-1is.exe,你填写完 http://webs.cs.berkeley.edu/users/user ...
- TinyOS总体介绍
TinyOS 体系结构图 TinyOS 硬件抽象层 TinyOS 引入了三层的硬件抽象结构: 硬件表示层(HPL) .硬件适应层(HAL).硬件接口层(HIL) HPL: 直 接对硬件资源进行访问,隐 ...
- TinyOS平台下一些代码的分析
(一)数据采集模块 底层-->高层 SHT->SHTData--> SensorCollection-->AtoSensorCollection-->ANTTree ...
最新文章
- scipy.cluster.vq.kmeans的使用
- 解读:数据科学、机器学习和AI的区别
- windows下mongodb配置
- git push everything up to date问题解决
- UA MATH567 高维统计专题1 稀疏信号及其恢复3 Coherence与RIP简介
- 我的世界梦之边缘5服务器在维护吗,8月5日服务器例行维护公告(已完成)
- 电脑编程教学_2020太原数控车床电脑编程一对一实操教学不限学时
- c语言中如何取消最后一个空格,新人提问:如何将输出时每行最后一个空格删除...
- oracle获取日期中日,关于ORACLE ERP中日记帐的借、贷对应的问题
- Spring父子上下文(WebApplicationContext)(防止事务失效)
- linux 小红伞使用手册,安装LINUX下小红伞图文教程.pdf
- 统计推断—参数估计—点估计、区间估计、t分布、Z分布
- sql server服务器 性能,初涉SQL Server性能问题(1/4):服务器概况
- 免费领7天腾讯视频VIP/优酷会员!
- 南京java架构师工资_java架构师工资一般是多少?怎么提升才能获得高薪?
- Linux:命令 执行操作符
- 我的世界java版刷雪球机,我的世界手机版怎么刷雪球 无限刷雪球机
- 计算机考研零基础英语怎么复习,英语零基础怎么考研 上岸学姐来教你
- 乐山市计算机学校的董事长是,乐山市计算机学校庆祝建校25周年
- 设置QTableView的内容自动换行(2)
热门文章
- three.js之模型
- centos7 Redis单机多节点集群部署
- 吴军的谷歌方法论|第009封信|上帝喜欢笨人(上)
- [docker]三、docker理论概念(镜像、仓库、容器),用docker运行nginx来搭建一个属于自己网站。查看进程监听哪个端口的命令
- z370对应的服务器芯片,8代酷睿绝配!Intel Z370芯片组主板评测:必备马甲
- 主谓宾定状补口诀及练习题
- 计算机电缆铠装电缆护套管,电缆护套管常用型号介绍
- c语言void* arg,求教!!!void *(*process) (void *arg);
- RPC304A POE系统四通道PSE控制芯片,POE Controller,PSE Controller ,主要PIN IP804/IP808,TPS28361等芯片
- java list定义和初始化_在 Java 中初始化 List 的五种方法