您的位置:首页 > 其它

CC2538之TinyOS例程实验:7-blip实验 开始zigbee通信

2016-01-05 10:42 363 查看
前面的6部实验为基本的驱动外设实验,是学习使用基础,实验设备只需要一个cc2538cb节点;从这一部开始实验开始需要两个cc2538cb节点,开始zigbee的无线通信;

此次例程为TinyOS的核心协议栈BLIP,现在的版本是BLIP2.0;大家可以去TinyOS的官网搜索BLIP查看介绍;

如何理解BLIP呢?他的存在意义是什么?我们清楚zigbee到6lowpan的升级,zigbee芯片厂商并没有在硬件部分做6lowpan的压缩解压,这些的完成是纯软件实现的,也就需要一个zigbee(IEEE802.15.4)到6lowpan的转换桥梁,BLIP最重要的功能就是如此;

例程目录tinyos-main-release_tinyos_2_1_2\apps\cc2538_Test\blip\TestLinkLocal

例程为TinyOS的官方固件的代码,以后大家使用会发现我的这些例程基本不修改官方的例程,方便大家的兼容学习;

Makefile文件:

COMPONENT=TestLinkLocalAppC
CFLAGS += -DUSE_TIMER_HANDLER
#CFLAGS += -DUSE_UART_HANDLER
CFLAGS += -DUSE_RF_HANDLER
CFLAGS += -DNOT_USE_PRINTFC_BUT_USE_PRINT
PFLAGS += -DIN6_PREFIX=\"fec0::\"

include $(MAKERULES)
CFLAGS += -DIN6_NO_GLOBAL -DLIB6LOWPAN_HC_VERSION=-1
CFLAGS += -DPRINTFUART_ENABLED


BLIP分为两种模式:短地址(16bit)和IEEE地址(8bytes/64bit)模式,默认采用短地址模式;注意如果后期的实验如边界路由,RPL,CoAP实验;通信都需要选择同一种模式;默认是短地址;大家在完成基本的通讯后可以修改Makefile,尝试IEEE地址模式;具体参考TinyOS官网BLIP文档;

TestLinkLocalAppC.nc文件:

/** Test the link-local communication in the blip stack
 */
configuration TestLinkLocalAppC {

} implementation {
  components MainC, LedsC;
  components TestLinkLocalC;
  components IPStackC;
  components new TimerMilliC();
  components new UdpSocketC();

  TestLinkLocalC.Boot -> MainC;
  TestLinkLocalC.SplitControl -> IPStackC;
  TestLinkLocalC.Sock -> UdpSocketC;
  TestLinkLocalC.Timer -> TimerMilliC;
  TestLinkLocalC.Leds -> LedsC;

  components StaticIPAddressTosIdC; // Use TOS_NODE_ID in address
  //components StaticIPAddressC; // Use LocalIeee154 in address
}


TestLinkLocalC.nc文件:

/*******************************************************************
 *实验5----zigbee blip实验
 *节点需求数 >= 2
 *编译命令make cc2538cb blip id.xx (xx为1~65533)
 ********************************************************************/
#include "blip_printf.h"
#include <lib6lowpan/ip.h>

module TestLinkLocalC {
  uses {
    interface Boot;
    interface SplitControl;
    interface UDP as Sock;
    interface Timer<TMilli>;
    interface Leds;
  }
} implementation {
  nx_struct echo_state {
    nx_int8_t cmd;
    nx_uint32_t seqno;
  } m_data;

  enum {
    SVC_PORT = 10210,
    CMD_ECHO = 1,
    CMD_REPLY = 2,
  };
   
  /***************************************************
  *启动事件
  ****************************************************/
  event void Boot.booted() {
    call SplitControl.start();
    m_data.seqno = 0;
  }

  event void SplitControl.startDone(error_t e) {
    /**开启约2秒的周期性定时器(单位毫秒)  Timer**/  
    call Timer.startPeriodic(2048);
    /**端口绑定************************************/
    call Sock.bind(SVC_PORT);
  }

  event void SplitControl.stopDone(error_t e) {}

  /***************************************************
  *Timer定时时间到事件
  ****************************************************/
  event void Timer.fired() {
    struct sockaddr_in6 dest;

    inet_pton6("ff02::1", &dest.sin6_addr);
    dest.sin6_port = htons(SVC_PORT);
    
    m_data.cmd = CMD_ECHO;
    m_data.seqno ++;
    /***启动zigbee发送,可以自己修改发送内容和长度*****/
    call Sock.sendto(&dest, &m_data, sizeof(m_data));
    call Leds.led0Toggle();
  }
  /***************************************************
  *接收事件
  ****************************************************/
  event void Sock.recvfrom(struct sockaddr_in6 *src, void *payload,                                                               
                           uint16_t len, struct ip6_metadata *meta) {
    nx_struct echo_state *cmd = payload;
    printf("TestLinkLocalC: recv from: ");
    printf_in6addr(&src->sin6_addr);
    printf("\n");

    if (cmd->cmd == CMD_ECHO) {
      cmd->cmd = CMD_REPLY;
      call Sock.sendto(src, payload, len);
      call Leds.led1Toggle();
    } else {
      printf("TestLinkLocalC: reply seqno: %li\n", cmd->seqno);
      call Leds.led2Toggle();
    }
  }
}


如果大家对nesC语法还是不熟悉,可以先去看看前6部实验帖子;

nx_struct---等价于struct{}__attribute__
((packed)) ;是为了兼容平台从8位单片机到32位arm的结构体对齐问题;常常使用的关键字;大家可以使用printf例程


测试一下一个struct里面有unsigned char/long成员后的sizeof打印和nx_struct的sizeof的区别;回忆2530的TinyOS代码,nesC编译成app.c后调用perl脚本对app.c进行转换,其中就必须注释掉了nx_struct生成的__attribute__
((packed)) ;


call SplitControl.start();这句代码大家可以使用yeti2插件图形化组件去查看代码(见视频),手动的分析代码;或者生成的app.c去查看,完成了什么,BLIP的地址初始化;



这个例程有视频,没记错应该是第十四部视频;

SplitControl.startDone事件开启一个2.048秒的周期性定时器;绑定端口,看到这里大家肯定很熟悉了,Socket的写法



inet_pton6(...)函数,说明一下对于TinyOS我们清楚函数修饰是command,但是由于它支持C的所有特性,所以对于C函数的调用和C语言写法一样,不需要使用call关键字;

call Sock.sendto(&dest, &m_data, sizeof(m_data)); 核心发包部分,也是咱们可以去DIY的,可以DIY内容,接收方解析;比如LED控制,大家可以自己去写;或者和之前的例程结合一下咱们可以发送采集的片内温度,又或者将串口接收的数据发送,做一个聊天QQ;

例程本质在烧写两个节点完成通信,定义

CMD_ECHO = 1,

CMD_REPLY = 2,


发送方发送CMD_ECHO
,接收方解析后发送回CMD_REPLY ;例程简单,不做截图了;


需要注意编译命令从这一部开始因为是多节点的通信,我们需要make的时候添加options了,前六部的编译命令是make
cc2538cb


这个例程编译命令为make cc2538cb blip id.xx

如两个节点 我们可以make cc2538cb blip id.1烧写

make cc2538cb blip id.2烧写完成实验;



blip的make选项是通知nesC编译器使用blip栈;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: