| 
 | 
 
节点与计算机利用串口通信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(); 
  } 
} 
 |   
 
 
 
 |