TinyOS 2.x 入门教程 - 图文

更新时间:2024-06-07 09:42:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

TinyOS 2.x 编程入门教程

Version 1.0

2010/12/17

目录

前言 ........................................................................................................................................... 1 第1章 编程环境的建立 ....................................................................................................... 2

1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 2.1

安装JAVA 1.6 JDK ........................................................................................... 2 安装CWGWIN(WINDOW ONLY) .................................................................................. 2 安装编译器 ................................................................................................... 3 安装TINYOS工具 ............................................................................................ 3 设置环境变量 ................................................................................................ 4 安装 GRAPHVIZ ................................................................................................. 4 检测软件安装情况 .......................................................................................... 4 USB串口驱动下载及安装................................................................................... 5

第2章

NESC

TINYOS简介 .......................................................................................................... 7

语言简介 ................................................................................................ 7 组件(components) ........................................................... 7 并发模型 .................................................................. 11

2.1.1 2.1.2 2.2 2.3

常用MAKE命令简介 ........................................................................................ 12 应用举例:BLINK ---TINYOS编程的“HELLO WORLD”程序 ............................................. 12 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5

Blink配件 ................................................................ 13 BlinkC模块 ............................................................... 14 事件evenst和命令commands ................................................ 16 编译Blink应用程序 ........................................................ 17 安装Blink程序到Telosb节点并运行 ......................................... 17

2.4 2.5 3.1

下载程序出错故障排除 ................................................................................... 18 小结 ......................................................................................................... 20

第3章

3.1.1 3.1.2 3.2

3.2.1 3.2.2 3.3

3.3.1 3.3.2 3.4

3.4.1 3.4.2 3.5 4.1 4.2 5.1

TELOSB硬件平台常用可编程器件和对应的TINYOS组件介绍 ...................... 21

Telosb硬件平台上的Led器件展示 ........................................... 22 TinyOS中Led编程组件介绍 ................................................. 22 Telosb硬件平台上的传感器展示 ............................................. 23 TinyOS中传感器编程组件介绍 ............................................... 24 Telosb硬件平台上的串口展示 ............................................... 25 TinyOS中串口编程组件介绍 ................................................. 26 Telosb硬件平台上的Radio相关器件展示...................................... 26 TinyOS中Radio编程组件介绍 ............................................... 27

LED ........................................................................................................... 22

传感器 ...................................................................................................... 23

串口 ......................................................................................................... 25

RADIO ......................................................................................................... 26

小结 ......................................................................................................... 27 模块实现 ................................................................................................... 28 ADC .......................................................................................................... 30

第4章 用事件驱动方式从传感器获取数据 ..................................................................... 27

第5章 TINYOS任务及应用举例 .................................................................................... 32

任务的创建和调度 ........................................................................................ 32

5.2 5.3 6.1 6.2 6.3 6.4 6.5 6.6

举例:SENSETASK应用程序 ................................................................................ 33 小结 ......................................................................................................... 33

第6章 TINYOS串口编程 ................................................................................................ 34

TESTSERIAL应用程序 ....................................................................................... 34 串口助手:PC上显示从串口读取的数据 .............................................................. 38 TELOSB从串口读取数据 ................................................................................... 39 OSCILLOSCOPE应用程序——数据感知 .................................................................... 41 BASESTATION应用程序 ...................................................................................... 45 小结 ......................................................................................................... 51

附录1 TINYOS命名约定 ....................................................................................................... 52

附录2 NESC语言特有关键字 ............................................................................................... 54

TinyOS Programming

前言

随着传感器技术、微机电系统、现代网络、无线通信、低功耗等技术的飞速发展,推动了无线传感器网络 (WSN:wireless sensor network) 的产生和发展。无线传感器网络涉及IT领域的多种技术,成为目前IT领域的研究热点之一。无线传感器网络就是由部署在监测区域内大量的廉价微型传感器节点组成,通过无线通信方式形成一个多跳的自组织网络。

