节点与计算机利用串口通信2-BaseStation

BaseStation的功能是实现一个中转的功能,将收到的节点信息发送给计算机,将收到的计算机的信息广播给其他的节点。

从安装BlinkToRadio的两个节点选择一个安装Basestation,对于基站的节点来说,LED0s闪烁:发送一个数据包到其他节点。LED1闪烁:接收到数据包,发送一个数据包到串口。LED2闪烁:丢失一个数据包(接收的速度大于发送的速度)。

下面对BaseStationP.nc的代码进行分析:
//需要用到发送信息的数据包和串口
#include "AM.h"       
#include "Serial.h"

module BaseStationP @safe() {
  uses {
    interface Boot;//启动系统                       
    interface SplitControl as SerialControl; //串口控制
    interface SplitControl as RadioControl;  //radio控制

    //向串口发送数据的设置am_id_t id,指定发送接收的am数据id
    interface AMSend as UartSend[am_id_t id];
    interface Receive as UartReceive[am_id_t id];
    interface Packet as UartPacket;
    interface AMPacket as UartAMPacket;
    
    //向radio发送数据的设置
    interface AMSend as RadioSend[am_id_t id];
    interface Receive as RadioReceive[am_id_t id];
    interface Receive as RadioSnoop[am_id_t id]; //嗅探
    interface Packet as RadioPacket;
    interface AMPacket as RadioAMPacket;

    //Led灯设置
    interface Leds;
  }
}

