TinyOS 2.x 入门教程 - 图文 联系客服

发布时间 : 星期日 文章TinyOS 2.x 入门教程 - 图文更新完毕开始阅读24b7b0a2a1c7aa00b42acb33

TinyOS Programming

第6章 TinyOS串口编程

串口是PC跟节点通信的最重要途径之一,是TinyOS编程中必须掌握的一个方面。下面以实例的方式了解一下关于串口的编程。

6.1 TestSerial应用程序

节点上的程序在文件夹:tinyos-2.x\\apps\\tests\\TestSerial中。对于这个源文件中,有TestSerialAppC.nc TestSerialC.nc TestSerial.h TestSerial.java,这里,.nc的源文件写的就是telosb节点向串口发msg和从串口接收msg的nesc程序。

此程序是一个简单的TinyOS的java工具的应用,它可以通过PC机的串口与节点进行通信。Java程序以1HZ的频率发送数据包,在这个数据包中有一个递增的计数器。当节点收到这个计数数据包时,将会通过不同灯的闪烁对当前的状态进行显示(其灯的闪烁效果和

RadioCountToLeds类似,只是本程序是从串口接收的数据)。同样的,节点也以1HZ的速率向串口发送数据包,当计算机从串口接收到数据,将会把其显示出来。

首先,让我们略为浏览一下TestSerial模块的代码:

#include \#include \ module TestSerialC { uses { interface SplitControl as Control; interface Leds; interface Boot; interface Receive; interface AMSend; interface Timer as MilliTimer; interface Packet;

Page 34 of 94

TinyOS Programming

} }

implementation {

message_t packet;

bool locked = FALSE; uint16_t counter = 0;

event void Boot.booted() { call Control.start(); }

event void MilliTimer.fired() { counter++; if (locked) { return; }

else {

test_serial_msg_t* rcm = (test_serial_msg_t*)call Packet.getPayload(&packet, sizeof(test_serial_msg_t));

if (rcm == NULL) {return;}

if (call Packet.maxPayloadLength() < sizeof(test_serial_msg_t)) { return; }

rcm->counter = counter;

if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS) { locked = TRUE; } } }

event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) {

if (len != sizeof(test_serial_msg_t)) {return bufPtr;} else {

test_serial_msg_t* rcm = (test_serial_msg_t*)payload; if (rcm->counter & 0x1) { call Leds.led0On(); }

else { call Leds.led0Off(); }

if (rcm->counter & 0x2) { call Leds.led1On(); }

else { call Leds.led1Off(); }

if (rcm->counter & 0x4) { call Leds.led2On();

Page 35 of 94

TinyOS Programming

}

else { call Leds.led2Off(); }

return bufPtr; } }

event void AMSend.sendDone(message_t* bufPtr, error_t error) { if (&packet == bufPtr) { locked = FALSE; } }

event void Control.startDone(error_t err) { if (err == SUCCESS) {

call MilliTimer.startPeriodic(1000); } }

event void Control.stopDone(error_t err) {} }

1)首先需要检查PC是否能够和节点通过串口正常的通信,大多数的节点都有类似的接口。例如mica类型的节点可以直接与串口进行通信,telos节点也有自己的与串口通信的接口,但它是基于USB的。我们可以通过如下语句对串口进行监听:

$ java net.tinyos.tools.Listen -comm serial@COM1:telos 2)将TestSerial代码成功下载到节点上后,其主要的应用是将会在每秒向串口发送数据包的同时接收从串口发送来的数据包,并通过LEDs的亮灭将数据包的序列号显示出来。这里由于telosb节点向串口发送msg,我们无法显示,所以这里有一个.java程序,它能自动的生成TestSerialMsg.java 这个java程序获得串口与telosb节点通信的信息,进行解析然后输出到终端。但要实现互相收发数据则需要在PC上创建一个伪节点,通过它与真实节点使用串口进行通信。

在目录下输入: $ java TestSerial 若收到如下错误: The java class is not found: TestSerial 则可能是没有编译java程序或者是在安装的时候没有将java的路径添加到CLASSPATH中。 3)我们可以通过工具对串口接收到的数据进行显示,也可以根据节点占用的端口号和相应的频率对其进行监听:

Platform Speed (baud) telos 115200 telosb 115200 tmote 115200 micaz 57600 mica2 57600 mica2dot 19200 eyes 115200 intelmote2 115200 具体使用方式如下:

Page 36 of 94

TinyOS Programming

export MOTECOM=serial@COM3:57600 # explicit mica2 baud rate 4)从上面的代码可以看出,首先声明了接口StdControl和AMSend,具体声明语句如下: interface SplitControl as Control; interface AMSend; 其中SplitControl用来初始化串口,AMSend则用来向串口发送数据。

5)接下来是串口组件的初始化和启动及停止操作,在完成相应动作后,就是数据的传递读写操作了。在TestSerialAppC.nc中有这样一条语句:components SerialActiveMessageC as AM声明是使用串口进行数据操作。 TinyOS串口写操作是分段操作的,亦即先调用一个写命令(send命令),等到完成后以事件形式(sendDone事件)通知调用者。

先进行一些数据的填充,填充完毕后,语句:

if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS) { locked = TRUE; } 通知下层(数据链路层)发送数据,如果发送命令被下层组件接收,发送完毕后下面语句通知调用者已经发送完毕,否则返回FAIL,也不触发sendDone事件: event void AMSend.sendDone(message_t* bufPtr, error_t error) { if (&packet == bufPtr) { locked = FALSE; } } 写操作只需这些语句了。当然,有一点需要提醒的是,发送的数据是message_t类型的(详见tinyos-2.x\\tos\\types 下的AM.h头文件),你可以往该结构体的data域直接填充数据,一般是程序员自己定义的一个结构体,然后获取data域的地址赋给自定义的结构体变量,再填充该结构体。

6)配件的配置程序如下: #include \ configuration TestSerialAppC {} implementation { components TestSerialC as App, LedsC, MainC; components SerialActiveMessageC as AM; components new TimerMilliC(); App.Boot -> MainC.Boot; App.Control -> AM; App.Receive -> AM.Receive[AM_TEST_SERIAL_MSG]; App.AMSend -> AM.AMSend[AM_TEST_SERIAL_MSG]; App.Leds -> LedsC; App.MilliTimer -> TimerMilliC; App.Packet -> AM; } 7)在正确设置了PORT号和SPEED后,运行TestSerial程序,可以看到如下输出: Sending packet 1 Received packet sequence number 4 Sending packet 2 Received packet sequence number 5 Sending packet 3

Page 37 of 94