无线传感器网络所具有的众多类型的传感器,可探测包括地震、电磁、温度、湿度、噪声、光强度、压力、土壤成分、移动物体的大小、速度和方向等各种各样的现象。具有广阔应用前景,潜在的应用领域可归纳为:军事、航空、反恐、防暴、救灾、环境、医疗、保健、家居、城市管理等诸多领域。

传感器节点是一个微型的嵌入式系统,具有非常有限的硬件资源,需要操作系统能够高效地使用其仅有的内存、处理器和通信模块,且能够对各种特定应用提供最大的支持。

传感器节点有两个突出的特点。一是并发性密集,即可能存在多个需要同时执行的逻辑控制,这需要操作系统能够有效地满足这种发生频繁、并发程度高、执行过程比较短的控制逻辑流程;另一个特点是传感器节点模块化程度很高,要求操作系统能够很方便让应用程序方便地对硬件进行控制,且保证在不影响整体开销的情况下,应用程序中的各个部分能够比较方便地进行重新组合。美国加州大学伯克利分校针对无线传感器网络的特点研发了TinyOS操作系统,在科研机构的研究中应用比较广泛。

TinyOS是无线传感器网络中较为流行的操作系统,所用编程语言为nesC (network embedded system C),nesC语言由C语言扩展而来,意在把组件化、模块化思想和TinyOS基于事件驱动的执行模型结合起来。

目前在国内,关于TinyOS的资料并不多,而且很散,给各个方面的人员在使用TinyOS时造成了诸多不便,我们在使用TinyOS时积累了一些经验,在此希望能对大家有一定的帮助。

本教程所用硬件平台为Telosb,操作系统版本为TinyOS 2.x,nesC语言版本为1.3。主要内容的几乎覆盖Telosb硬件平台的所有常用可编程器件及TinyOS一些重要概念,内容不是很深入,适合没有接触过TinyOS的初学者,但就其对于Telosb硬件平台而言,是使用Telosb硬件平台的工作人员或爱好者不可多得的参考文档,并且在熟悉了此教程之后,读者朋友们可以很容易地转到其它硬件平台上去。

在范例的选择方面,本教程尽量选择了TinyOS自带的例子,方便读者测试。只有少数例子在TinyOS中没有,已编写了尽量简短的程序并在教程中展示了这些例子的完整代码。在讲解某些内容方面,特别是概念性的内容,我们借鉴了TinyOS官方公布的一些讲解方式、引用了部分内容及例子,以便尽可能准确传达TinyOS研发者的初衷。

最后,本教程要求读者均具有C语言编程的基础。因为nesC是C语言的扩展,在此教程不会讲解任何C编程方面的内容,如有读者未有C语言基础,请先学习C方面内容,以便可以进一步学习此教程涉及的内容。更加深入的内容及本教程使用到的工具会在“相关资源”列出,以方便大家进一步学习。

Page 1 of 94

TinyOS Programming

第1章 编程环境的建立

目前TinyOS支持两种平台:cygwin(windows)和Linux。下面介绍在这两种操作系统下TinyOS的安装步骤。

1.1 安装Java 1.6 JDK

(1) 下载JAVA JDK SE 6

http://java.sun.com 或

http://www.java.net/download/jdk6/6u10/promoted/b32/binaries/jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe

(2) 安装路径

[c:\\UCB\\Java\\jdk1.6.0_10\\] [c:\\UCB\\Java\\jre6\\]

(3) 设置环境变量

(a)CLASSPATH

[我的电脑]-[属性]-[高级]-[环境变量]-[系统变量]-[新建] 变量名:CLASSPATH

变量值:..;c:\\UCB\\Java\\jdk1.6.0_10\\bin;c:\\UCB\\Java\\jdk1.6.0_10\\lib\\tools.jar (b)Path

[我的电脑]-[属性]-[高级]-[环境变量]-[系统变量]-[编辑] 变量名:Path

变量值:c:\\UCB\\Java\\jdk1.6.0_10\\bin;c:\\UCB\\Java\\jdk1.6.0_10\\jre\\bin (c)JAVA_HOME

[我的电脑]-[属性]-[高级]-[环境变量]-[系统变量]-[新建] 变量名:JAVA_HOME

变量值:c:\\UCB\\Java\\jdk1.6.0_10 (OK)

