文章目录

  • 一、基础知识
    • 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

发送流程:

  1. 开机上电后,去开启我们的无线通信控制器
    call AMControl.start();
  2. 开启无线通信控制器成功后会开启1S为周期的定时器,失败则重新开启无线通信控制器。
  3. 定时器到达定时时间,广播发送一个定义的不断自增的计数器count的数据。

接收流程:

  1. 开机上电后,去开启我们的无线通信控制器
    call AMControl.start();
  2. 编写接收事件函数
    首先过滤有效负载长度不正确的数据
    然后给有效负载的数据起个别名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 - 点对点通信相关推荐

  1. TinyOS下TOSSIM仿真

    TOSSIM仿真实现过程如下所示: 1.进入cygwin应用程序,进入目录 c:/cygwin/opt/tinyos-1.x/apps/TestTinyViz (最后一级的目录为应用程序,自己可以选择 ...

  2. Powerup tinyos接口实现

    // tos启动时点亮Led module PowerupC @safe() { // 使用Boot接口,Boot接口中只有一个事件booted,模块使用接口时,要实现接口中的事件 // 根据提供接口 ...

  3. node.js当中net模块的简单应用(基于控制台的点对点通信)

    我们可以使用node.js当中内置的net模块来创建socket服务端和socket客户端,实现一个简单的基于控制台的点对点通信. 一.利用net模块建立socket客户端 1.引包 const ne ...

  4. 安装TinyOS需要六个步骤

    2019独角兽企业重金招聘Python工程师标准>>> 安装TinyOS需要六个步骤 安装TinyOS需要六个步骤. 1.Installing a Java 1.5 JDK.     ...

  5. 嵌入式系统TinyOS学习资源

    2019独角兽企业重金招聘Python工程师标准>>> 本文总结了有关TinyOS学习的资源,以便查找使用. 目录 [隐藏] 1 TinyOS官方资源 2 WSN相关实验室 3 Ti ...

  6. 数据链路层点对点通信

    点对点通信 1.当主机H1向主机H2发送数据时,从协议的层次看,数据进入路由器后要先从物理层上升到网络层,在转发表中找到下一跳的地址后,再下到物理层转发出去. 点对点信道的数据链路层在进行通信时的主要 ...

  7. tinyos环境安装

    我用的是XP,第一步,我先在TINYOS的网站登记下载TINYOS安装包tinyos-1.1.0-1is.exe,你填写完 http://webs.cs.berkeley.edu/users/user ...

  8. TinyOS总体介绍

    TinyOS 体系结构图 TinyOS 硬件抽象层 TinyOS 引入了三层的硬件抽象结构: 硬件表示层(HPL) .硬件适应层(HAL).硬件接口层(HIL) HPL: 直 接对硬件资源进行访问,隐 ...

  9. TinyOS平台下一些代码的分析

     (一)数据采集模块 底层-->高层 SHT->SHTData--> SensorCollection-->AtoSensorCollection-->ANTTree ...

最新文章

  1. scipy.cluster.vq.kmeans的使用
  2. 解读:数据科学、机器学习和AI的区别
  3. windows下mongodb配置
  4. git push everything up to date问题解决
  5. UA MATH567 高维统计专题1 稀疏信号及其恢复3 Coherence与RIP简介
  6. 我的世界梦之边缘5服务器在维护吗,8月5日服务器例行维护公告(已完成)
  7. 电脑编程教学_2020太原数控车床电脑编程一对一实操教学不限学时
  8. c语言中如何取消最后一个空格,新人提问:如何将输出时每行最后一个空格删除...
  9. oracle获取日期中日,关于ORACLE ERP中日记帐的借、贷对应的问题
  10. Spring父子上下文(WebApplicationContext)(防止事务失效)
  11. linux 小红伞使用手册,安装LINUX下小红伞图文教程.pdf
  12. 统计推断—参数估计—点估计、区间估计、t分布、Z分布
  13. sql server服务器 性能,初涉SQL Server性能问题(1/4):服务器概况
  14. 免费领7天腾讯视频VIP/优酷会员!
  15. 南京java架构师工资_java架构师工资一般是多少?怎么提升才能获得高薪?
  16. Linux:命令 执行操作符
  17. 我的世界java版刷雪球机,我的世界手机版怎么刷雪球 无限刷雪球机
  18. 计算机考研零基础英语怎么复习,英语零基础怎么考研 上岸学姐来教你
  19. 乐山市计算机学校的董事长是,乐山市计算机学校庆祝建校25周年
  20. 设置QTableView的内容自动换行(2)

热门文章

  1. three.js之模型
  2. centos7 Redis单机多节点集群部署
  3. 吴军的谷歌方法论|第009封信|上帝喜欢笨人(上)
  4. [docker]三、docker理论概念(镜像、仓库、容器),用docker运行nginx来搭建一个属于自己网站。查看进程监听哪个端口的命令
  5. z370对应的服务器芯片,8代酷睿绝配!Intel Z370芯片组主板评测:必备马甲
  6. 主谓宾定状补口诀及练习题
  7. 计算机电缆铠装电缆护套管,电缆护套管常用型号介绍
  8. c语言void* arg,求教!!!void *(*process) (void *arg);
  9. RPC304A POE系统四通道PSE控制芯片,POE Controller,PSE Controller ,主要PIN IP804/IP808,TPS28361等芯片
  10. java list定义和初始化_在 Java 中初始化 List 的五种方法