查看: 1913|回复: 0
打印 上一主题 下一主题

TinyOS学习笔记11-节点与计算机利用串口通信2-BaseStation

[复制链接]
跳转到指定楼层
沙发
发表于 2015-3-25 17:08:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
节点与计算机利用串口通信2-BaseStation

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 = &uartQueueBufs;  //将buffer中的每一个赋给指针
    uartIn = uartOut = 0;   //输入输出都为0
    uartBusy = FALSE;      //串口不忙
    uartFull = TRUE;       //数据已满

    //同理设置radio
    for (i = 0; i < RADIO_QUEUE_LEN; i++)
      radioQueue = &radioQueueBufs;
    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();
  }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表