1.2 安装cwgwin(window only)

(1) 从tinyos上下载Cygwin的兼容包

http://cone.informatik.uni-freiburg.de/people/aslam/cygwin-files.zip

(2) 解压到[c:\\cygwin-installationfiles] (3) 运行c:\\cygwin-installationfiles\\setup.exe

[下一步]-[Install from Local Directory]-[下一步]-[Root Directory输入c:\\UCB\\cygwin]-[下一

步]-[Local Package Directory输入c:\\cygwin-installationfiles]-[下一步]-[下一步]-[安装]-[完成]

(4) 运行[C:\\cygwin\\cygwin.bat]

Page 2 of 94

TinyOS Programming

图2.1 组件的原型

一个组件提供(provides)和使用(uses)接口。接口是访问组件的唯一途径,并且接口是具有双向性的。一个接口声明了一系列称之为命令 (command) 的函数,及一系列称之为事件 (event) 的函数,接口的提供者必须实现该接口声明的所有的命令,而接口的使用者则必须实现该接口声明的所有的事件。一个组件可以提供或使用多个接口,并且可以提供或使用同一个接口的多个实例。

(2)基于组件的模型

一个简单的基于组件的调用模型如图2.2所示。

Page 8 of 94

TinyOS Programming

图2.2 基于组件的模型

上层的应用调用TinyOS所提供的不同组件,而每个组件都会相应的提供自身的应用接口。实际上各个组件的实现还需要调用其下层的图中所示的模型类似于一个库(library),不同的组件(components)相当于库中的元素(objects),而接口(interfaces)相当于APIs。

(3)简单示例Blink

Blink示例的主要现象为通过对Timer的调用触发红、绿、黄三种颜色的灯的闪烁事件:

? Toggle Red LED @ 0.25 Hz ? Toggle Green LED @ 0.25 Hz ? Toggle Yellow LED @ 0.25 Hz

如右图所示,在Blink示例中只需要用 到以下三个组件:

? LEDs ? Timer ? Main

1、 接口

不同的组件提供自身相应的接口,应用程序则通过调用这些接口来实现对于更低层的组件和硬件的调用。例如在本例中的如下代码: {

uses interface Timer as Timer0; uses interface Timer as Timer1; uses interface Timer as Timer2; uses interface Leds; uses interface Boot; }

and you implement what you want to do in your program {

当Timer被触发的时候,所对应的灯闪烁; }

Page 9 of 94

TinyOS Programming

其中接口Timer是一个带参数的接口,它使用类型作为参数,接口中的类型参数被放在一对尖括号中,当串连提供者和使用者的接口带有类型参数时,它们的类型必须相互匹配,有时类型参数只是用来做类型匹配检测的,而并没有用到命令和事件中去,本例中的Timer接口就是如此,虽然它带有一个类型参数,但它里面没有一个函数用到了这个类型参数。

Blink示例是一个LEDs的闪烁示例,其中LED0的开关频率为4HZ,LED1的开关频率为2HZ,LED2的开关频率为1HZ。模块BlinkC使用了三个Timer接口示例,同时也使用了LEDs和Boot接口,也就是说BlinkC在调用这些接口所定义的命令的同时必须实现接口所定义的事件的处理函数,如图2.3所示:

图2.3 Blink接口

其中各个组件和接口的作用为: Main.Boot:初始化并启动程序

LEDs.Leds:控制LED的动作(亮、灭、闪烁) Timer.Timer:计时器

之前提到过Timer是一个带类型参数的接口,它的3个标注的类型是TMilli, T32khz, 和 TMicro,分别表示毫秒级,32Khz和微妙级的计时器。这些类型都各自的定义为C的结构体。

2、 组成和编译

接口可以由组件提供或使用。被提供的接口表现它为使用者提供的功能,被使用者表现使用者完成它的作业所需要的功能。例如在Blink示例中,组件LEDs和Timer提供了使用的接口,实际上它们也需要再调用下层的组件,如MSP430GPIO和MSP430TimerB7等。