implementation
{
//设置序列的长度
  enum {
    UART_QUEUE_LEN = 12,
    RADIO_QUEUE_LEN = 12,
  };

  //串口设置
  message_t  uartQueueBufs[UART_QUEUE_LEN];//数据Buffer
  message_t  * ONE_NOK uartQueue[UART_QUEUE_LEN]; //??????
  uint8_t    uartIn, uartOut;  //???????????
  bool       uartBusy, uartFull;//串口状态
 
  //radio设置
  message_t  radioQueueBufs[RADIO_QUEUE_LEN];//buffer
  message_t  * ONE_NOK radioQueue[RADIO_QUEUE_LEN];
  uint8_t    radioIn, radioOut;   //????
  bool       radioBusy, radioFull;//radio状态

  //声明
  task void uartSendTask();//串口发送
  task void radioSendTask();//radio发送

  //丢失数据包led2闪烁
  void dropBlink() {
    call Leds.led2Toggle();
  }

 //失败,led2闪烁
  void failBlink() {
    call Leds.led2Toggle();
  }

  //启动
  event void Boot.booted() {
    uint8_t i;

    for (i = 0; i < UART_QUEUE_LEN; i++)
      uartQueue[i] = &uartQueueBufs[i];  //将buffer中的每一个赋给指针
    uartIn = uartOut = 0;   //输入输出都为0
    uartBusy = FALSE;      //串口不忙
    uartFull = TRUE;       //数据已满

    //同理设置radio
    for (i = 0; i < RADIO_QUEUE_LEN; i++)
      radioQueue[i] = &radioQueueBufs[i];
    radioIn = radioOut = 0;
    radioBusy = FALSE;
    radioFull = TRUE;

    call RadioControl.start(); //启动radio
    call SerialControl.start();//启动串口
  }

  event void RadioControl.startDone(error_t error) {
    if (error == SUCCESS) {
      radioFull = FALSE;  //启动成功,radio数据不满
    }
  }

  event void SerialControl.startDone(error_t error) {
    if (error == SUCCESS) {
      uartFull = FALSE;  //启动成功,serial数据不满
    }
  }

  event void SerialControl.stopDone(error_t error) {}
  event void RadioControl.stopDone(error_t error) {}

  uint8_t count = 0;   //计数

 
  message_t* ONE receive(message_t* ONE msg, void* payload, uint8_t len);
 
  //radio嗅探接收数据
  event message_t *RadioSnoop.receive[am_id_t id](message_t *msg,
                            void *payload,
                            uint8_t len) {
    return receive(msg, payload, len);
  }
 
  //radio接收数据
  event message_t *RadioReceive.receive[am_id_t id](message_t *msg,
                            void *payload,
                            uint8_t len) {
    return receive(msg, payload, len);
  }

  //接收数据
  message_t* receive(message_t *msg, void *payload, uint8_t len) {
    message_t *ret = msg; //整个数据

    //原子操作,不可被打断
    atomic {
      if (!uartFull)//串口未满
    {
      ret = uartQueue[uartIn];//ret指向输入
      uartQueue[uartIn] = msg;//msg进入序列

      uartIn = (uartIn + 1) % UART_QUEUE_LEN; //uarIn指向下一个
    
      if (uartIn == uartOut) //入==出,串口序列的数据已满
        uartFull = TRUE;

      if (!uartBusy) //串口不忙,则发送数据
        {
          post uartSendTask(); //发送操作
          uartBusy = TRUE;     //串口变忙
        }
    }
      else
    dropBlink();//串口已满,数据丢失
    }
    
    return ret;
  }

  uint8_t tmpLen;
 
  //向串口发送收到的数据
  task void uartSendTask() {
    uint8_t len;
    am_id_t id;
    am_addr_t addr, src;
    message_t* msg;
    //将所有数据发送完毕
    atomic
      if (uartIn == uartOut && !uartFull)
    {
      uartBusy = FALSE;
      return;
    }

    msg = uartQueue[uartOut]; //待发送的数据
    //从radio的msg数据包中获取每一个参数
    tmpLen = len = call RadioPacket.payloadLength(msg);
    id = call RadioAMPacket.type(msg);
    addr = call RadioAMPacket.destination(msg);
    src = call RadioAMPacket.source(msg);
    call UartPacket.clear(msg);//清空串口数据包
    call UartAMPacket.setSource(msg, src);//设置数据
    
    //发送数据给串口,成功led1闪烁,寻找sendDone
    if (call UartSend.send[id](addr, uartQueue[uartOut], len) == SUCCESS)
      call Leds.led1Toggle();
    else
      {
    failBlink();//发送失败,继续发送
    post uartSendTask();
      }
  }

  event void UartSend.sendDone[am_id_t id](message_t* msg, error_t error) {
    if (error != SUCCESS)
      failBlink();//发送失败
    else
      atomic  //发送成功
    if (msg == uartQueue[uartOut]) //发送的数据是所要发的数据
      {
        if (++uartOut >= UART_QUEUE_LEN) //输入指向下一个的超过了长度12
          uartOut = 0; //从0开始
        if (uartFull)  //如果满的话,设置为没满
          uartFull = FALSE;
      }
    post uartSendTask(); //继续发送其他数据
  }

  //串口接收数据
  event message_t *UartReceive.receive[am_id_t id](message_t *msg,
                           void *payload,
                           uint8_t len) {
    message_t *ret = msg;
    bool reflectToken = FALSE;

    //串口接收到数据发送给radio
    atomic
      if (!radioFull)
    {
      reflectToken = TRUE;
      ret = radioQueue[radioIn];
      radioQueue[radioIn] = msg;
      if (++radioIn >= RADIO_QUEUE_LEN)
        radioIn = 0;
      if (radioIn == radioOut)
        radioFull = TRUE;

      if (!radioBusy)
        {
          post radioSendTask();
          radioBusy = TRUE;
        }
    }
      else
    dropBlink(); //丢失数据

    if (reflectToken) {
      //call UartTokenReceive.ReflectToken(Token);
    }
    
    return ret;
  }

  task void radioSendTask() {
    uint8_t len;
    am_id_t id;
    am_addr_t addr,source;
    message_t* msg;
    
    atomic
      if (radioIn == radioOut && !radioFull)
    {
      radioBusy = FALSE;
      return;
    }

    msg = radioQueue[radioOut];
    len = call UartPacket.payloadLength(msg);
    addr = call UartAMPacket.destination(msg);
    source = call UartAMPacket.source(msg);
    id = call UartAMPacket.type(msg);

    call RadioPacket.clear(msg);
    call RadioAMPacket.setSource(msg, source);
    
    if (call RadioSend.send[id](addr, msg, len) == SUCCESS)
      call Leds.led0Toggle();
    else
      {
    failBlink();
    post radioSendTask();
      }
  }

  event void RadioSend.sendDone[am_id_t id](message_t* msg, error_t error) {
    if (error != SUCCESS)
      failBlink();
    else
      atomic
    if (msg == radioQueue[radioOut])
      {
        if (++radioOut >= RADIO_QUEUE_LEN)
          radioOut = 0;
        if (radioFull)
          radioFull = FALSE;
      }
    
    post radioSendTask();
  }

}

节点与计算机利用串口通信2-数据包分析 1号节点和2号节点运行BlinkToRadio程序,BaseSation中snoop的作用就是即使1号发送数据指定目的地为2号节点,利用snoop也可以收到数据 使用命令,对串口进行监听 root@ubuntu:~# java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:telosb serial@/dev/ttyUSB0:115200: resynchronising 00 FF FF 00 01 04 00 06 00 01 01 E2 00 FF FF 00 02 04 00 06 00 02 01 B9 00 FF FF 00 01 04 00 06 00 01 01 E3 00 FF FF 00 02 04 00 06 00 02 01 BA 串口接收到的数据如上所示,其数据包的含义为: 00 FF FF 00 01 04 00 06 00 01 01 E2 00(数据包包头) FF FF(目的地,广播FFFF为广播地址) 00 01(源地址,该信息为1号节点发送) 04(数据长度,4个字节) 00 (组号) 06(AM数据包的类型) 负载部分(用户定义) 00 01 (发送节点id)01 E2(计数,2字节) 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值