节点与节点之间无线通信的组成原理与具体实现(实验篇,含完整代码)_物联网挑战赛

目录

TinyOS下的CC2420编程

 编程语言介绍

代码实现

Makefile

RadioCountToLeds.h

RadioCountToLedsAppC.nc

RadioCountToLedsC.nc

头文件

 implementation

implementation



如果大家对节点与节点之间无线通信的底层逻辑与原理有需求的话,可以看看笔者的这篇文章,相信能然让你更好的理解无线通信的实现(因为合在一起太长了,所以分成两篇,也更有目的性一些😁😁):节点与节点之间的无线通信的组成原理与具体实现(原理篇,含组件解析)_物联网挑战赛_勾栏听曲_0的博客-CSDN博客


TinyOS下的CC2420编程

RadioCountToLedsC组件图如下图所示,我们可以看到要实现RadioCountToLedsC相关功能,需要使用到MainC,AMReceiverC,AMSenderC,ActiveMessageC,LedsC,TimerMilliC组件,虚线框表明该组件使用的是虚拟资源。

 编程语言介绍

本次实验所用的编程语言为nesC,在本篇里笔者就不过多赘述啦,感兴趣的小伙伴可以去这篇里面看看哦。CTP协议的组成原理与具体实现(实验篇,含代码)_物联网竞赛挑战赛_勾栏听曲_0的博客-CSDN博客

代码实现

我们直接进入正题,看代码来理解节点与节点之间无线通信的具体实现。 

一下代码的效果是,通过无线通信完成每个节点LED灯都按同一种频率闪烁。

Makefile

Makefile文件,就是定义代码的书写规则

CFLAGS += -DCC2420_DEF_CHANNEL=14,  这句话是非常重要的,是无线通信里的频段设置

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;
        }
    }
}

如果有帮助的话,欢迎点赞收藏哦~🤩,有不同见解或更好的观点也可以在评论区留言,也可以笔者点点关注,互通有无,互相进步。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在ROS2C++节点通信主要通过ROS2提供的rclcpp库实现。rclcpp库是一个ROS2的C++客户端库,它提供了创建ROS2节点、发布和订阅话题、服务调用等功能。 下面是一个简单的例子,演示如何使用rclcpp库在C++节点之间进行通信: 1. 首先,我们需要包必要的头文件: ```cpp #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" ``` 2. 创建一个发布者: ```cpp auto publisher = node->create_publisher<std_msgs::msg::String>("my_topic", 10); ``` 其,`node`是一个`rclcpp::Node`对象,`std_msgs::msg::String`是消息类型,`my_topic`是话题名称,`10`是话题队列长度。 3. 创建一个消息: ```cpp auto message = std_msgs::msg::String(); message.data = "Hello, world!"; ``` 4. 发布消息: ```cpp publisher->publish(message); ``` 5. 创建一个订阅者: ```cpp auto subscription = node->create_subscription<std_msgs::msg::String>("my_topic", 10, [](const std_msgs::msg::String::SharedPtr msg) { RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "I heard: '%s'", msg->data.c_str()); }); ``` 其,`std_msgs::msg::String`是消息类型,`my_topic`是话题名称,`10`是话题队列长度,`[](const std_msgs::msg::String::SharedPtr msg) {...}`是消息回调函数,用于处理接收到的消息。 6. 运行节点: ```cpp rclcpp::spin(node); ``` 以上是一个简单的例子,演示了如何在C++节点之间使用ROS2进行通信。在实际应用,我们可以根据需要创建多个发布者和订阅者,以实现节点之间的复杂通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勾栏听曲_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值