考虑到较好的代码重用性,nesC是基于由编译器生成完整程序代码的需求设计的。作为一个必要的组成部分,nesC的编译器会根据用户所指定的平台编译生成一个对应于特定平台的C源文件。对于其产生的C源文件,nesC依据不同的微控制器使用一个对应的本地GNU的C编译器将产生的C源文件编译成可执行文件并将其下载到对应硬件平台上。如图2.4所示,nesC就根据不同的环境使用不同的编译器:Atmel128 C 源文件对应的是AVRgcc 编译器,MPS430 C 源文件对应的是mspgcc 编译器,其他的C 源文件对应的是另外的编译组件,它们对应的下载到的硬件平台分别为MicaZ和Mica2、Telosb和Taroko、其他硬件平台。

Page 10 of 94

TinyOS Programming

图2.4 组成和编译方式

3、 开发环境

开发环境是一个命令行界面,下图是在Windows操作系统上Cygwin + TinyOS的一个开发环境界面。

图2.5 开发环境

2.1.2 并发模型

TinyOS一次只执行一个应用程序,而一个应用程序由一些必要的组件和一些可选的组件组合而成。TinyOS程序有两个执行线程:任务和硬件事件句柄。任务是一种被延迟执行的函数。一旦任务被执行,它们就一直运行直至结束,中间不会被其它任务中断。硬件事件句柄是对硬件中断的处理,同样会一直运行到结束,但是可能会抢占一个任务或其它硬件事件句柄的运行。命令和事件要作为硬件事件句柄来执行,则必须用关键字async来声明。

Page 11 of 94

TinyOS Programming

因为任务和硬件事件句柄是可以被其它异步代码抢占的,所以在一定竞争情况下,nesC程序是很容易受到影响,从而导致数据的不一致或错误。为避免竞争而带来的错误产生,可以在任务内排外地访问数据,或者每次访问都采用原子 (atomic) 语句。nesC编译器在编译期间给程序员报告潜在的数据竞争。编译器也可能会产生错误的报告(例如:该变量需要随时变化),这种情况下,变量可以用关键字norace声明。注意:关键字norace必须极其小心地使用。

要了解用 nesC 编程的更多信息,请参看:

http://www.tinyos.net/tinyos-2.x/doc/nesc/ref.pdf。

2.2 常用make命令简介

TinyOS编程中,有一些make命令是经常用到的,下面对其一一进行介绍。

1) make [platform]

此命令是将nesC代码编译成可在某平台运行的代码。在执行前要切换到代码所在的目录。例如:Blink程序的代码在C:\\UCB\\cygwin\\opt\\tinyos-2.x\\apps\\Blink 目录下。打开Cygwin shell后用cd命令转到该目录下,然后输入make telosb (make mica) 命令就可以让编译器将其编译成可以在telosb (mica) 平台运行的代码了,当然首先得保证没有任何语法错误。

2) make [platform] reinstall

使用 make [platform]命令后,就可以将在某平台的可执行代码下载到对应的平台上了。例如:make telosb reinstall (make mica reinstall) 就可以将编译好的可在telosb (mica) 平台上运行的代码下载到telosb (mica) 硬件平台。

3) make [platform] install

此命令的功能相当于先执行命令make [platform],再执行命令make [platform] reinstall。当然,如果执行make [platform] 命令时,发现程序有错误,则不会执行下载动作,即不会执行make [platform] reinstall命令。

4) make clean

此命令删除上述编译命令产生的文件及文件夹。

5) make [platform] docs

此命令生成程序使用的所有组件、接口的关系的文件。生成的文件在tinyos-2.x\\doc\\nesdoc 目录下,其中索引文件为 “index.html”。

2.3 应用举例:Blink ---TinyOS编程的“Hello World”程序

上面的nesC语言简介中,简略介绍了组件、接口、模块、连接、命令、事件等基本概念。对于初学者来说相当抽象,下面结合一个例子来看看各个概念在nesC/TinyOS编程中的用法。这个例子是TinyOS自带的程序,位于tinyos-2.x/apps/Blink,其功能是让一个LED以1Hz的频率闪烁。

