天天看点

实验二 串口与节点通信(下)

实验日期:2012年12月13日

实验内容:上位机通过串口将数据发送到节点,节点将接收到的数据反馈给上位机

实验环境:基于Linux下的TinyOS  Telosb节点

接收到PC发出的数据后,通过定时器的方式反馈收到的数据,同时LED0闪烁。

新添加TimerMilliC组件和SerialAMsender组件。SerialAMsender组件主要完成反馈数据至串口。

实验二 串口与节点通信(下)

(1)发送数据方法

发送数据的思路比较简单,可以简单概况为:打包à发送

具体地,步骤如下:

a)定义message_t变量,如message_t ToUartMsg;

b)定义有效数据数据段(即载荷区),如

typedef nx_struct ReturnMsg

{

    nx_uint16_t testnum;

}ReturnMsg;//定义结构体,其中testnum是有效数据段中占两个字节的数据

c)定义指向payload段指针(关键)

通过Packet接口调用getpayload函数获取payload段地址,需要message消息(即message_t)变量的地址和有效数据段字节长度两个参数,如:

ReturnMsg *btrpkt=(ReturnMsg *)(call UartPacket.getPayload(&ToUartMsg,sizeof(ReturnMsg)));//UartPacket为Packet接口

d)装载载荷区

给有效数据段对应的结构体中的变量赋值,如:

btrpkt->testnum=temp16;//temp16是uint16_t类型数据

e)发送数据

调用AMSend接口中send函数即可将数据发送到串口,如:

call UartSend.send(0xff,&ToUartMsg,sizeof(ReturnMsg);//由于是发送到串口,故第一个AM地址参数可忽略(任意)。

f)相应发送数据完毕的函数(sendDone函数)

event void UatSend.sendDone(message_t *msg,error_t error)

【测试】

1.向串口写入数据:java net.tinyos.tools.Send 00 ff ff 00 09 00 89 07 01 03

LED0灯没有马上点亮,而是隔3秒中左右开始闪烁

2、侦听串口:java net.tinyos.tools.Listen –comm [email protected]/dev/ttyUSB0:telos

Linux终端反馈数据:00 00 FF 00 00 02 00 06 01 03

Xgcom软件反馈数据:

1)无校验:7E 45 00 00 FF00 00 02 00 06 01 03 E5 AC 7E

2)奇校验:7E 45 80 00 FF00 00 02 00 06 01 03 E5 AC BF

3)偶检验:7E 45 80 00 FF 00 00 02 00 06 01 03 E5 AC BF

3、串口数据包格式分析:

在TinyOS 2.x的串口协议栈里,各协议字段分别和特定的组件有关,其具体格式如下图所示:

F P S D Payload CR F

串口协议包的格式

F:帧字节,表示数据包开始,与HdlcTranslateC组件有关

P:协议字节,与SerialP组件有关

S:序号字节,与SerialP组件有关

D:包格式的分派字节,与SerialDispatcherC组件有关

Payload:数据包的有效载荷区,与SerialDispatcherC组件有关

CR:两个字节的CRC校验码,校验从S到Payload,与SerialP组件有关

F:帧字节,表示数据包接收,与HdlcTranslate组件有关

注意:这里的Payload不是AM消息里的Payload,二是串口协议包中的Payload。

有效载荷区是SerialDispatcherC组件读入的连续数据包,包含串口主动消息的包头。需要注意的是,从P到CR的任何字节如果等于0x7e或0x7d,将会相应的被转换为0x7d 0x5e与0x7d 0x5e

               7E 4500 00FF 00 00 02 00 06 01 03E5 AC 7E

                 F |P | S |  D|                Payload             |  CR     |F

【完整代码】

PC2NodeC.nc文件:

module PC2NodeC
{
   uses interface SplitControl as SerialControl;

   uses interface Packet as UartPacket;
   uses interface AMSend as UartSend;
   uses interface Receive as UartReceive[am_id_t id];
   uses interface Leds;
   uses interface Boot;
   uses interface Timer<TMilli> as Timer0;
}
implementation
{
    typedef nx_struct RealMsg
     {
         nx_uint16_t LedCount;
      }RealMsg;

   message_t ToUartMsg;
  typedef nx_struct ReturnMsg
      {
         nx_uint16_t testnum;
      }ReturnMsg;
  
   uint16_t temp16;
  

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

     }
  
    event void SerialControl.startDone(error_t error)
       {
        }
     event void SerialControl.stopDone(error_t error){}
 //接收到从PC发过来的数据
  event message_t *UartReceive.receive[am_id_t id](message_t *msg,void *payload,uint8_t len)
{
  if(len==sizeof(RealMsg))
  {
    RealMsg *btrpkt=(RealMsg*)payload;
    temp16=btrpkt->LedCount;
    call Timer0.startPeriodic(1000);
   }
  return msg; 
}


event void Timer0.fired()
{
  ReturnMsg *btrpkt2=(ReturnMsg*)(call UartPacket.getPayload(&ToUartMsg,sizeof(ReturnMsg)));
 
  btrpkt2 -> testnum = temp16;
   if(call UartSend.send(0xff,&ToUartMsg,sizeof(ReturnMsg))==SUCCESS)
   { 
      call Leds.led0Toggle();

    }


}

event void UartSend.sendDone(message_t *msg, error_t error) {}
}

PC2NodeAppC.nc文件

configuration PC2NodeAppC
{
}
implementation
{
  //components
  components PC2NodeC,MainC,LedsC;
  components SerialActiveMessageC as SeriAcMsg;
  components new SerialAMSenderC(6);
  components new TimerMilliC() as T0;
 

  //Links
  PC2NodeC -> SeriAcMsg.Packet;
 
  PC2NodeC.UartSend -> SerialAMSenderC.AMSend;
  PC2NodeC -> SeriAcMsg.Receive;
  PC2NodeC -> MainC.Boot;
  PC2NodeC.SerialControl -> SeriAcMsg;//有疑问???因为SerialControl 是由PC2NodeC提供的
  PC2NodeC -> LedsC.Leds;
  PC2NodeC.Timer0 -> T0;
}


           

继续阅读