Blink应用程序由两个组件组成:一个模块定义文件“BlinkC.nc”和一个配置文件“BlinkAppC.nc”,“BlinkAppC.nc”也就是顶层配置,它连接“BlinkC.nc”和其他必要组件。请记住,任何一个应用程序都有一个用应用程序名命名的顶层配件,在此处,配件BlinkAppC.nc就是Blink应用程序的顶层配件,nesC编译器根据该文件的内容产生可执行文件。另一方面,模块BlinkC.nc提供Blink应用程序的实现代码。正如你所想的,BlinkAppC配件是用来连接组件:BlinkC模块和Blink应用程序用到的其它组件的。

Page 12 of 94

TinyOS Programming

4.1 模块实现

SenseC.nc

#include \

module SenseC {

uses {

interface Boot; interface Leds;

interface Timer; interface Read; } }

implementation {

// 采样周期100ms

#define SAMPLING_FREQUENCY 100

event void Boot.booted() {

call Timer.startPeriodic(SAMPLING_FREQUENCY);//启动计数器 }

event void Timer.fired() {

call Read.read(); //计时器到,开始读取数据 }

//读取数据完毕,处理数据,即将数据用LED显示

event void Read.readDone(error_t result, uint16_t data) {

if (result == SUCCESS){ if (data & 0x0004) call Leds.led2On(); else

call Leds.led2Off(); if (data & 0x0002) call Leds.led1On(); else

call Leds.led1Off(); if (data & 0x0001) call Leds.led0On(); else

call Leds.led0Off(); } } }

event result_t Timer.fired() { return call ADC.getData(); }

async event result_t ADC.dataReady(uint16_t data) { display(7-((data>>7) &0x7));

Page 28 of 94

TinyOS Programming

return SUCCESS; } }

像BlinkC模块一样,SenseC组件使用Boot,Timer和Leds接口。此外,SenseC组件还使用了Read接口。SenseC周期性的读取采集到的数据并根据数据决定LED的亮灯情况。具体实现过程如下:

1. 首先系统初始化,调用Timer.startPeriodic(SAMPLING_FREQUENCY)启动周期性计数器 2. 计数器到,触发事件Timer.fired(),调用Read接口Read.read()命令读取数

据 3. 当读取数据完成,触发事件Read.readone(),然后将数据通过LED显示出来

可以看出,SenseC应用程序是事件驱动的,即每隔一段时间触发一次定时器事件,然后在事件中执行采集数据的任务。这种编程的模式是tinyos编程普遍的做法,几乎每个TinyOS都是采用事件驱动模式的,在这里是采样事件,在另外一些应用程序可能是串口事件和无线电收发事件。

现在你可能有这样的疑问:Sense程序中ADC访问的究竟Telosb中的哪个传感器,是温度传感器,电压传感器还是光电传感器呢?我们通过查看Sense配件可以得到答案。 Sense.nc

configuration SenseAppC {

//该模块不提供接口 }

implementation {

components SenseC, MainC, LedsC, new TimerMilliC(), new DemoSensorC() as Sensor;

SenseC.Boot -> MainC; SenseC.Leds -> LedsC;

SenseC.Timer -> TimerMilliC; SenseC.Read -> Sensor; }

SenseAppC.nc组件和BlinkAppC组件类似。其中Read接口是由DemoSensorC提供的。

DemoSensorC.nc

generic configuration DemoSensorC() {

provides interface Read; }

implementation {

components new VoltageC() as DemoSensor; Read = DemoSensor; }

Page 29 of 94

TinyOS Programming

由DemoSensorC的配件可知,DemoSensorC提供的Read接口是实际上由VoltageC()提供的,即电压传感器。

VoltageC.nc

generic configuration VoltageC() { provides interface Read; }

implementation {

components new Msp430InternalVoltageC(); Read = Msp430InternalVoltageC.Read; }

在telosb平台,因此VoltageC()组件调用的是Msp430InternalVoltageC组件提供的Read接口。

下面我们向下更深层次的分析,这就直接和硬件相关了。 4.2 ADC

下图为MSP4301611芯片的内部结构,左侧为16路ADC输入通道,A0-A7为8个可以外接的输入通道,由具体的硬件平台决定。参考telosb节点的数据手册,外置的温湿度传感器和光电传感器分别对于A3和A4通道。

16路输入通道

Msp430Adc12.h

Page 30 of 94

TinyOS Programming

enum inch_enum {

// see device specific data sheet which pin Ax is mapped to INPUT_CHANNEL_A0 = 0, // input channel A0 INPUT_CHANNEL_A1 = 1, // input channel A1 INPUT_CHANNEL_A2 = 2, // input channel A2 INPUT_CHANNEL_A3 = 3, // input channel A3 INPUT_CHANNEL_A4 = 4, // input channel A4 INPUT_CHANNEL_A5 = 5, // input channel A5 INPUT_CHANNEL_A6 = 6, // input channel A6 INPUT_CHANNEL_A7 = 7, // input channel A7

EXTERNAL_REF_VOLTAGE_CHANNEL = 8, // VeREF+ (input channel 8) REF_VOLTAGE_NEG_TERMINAL_CHANNEL = 9, // VREF-/VeREF- (input channel 9)

TEMPERATURE_DIODE_CHANNEL = 10, // Temperature diode (input channel 10)

SUPPLY_VOLTAGE_HALF_CHANNEL = 11, // (AVcc-AVss)/2 (input channel 11-15)

INPUT_CHANNEL_NONE = 12 // illegal (identifies invalid settings) };

内部电压传感器Msp430InternalVoltage的实现如下所示: Msp430InternalVoltageP.nc

module Msp430InternalVoltageP {

provides interface AdcConfigure; }

implementation {

const msp430adc12_channel_config_t config = {

inch: SUPPLY_VOLTAGE_HALF_CHANNEL, //输入通道 sref: REFERENCE_VREFplus_AVss, //参考电压 ref2_5v: REFVOLT_LEVEL_1_5, adc12ssel: SHT_SOURCE_ACLK, adc12div: SHT_CLOCK_DIV_1, sht: SAMPLE_HOLD_4_CYCLES,

sampcon_ssel: SAMPCON_SOURCE_SMCLK, sampcon_id: SAMPCON_CLOCK_DIV_1 };

async command const msp430adc12_channel_config_t* AdcConfigure.getConfiguration() {

return &config; } }

内部电压的输入通道inch:SUPPLY_VOLTAGE_HALF_CHANNEL对于为ADC11,如果将输入通道设为INPUT_CHANNEL_A3(INPUT_CHANNEL_A4),即为温度传感器(光电传感器)。

Page 31 of 94

TinyOS Programming

第5章 TinyOS任务及应用举例

本章以实例的方式介绍TinyOS的一个重要概念:任务。所举例子:SenseTask,是Sense应用程序的另一个版本。

5.1 任务的创建和调度

TinyOS 提供任务和硬件事件句柄组成的两层调度策略。如前所述,过关键字 async 声明了可被硬件事件句柄执行的命令或事件。这意味着它可以在任何时候执行(可能会抢占其它代码的执行)。因此,用 async 声明的命令和事件所做的工作应该做尽量少,且要快速完成。此外,还得注意被异步命令或事件访问的数据可能存在的数据竞争。任务则被用来处理一些较长时间的操作,例如:后台数据处理,但任务可以被硬件事件句柄抢占。

一个任务可以用以下语法在你的实现模块中声明: task void taskname(){ //?? } 其中,taskname 是程序员任意指定的任务的标识,也就是“函数名”。一个任务的返回值类型必须是 void,并且不能有任何参数。而向操作系统提交任务则可以用以下语法: post taskname(); 一个任务可以在命令、事件或其它任务内部向操作系统提交。

post 操作把任务放置到一个以先进先出为处理方式的内部任务队列中去。当一个任务开始执行的时候,只有它运行结束,下一个任务才能开始运行;因此,一个任务不应该占用或阻塞太长时间。任务之间不可以互相抢占,但是会被硬件事件句柄抢占。如果你的任务需要执行一系列长时间的操作,最好把任务分成几个而不是使用一个大的任务。

Page 32 of 94

本文来源:https://www.bwwdw.com/article/j626.html

Top