TinyOS学习笔记1
更新时间:2023-11-22 20:08:01 阅读量: 教育文库 文档下载
- TinyOs怎么读推荐度:
- 相关推荐
TinyOS学习笔记1-TinyOS安装 1、Ubuntu系统的安装
安装TinyOS可以在Windows中利用Cygwin进行安装,经过测试在XP中可以正确安装,但是安装的步骤过于麻烦,可以参考官方网站的安装步骤。在Win7中安装后有问题,不能正确编译。因此最好使用Linux系统来安装TinyOS,安装过程简单。 安装Ubuntu系统
1.Ubuntu的官方网站下载iso镜像,我安装的是10.04版本 2.可以有两种方式进行Ubuntu安装。
(1)传统方式安装:在系统中划分出空闲分区,利用U盘制作启动盘,官网有,可下载。重启系统选择U盘启动。进行安装。
(2)wubi方式进行安装:以文件形式进行安装,下载wubi,将镜像与wubi放于同一文件夹。点击wubi进行安装。 3.更新Ubuntu
更行Ubuntu时需要注意,更新时grub不更新。利用wubi安装,我选择了更新grub,重新启动系统出现错误。解决方法如下:
1.另一台电脑,到Ubuntu网站下载镜像,安装到U盘中,制作启动盘。
2.开机,选择从U盘启动,在Boot里设置不好使,像我的ASUS A8,开机按ESC,选择U盘启动。
3.看到Ubuntu的欢迎界面,选择第一项,进入U盘中的Ubuntu系统。 4.在终端中,输入 sudo apt-get install lilo sudo lilo -M /dev/SDa mbr
5.重启系统,问题解决 4.使用root登录系统
2、在Ubuntu系统下安装TinyOS
我安装的时TinyOS2.1.1,安装过程参考TinOS官网的安装指导,但有问题,具体步骤如下: 1)在系统的“/etc/apt/sources.list”中,添加如下代码: deb http://tinyos.stanford.edu/tinyo ... lt;distribution> main
以上的源可能有问题,在安装是提示tinyos-2.1.1依赖的包找不到或无法安装,更新源如下解决此问题:
deb http://tinyos.stanford.edu/tinyos/dists/ubuntu hardy main deb http://hinrg.cs.jhu.edu/tinyos oneiric main
2)更新知识库,打开终端,输入 sudo apt-get update 3)安装TinyOS
sudo apt-get install tinyos
提示可选的tinyos的版本,选择最新的版本2.1.1 sudo apt-get install tinyos-2.1.1 4)设置环境变量
在~/.bashrc或者~/.profile中加入如下代码
#Sourcing the tinyos environment variable setup script
source /opt/tinyos-2.1.1/tinyos.sh
可用如下方法打开~/.bashrc或者~/.profile gedit ~/.bashrc
添加成功后需要重新启动终端 5)测试是否安装成功
cd /opt/tinyos-2.1.1/apps/Blink/
(若当前文件夹没有权限创建文件,将Blink复制到当前用户的目录进行运行) make telosb
显示如下则安装成功: mkdir -p build/telosb
compiling BlinkAppC to a telosb binary
ncc -obuild/telosb/main.exe -Os-O -mdisable-hwmul -fnesc-separator=__ -Wall -Wshadow -Wnesc-all-target=telosb -fnesc-cfile=build/telosb/app.c -board=-DDEFINED_TOS_AM_GROUP=0x22
-DIDENT_APPNAME=/\-DIDENT_HOSTNAME=/\
-DIDENT_TIMESTAMP=0x4c566efbL-DIDENT_UIDHASH=0xd972ea96L BlinkAppC.nc -lm
compiled BlinkAppC to build/telosb/main.exe
2648 bytes in ROM
54 bytes in RAM
MSP430-objcopy --output-target=ihexbuild/telosb/main.exe build/telosb/main.ihex
writing TOS image
TinyOS学习笔记2-TinyOS的IDE-Yeti2
3.测试TinyOS中的Toosim
? make micaz sim
? 提示找不到python2.5
? 查看本机python的版本,我的版本为2.6 ? 进入/opt/tinyos-2.1.1/support/make/sim.extra ? 修改python的版本PYTHON_VERSION=2.6 ? 重新make micazsim
? 提示*** Successfullybuilt micaz TOSSIM library.则可运行tossim。 4.安装Eclipse以及TinyOS的IDE-Yeti2 1)下载,解压Eclipse
Eclipse,在桌面创建启动器,连接Eclipse. 2)参考http://tos-ide.ethz.ch/wiki/index.php
Help->Install New Software
3)点击Add,Name:Yeti2,location:http://tos-ide.ethz.ch/update/site.xml 4) next等待更新
5)选择如下,进行安装
6)安装Graphical Editing Framework 若出现如下错误:
Cannot complete the install because one or more required items could not be found.
Software being installed: Yeti 2 - TinyOS Debugger (optional) 1.2.18 (tinyos.yeti.debugger.feature.group 1.2.18)
Missing requirement: Yeti 2 - TinyOS Debugger (optional) 1.2.18 (tinyos.yeti.debugger.feature.group 1.2'org.eclipse.cdt.debug.core 0.0.0' but it could not be found
在安装Eclipse时解压错误,导致一些文件没有正确安装,卸载Eclipse重新安装,注意是先解压后再拷贝到相应tar出错的),再次安装问题解决。 7)安装完毕,设置环境变量
Window->Preferences->TinyOS->Environments
检查各个目录,点击Apply,OK,设置完毕。 8)检查TinyOS的安装
TinyOS->CheckInstallation(需要新建一个TinyOS项目才会出来此选项,在上部Window旁) 我的返回:Done Errors:0 Warnings:1 警告的部分:
Test:Environment variables
Description: Compare the environment variables known toEclipse with the variables known to the shell Environment variables differ, this can lead to failureswhen compiling or debugging an application.
CLASSPATH: Eclipse = ''
Shell =':/opt/tinyos-2.1.1/support/SDk/java'
LESSCLOSE: Eclipse = ''
Shell ='/usr/bin/lesSPIpe %s %s'
LESSOPEN: Eclipse = ''
Shell ='| /usr/bin/lesspipe %s'
LS_COLORS: Eclipse = '' Shell =''
MAKERULES: Eclipse = ''
Shell ='/opt/tinyos-2.1.1/support/make/Makerules'
TOSDIR: Eclipse = ''
Shell ='/opt/tinyos-2.1.1/tos'
TOSROOT: Eclipse = ''
Shell ='/opt/tinyos-2.1.1' Status: warning
Message: Not all environment variables are thesame 警告未解决!!!
TinyOS学习笔记3-Blink分析
5.TinyOS2.1.1应用程序举例:Blink 1.导入TinyOS例子
File->New->Example->选择TinyOS Example,配置如下: Projete Name:MyBlink
Environment: TinyOS Unix Wrapper 2 Example: Blink Targer: telosb
2.参考Blink例子,建立自己的TestBlink进行分析,我们的程序只让一个灯闪烁。 File->New->Project->TinyOSProject Project Name:TestBlink Target:telosb
3.src->New->Module->Nameof new Module:BlinkC
Moduule的含义:模块实现应用程序的代码,实现一个或多个接口。 在模块中添加接口,供configuration来调用。 本程序的源代码如下:
#include \导比入头文件
module BlinkC @safe(){ //@safe的含义:?????
uses interface Timer as Timer0; //Timer接口,必须实现 uses interface Leds;//Led灯的接口 uses interface Boot;//启动接口 }
//接口的实现 implementation{ //自动生成
event void Timer0.fired(){
// TODO Auto-generated method stub //输出信息,在tossim中显示
dbg(\
//使led灯改变
call Leds.led0Toggle(); }
event void Boot.booted(){
// TODO Auto-generated method stub //时间周期为250毫秒
call Timer0.startPeriodic(250); } }
3.src->New->configuration->Nameof new Configuration:BlinkAppC
Configuration的含义:配置是将组件装配起来的组件,将各个组件使用的接口与其他组件提供的接口连接在一起。
components的含义:各个组件连接形成nesC的程序,组件是由各个模块组成的。
TinyOS学习笔记4-task操作分析
task操作分析 1.task操作的含义
正如基本的c语言一样,所有的代码是同步的,cup的资源是没有充分利用的。进一步而言,如果一段代码运行会影响其他代码的运行。任务的含义就是使任务中的代码在后台运行,也就是说过一会儿运行,类似于中断操作例如:
task void computeTask() { uint32_t i;
for (i = 0; i < 400001; i++){} }
event void Timer0.fired() { call Leds.led0Toggle(); post computeTask(); }
task为任务的代码部分,而task利用post来调用。本段代码的含义就是在灯亮过之后进行一个400,001次的作用就是在进行循环时不影响Timer.fired()的结束。 实验如下:
event void Timer0.fired() {
uint32_t i;
for (i = 0; i < 400001; i++) { call Leds.led0Toggle(); } }
此段代码的含义:循环400,001次,灯进行反转400,001次,由于是奇数,最后的结果是红灯。
实验的结果:红灯长亮,并没有进行闪烁,将数值变小后进行闪烁。 原因:计算干扰了Timer的操作。‘ 利用task的实验:
task void computeTask() { uint32_t i;
for (i = 0; i < 400001; i++){} }
event void Timer0.fired() { call Leds.led0Toggle(); post computeTask(); }
此段代码的含义:灯反转,再循环400,001次。 实验的结果:灯不断进行闪烁。
原因:task将计算与Timer的操作分开,由一个任务来执行计算。post操作将task放入一个任务序列,利用FIFO原则,完成一个任务继续执行下一个任务,不影响当前的操作。 进一步优化task操作: uint32_t i;
task void computeTask() { uint32_t start = i;
for (;i < start + 10000&& i < 400001; i++){} if (i >= 400000) { i = 0; } else {
postcomputeTask(); } }
event void Timer0.fired() { call Leds.led0Toggle(); post computeTask(); }
此段代码的含义:将计算分为10000次的多个小任务。实验的结果:红灯闪烁的频率变快。可见代码的效率提高修改优化代码:
task void computeTask() { static uint32_t i; uint32_t start = i;
for (;i < start + 10000&& i < 400001; i++){} if (i >= 400000) { i = 0; }
else {
postcomputeTask(); } }
在此段代码中将静态变量i设置为局部变量。在nesC中,由于组件的状态是完全私有的,使用静态变量不利于命用,也就是说可能和别的组件中变量的定义冲突,因此应注意静态变量变为局部变量。
TinyOS, task
TinyOS学习笔记5-Split-Phase操作 Split-Phase操作
比较以下Blocking和Split-Phase操作的两段代码 Blocking
if (send() == SUCCESS) { sendCount++; }
在Block的系统中,当要调用一个运行时间很长的操作时,直到操作完成调用才能返回。例如,只有执行完sen返回值。
Split-Phase // start phase send();
//completion phase
void sendDone(error_t err) { if (err == SUCCESS) { sendCount++; } }
在Split-Phase操作中,将程序的执行分为两个部分,开始部分和完成部分。 Split-Phase操作的好处:
1.节省内存,与block的操作需要stack相比,节省了内存stack的开销。 2.可以并行运行多个操作。 下面是另一个例子 Blocking:
state = WAITING; op1();
sleep(500); op2();
state = RUNNING
在此个Block的例子中,整个程序需要进行sleep(500)
Split-phase:
state = WAITING; op1();
call Timer.startOneShot(500);
event void Timer.fired() { op2();
state = RUNNING; }
此Split-Phase的操作,在调用Timer.startOneShot(500)后,程序立即返回,整个程序并没有停止,过500ms后,自void Timer.fired()
以上均为本人读过tutorials的总结,还会继续更新。
TinyOS, Split-Phase
TinyOS 学习笔记6- 基本的通信接口
基本的通信接口:
Packet:为message_t的抽象数据类型提供访问的接口
Packet.nc的位置为/opt/TinyOS-2.1.1/tos/interfaces/Packet.nc
#include
interface Packet {
//清空数据包,将msg的数据清空重新使用 command void clear(message_t* msg);
//返回信息负载的长度
command uint8_t payloadLength(message_t* msg); //设置负载长度
command void setPayloadLength(message_t* msg, uint8_t len); //返回最大负载
command uint8_t maxPayloadLength(); //获取负载,len为需要的负载的长度
command void* getPayload(message_t* msg, uint8_t len); }
message.h为于/opt/tinyos-2.1.1/tos/types/message.h,其主要内容如下:
#include \
typedef nx_struct message_t {
nx_uint8_t header[sizeof(message_header_t)]; nx_uint8_t data[TOSH_DATA_LENGTH];
nx_uint8_t footer[sizeof(message_footer_t)];
nx_uint8_t metadata[sizeof(message_metadata_t)]; } message_t;
platform_message.h为于相应平台下的目录中,例如在/telosb/mac/tkn154/platform_message.h
telosb
中为/opt/tinyos-2.1.1
telosb所采用的MAC层为802.15.4的MAC协议,用户无需再关心MAC协议,该Message同样定义了如何于串口nx_struct为nesC中的结构体,即可理解成c语言中的stuct nx_uint8_t,为无符号的8位整型数据
Send:提供基本的无地址信息发送接口
#include
interface Send {
//设置发送数据包的负载长度
command error_t send(message_t* msg, uint8_t len); //取消数据的传输
command error_t cancel(message_t* msg); //发送数据完成
event void sendDone(message_t* msg, error_t error); //返回通讯层允许的最大负载长度 command uint8_t maxPayloadLength();
//获取负载
command void* getPayload(message_t* msg, uint8_t len); }
Receive:提供基本的信息接收接口
#include
interface Receive {
//返回数据包的buffer,msg接收的数据包,数据包负载的指针,负载长度。
event message_t* receive(message_t* msg, void* payload, uint8_t len); }
PacketAcknowledgements:在每个包上为请求ACK提供一个策略
interface PacketAcknowledgements {
//告诉协议,当要发送这个数据包时,使用同步的ACK async command error_t requestAck( message_t* msg ); //不使用同步ACK
async command error_t noAck( message_t* msg ); //传输的数据包是否为ACK
async command bool wasAcked(message_t* msg); }
async的含义:同步
RadioTimeStamping:为无线通讯提供时间戳信息 interface RadioTimeStamping {
//提供帧开始传输的时间,时间单元是a 32kHz clock
async event void transmittedSFD( uint16_t time, message_t* p_msg ); //开始接收帧的时间
async event void receivedSFD( uint16_t time ); }
接口, 通信, TinyOS
TinyOS 学习笔记7- ACtive Message接口 Active Message Interfaces
由于会出现多个服务利用同一个radio通信的情况,TinyOS提供了AM层来多元访问radio。 AM type代表AM的类型,与以太网的帧类型,IP协议区,UDP协议区相类似。 AM address接收节点的地址,目的区域
AMPacket:对AM数据包的基本设置
位于/opt/tinyos-2.1.1/tos/interfaces/AMPacket.nc #include
interface AMPacket {
//返回AM栈中节点的am地址 command am_addr_t address();
//返回AM数据包的目的地址的AM地址
command am_addr_t destination(message_t* amsg);
//返回AM数据包中的原地址的AM地址
command am_addr_t source(message_t* amsg); //设置AM数据包的目的地址的AM地址
command void setDestination(message_t* amsg, am_addr_t addr); //设置AM数据包中的原地址的AM地址
command void setSource(message_t* amsg, am_addr_t addr);
//返回该信息是否为给本节点的,简单判断destination和address是否一致,广播可能出错 command bool isForMe(message_t* amsg); //返回AM数据包的AM类型,就是说包的类型 command am_id_t type(message_t* amsg);
//设置包的类型
command void setType(message_t* amsg, am_id_t t); //获得AM数据包的AM组
command am_group_t group(message_t* amsg); //设置AM数据包的AM组
command void setGroup(message_t* amsg, am_group_t grp); //返回本节点的AM组
command am_group_t localGroup(); }
AMSend:为基本的AM数据包提供发送接口
#include
interface AMSend {
//发送负载长度为len的数据,addr为发送地址
command error_t send(am_addr_t addr, message_t* msg, uint8_t len); //取消发送数据
command error_t cancel(message_t* msg);
//数据发送完成,成功返回SUCCESS,失败返回FAIL,被取消返回ECANCEL event void sendDone(message_t* msg, error_t error); //返回通信层提供的最大负载长度 command uint8_t maxPayloadLength(); //获取负载
command void* getPayload(message_t* msg, uint8_t len); }
通信的组件:此组件位于/tos/system的目录下
AMReceiverC:提供Receive,Packet和AMPacket的接口
#include \
generic configuration AMReceiverC(am_id_t amId) { provides {
interface Receive; interface Packet; interface AMPacket; } }
implementation {
components ActiveMessageC;
Receive = ActiveMessageC.Receive[amId]; Packet = ActiveMessageC; AMPacket = ActiveMessageC; }
generic的含义:普通的,可以在其他的程序中调用
AMSenderC:提供AMSend,Packet和AMPacket和ACK的接口 #include \
generic configuration AMSenderC(am_id_t AMId) { provides {
interface AMSend; interface Packet; interface AMPacket;
interface PacketAcknowledgements as Acks; } }
implementation {
#if defined(LOW_POWER_LISTENING)
components new LplAMSenderC(AMId) as SenderC; #else
components new DirectAMSenderC(AMId) as SenderC; #endif
AMSend = SenderC; Packet = SenderC; AMPacket = SenderC; Acks = SenderC; }
AMSnooperC:提供Receive,Packet和AMPacket的接口,进行嗅探的组件功能于AMRecieverC相同,用于接收#include \
generic configuration AMSnooperC(am_id_t AMId) { provides {
interface Receive; interface Packet; interface AMPacket; } }
implementation {
components ActiveMessageC;
Receive = ActiveMessageC.Snoop[AMId]; Packet = ActiveMessageC; AMPacket = ActiveMessageC; }
AMSnoopingReceiverC:提供Receive,Packet和AMPacket的接口,多了个ActiveMessageC.Receive[AMId]
#include \
generic configuration AMSnoopingReceiverC(am_id_t AMId) { provides {
interface Receive; interface Packet; interface AMPacket; } }
implementation {
components ActiveMessageC;
Receive = ActiveMessageC.Snoop[AMId]; Receive = ActiveMessageC.Receive[AMId]; Packet = ActiveMessageC; AMPacket = ActiveMessageC;
}
ActiveMessageAddressC:本module提供了get和set节点AM地址的commond。本module不是为一般用户提供坏网络栈,在了解其操作的情况下才可使用。
module ActiveMessageAddressC @safe() { provides {
interface ActiveMessageAddress;
async command am_addr_t amAddress();
async command void setAmAddress(am_addr_t a); } }
implementation {
am_addr_t addr = TOS_AM_ADDRESS;
am_group_t group = TOS_AM_GROUP;
async command am_addr_t ActiveMessageAddress.amAddress() { return call amAddress(); }
async command void ActiveMessageAddress.setAddress(am_group_t myGroup, am_addr_t myAddr) { atomic {
addr = myAddr; group = myGroup; }
signal ActiveMessageAddress.changed(); }
async command am_group_t ActiveMessageAddress.amGroup() { am_group_t myGroup; atomic myGroup = group; return myGroup; }
async command am_addr_t amAddress() { am_addr_t myAddr; atomic myAddr = addr; return myAddr; }
async command void setAmAddress(am_addr_t a) { atomic addr = a;
signal ActiveMessageAddress.changed(); }
default async event void ActiveMessageAddress.changed() { } }
TinyOS, address, 数据包, 以太网, 接口
TinyOS学习笔记8-简单发送接收数据
简单发送接收数据
本节为对BlinkToRadio的分析,从而了解简单的收发过程。 我们读BlinkToRadio修改如下:发送本节点的id给其他的节点 BlinkToRadio.h
#ifndef BLINKTORADIO_H #define BLINKTORADIO_H
enum {
AM_BLINKTORADIO = 6, //AM数据包的类型
TIMER_PERIOD_MILLI = 250 //发送的时间间隔为250ms };
//定义发送数据包的负载部分
typedef nx_struct BlinkToRadioMsg { nx_uint16_t nodeid; //本节点的id nx_uint16_t counter; //计数 } BlinkToRadioMsg;
#endif
BlinkToRadioC.nc 文件分析
#include
#include \
module BlinkToRadioC { //定义使用的接口
uses interface Boot; //从Boot开始启动 uses interface Leds; //led灯
uses interface Timer
uses interface Packet; //数据包,在获取负载处用到
uses interface AMPacket; //AM数据包,需要实现SendDone() uses interface AMSend; //AM发送数据 uses interface Receive; //接收数据包 uses interface SplitControl as AMControl; //Split操作 }
implementation {
uint16_t counter; //发送的次数 message_t pkt; //数据包
bool busy = FALSE; //节点是否忙,开始为不忙
//从此处启动,开始程序 event void Boot.booted() {
call AMControl.start(); //调用Split操作的开始,是否成功在startDone()处判断 }
//判断开始是否完成
event void AMControl.startDone(error_t err) { if (err == SUCCESS) {
//成功调用时间周期执行
call Timer0.startPeriodic(TIMER_PERIOD_MILLI); } else {
//未成功重新开始 call AMControl.start(); } }
//停止判断
event void AMControl.stopDone(error_t err) { }
//时间的每次周期执行的内容,发送数据 event void Timer0.fired() {
counter++;//发送数据个数加1
if (!busy) {//节点不忙,则开始发送数据
//设置数据包的负载,btr指向数据包的负载部分 BlinkToRadioMsg* btrpkt =
(BlinkToRadioMsg*)(call Packet.getPayload(&pkt, sizeof(BlinkToRadioMsg))); if (btrpkt == NULL) {//没有数据就不发送 return; }
btrpkt->nodeid = TOS_NODE_ID; //发送节点的ID,TOS_NODE_ID为在make telosb install,1时设置的 btrpkt->counter = counter; //发送数据包的个数
//开始发送数据,AMSend.send(广播地址,负载数据,负载数据的大小) if (call AMSend.send(AM_BROADCAST_ADDR, //修改AM_BROADCAST_ADDR为2,则节点只向2号节点发,其他 &pkt, sizeof(BlinkToRadioMsg)) == SUCCESS) {
busy = TRUE;//调用发送数据成功,节点正在发送数据,变为忙的状态,是否发送完成在sendDone里判断 } } }
event void AMSend.sendDone(message_t* msg, error_t err) {
if (&pkt == msg) {//如果发送的数据是所设置的数据,发送成功,节点变为不忙 busy = FALSE; } }
//接收数据部分
event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len){ if (len == sizeof(BlinkToRadioMsg)) {//判断接受的数据的长度,是否为所需要的 BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload; //获取数据 call Leds.set(btrpkt->nodeid); //设置led为获取节点的id }
return msg; //返回数据 } }
BlinkToRadioAppC.nc文件,实现连线
#include
#include \
configuration BlinkToRadioAppC { }
implementation { components MainC; components LedsC;
components BlinkToRadioC as App;
components new TimerMilliC() as Timer0; components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIO); components new AMReceiverC(AM_BLINKTORADIO);
App.Boot -> MainC;
App.Leds -> LedsC; App.Timer0 -> Timer0; App.Packet -> AMSenderC; App.AMPacket -> AMSenderC; App.AMControl -> ActiveMessageC; App.AMSend -> AMSenderC; App.Receive -> AMReceiverC; } 在编译时出现警告问题,未解决,估计和平台有关 /opt/TinyOS-2.1.1/tos/chips/cc2420/lpl/DummyLPLC.nc:39:2: warning: #warning \LOW POWER COMMUNICATIO***\ TinyOS 分享到: QQ好友和群 QQ空间 腾讯微博 腾讯朋友 收藏 转播 淘帖 相关帖子 ? ? TinyOS系统从2.1升级到2.1.2教程 ? ? TinyOS 2.x中如何修改message_t中playload的长度 ? ? tinyos CTP温湿度采集android终端显示 ? ? TinyOS2.x启动顺序 ? ? TinyOS中的I/O中断使用 ? ? TinyOs无线消息收发问题 ? ? 关于TinyOS实例化多个定时器的问题 ? ? TinyOS在MSP430F2618上移植(二)之USCI ? ? TinyOS在MSP430F2618上移植(三)之LCD TinyOS学习笔记9-简单的转发程序
本转发程序实现的功能是1号节点发送数据,2号节点接收到数据后转发给3号节点 在BlinkToRadio的基础上,修改BlinkToRadioC.nc如下: #include
#include \
module BlinkToRadioC { uses interface Boot; uses interface Leds;
uses interface Timer
uses interface SplitControl as AMControl; }
implementation {
uint16_t counter; message_t pkt; bool busy = FALSE;
event void Boot.booted() { call AMControl.start(); }
event void AMControl.startDone(error_t err) { if (err == SUCCESS) {
call Timer0.startPeriodic(TIMER_PERIOD_MILLI); } else {
call AMControl.start(); } }
event void AMControl.stopDone(error_t err) { }
event void Timer0.fired() { counter++;
if (TOS_NODE_ID==1&&!busy) { BlinkToRadioMsg* btrpkt =
(BlinkToRadioMsg*)(call Packet.getPayload(&pkt, sizeof(BlinkToRadioMsg))); if (btrpkt == NULL) { return; }
btrpkt->nodeid = TOS_NODE_ID; btrpkt->counter = counter; if (call AMSend.send(2,
&pkt, sizeof(BlinkToRadioMsg)) == SUCCESS) { busy = TRUE; } } }
event void AMSend.sendDone(message_t* msg, error_t err) { if (&pkt == msg) { busy = FALSE; } }
event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len){ if (len == sizeof(BlinkToRadioMsg)) {
BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload; call Leds.set(btrpkt->nodeid);
if (TOS_NODE_ID==2&&btrpkt->nodeid==1&&!busy) {
BlinkToRadioMsg* temppkt = (BlinkToRadioMsg*)(call Packet.getPayload(&pkt, sizeof(BlinkToRadioMsg)));
temppkt->nodeid=btrpkt->nodeid;
temppkt->counter=btrpkt->counter;
if (call AMSend.send(3, &pkt, sizeof(BlinkToRadioMsg)) == SUCCESS) { busy = TRUE; } } }
return msg; } }
经过实验,在没有2号节点的情况下,3号节点收不到数据,加入2号节点后,3号节点收到数据。
TinyOS学习笔记10-节点与计算机利用串口通信1 节点与计算机利用串口通信1
节点与计算机的通信是通过support/SDk/java和support/sdk/c,可以利用java代码或者C代码来实现串口的通信。中的内容,主要介绍了java的应用,如果在以后遇到要使用c语言连接串口的话,到时再研究。 1.如何查看本机的串口,使用motelist命令,我的机器显示如下信息:
root@ubuntu:~# motelist
Reference Device Description
---------- ---------------- --------------------------------------------- XBS518PB /dev/ttyUSB0 XBOW Crossbow Telos Rev.B
java net.TinyOS.tools.Listen -comm serial@/dev/ttyUSB0:telosb
本命令代表使用java命令来执行串口的监听,net.tinyos.tools.Listen为在support/sdk/java中的一个程serial@/dev/ttyUSB0:telosb为程序需要使用的参数。由于连接每一个设备使用不同的波特率,其中telosb代表的在后面我们将详细分析以下这个Listen的程序。
下面首先看一下TestSerial这个例子:
本程序为节点通过串口向计算机周期性的发送数据,并显示在计算机上。 本程序有如下文件,将进行详细的分析:
TestSerial.h文件:
#ifndef TEST_SERIAL_H
3)TinyOS中组件分为两种类型:模块(module)和配件(configuration)。前者用于程序代码的具体实现,后者则他组件连接起来形成新的组件。相应地,一个组件主要由两种文件形式表述:模块文件(文件形式为:*C.nc)和常表达为*AppC.nc),*为自命名的组件名称。
4)配置文件主用功能是实现组件的声明和连接,其一般格式如下: configuration *AppC { }
implementation {
//声明组件或组件的实例化 ……
//连接组件 …… }
5)模块文件是实现文件,也即相应事件和调用命令的文件,其一般格式如下: module *C {
//提供的接口声明或实例化 provides interface ** ;
//使用的接口声明或实例化 uses interface ** as ***; }
implementation {
//事件响应和命令调用 }
6)接口:TinyOS中接口是事件和命令的集合,通过接口,可以调用该接口的事件(event)和命令(commands如Timer接口中包含的命令和事件如下 Commands:
command uint32_t getdt() …… Events
event void fired()
调用形式:假设Timer接口的一个实例为Timer0,则事件响应函数如下: event void Timer0.fired()
【实验步骤】
1、分析实验内容和要求,确定所需组件 从实验内容知,需要使用和定时器有关的组件和驱动LED有关的组件,通过查找和参阅相关资料,得知TimerMilliC组件,通过帮助文档,得知两个组件所提供的接口,再利用帮助文档查找相关的实现功能(如本实验的点亮LE命令)。所需组件分析如下:
节点上电:MainC(提供Boot接口) 定时器:TimerMilliC组件 LED驱动:LedsC组件
2、定义新的组件用以“集合”所需的组件
分析所需的组件之后,定义一个“父”组件,用以集成各组件,也即通过配置文件和模块文件来实现。 如本实验定义组件TimerLightC组件,与其他组件之间的关系如下框图所示:
登录/注册后可看大图 定时器, TinyOS, 编程
#define TEST_SERIAL_H
//定义数据包的格式
typedef nx_struct test_serial_msg { nx_uint16_t counter; //计数 } test_serial_msg_t;
enum {
AM_TEST_SERIAL_MSG = 0x89, //表明是AM测试串口数据。就是个标志 };
#endif
TestSerialC.nc文件,实现接口中的event,和基本的通信程序差不多,但接收的是计算机传来的数据
#include \#include \
module TestSerialC { uses {
interface SplitControl as Control; interface Leds; interface Boot; interface Receive; interface AMSend;
interface Timer
implementation {
message_t packet;//数据包
bool locked = FALSE;//节点是否忙,同busy uint16_t counter = 0;//数据包计数
event void Boot.booted() {
call Control.start(); //开始,向下找startDone }
//时间每次启动调用的函数 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;}
//所发的数据超界,返回-comm serial@/dev/ttyUSB0:telosb if (call Packet.maxPayloadLength() < sizeof(test_serial_msg_t)) { return; }
rcm->counter = counter;
//广播该计数数据,寻找sendDone
if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(test_serial_msg_t)) == SUCCESS) { locked = TRUE; } } }
//接收数据程序,接收到数据后三位设置led灯 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(); } 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) {} //结束成功 }
该程序和收发程序一致,无需考虑于串口的通信,与串口的通信的代码是在java的代码中实现的。
TestSerialAppC.nc:该文件实现相应的连线,注意AM数据包的不同,为SerialActiveMessageC
#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; }
TestSerialMsg.java:该文件实现对接收到的数据包的解析,其继承的是net.tinyos.message.Message 本文件是有MIG自动生成的,不用编辑此文件,其自动生成的代码在makefile中,如下:
TestSerialMsg.java:
mig java -target=null $(CFLAGS) -java-classname=TestSerialMsg TestSerial.h test_serial_msg -o $@ 不做详细分析,在以后讲解makefile时在详细说明
TestSerial.java:实现对与串口的连接和显示数据 import java.io.IOException;
import net.tinyos.message.*; import net.tinyos.packet.*; import net.tinyos.util.*;
public class TestSerial implements MessageListener {
private MoteIF moteIF;
public TestSerial(MoteIF moteIF) { this.moteIF = moteIF;
this.moteIF.registerListener(new TestSerialMsg(), this); //为节点添加监听事件 }
//发送数据包,由节点发给计算机 public void sendPackets() { int counter = 0;
TestSerialMsg payload = new TestSerialMsg();
try {
while (true) {
System.out.println(\输出接收的数据包,接收数据包的个数 payload.set_counter(counter);
moteIF.send(0, payload);//计算机给节点发送数据 counter++;
try {Thread.sleep(1000);}
catch (InterruptedException exception) {} } }
catch (IOException exception) {
System.err.println(\ System.err.println(exception); } }
//接收节点向计算机发送的数据,MessageListener的实现 public void messageReceived(int to, Message message) { TestSerialMsg msg = (TestSerialMsg)message;
System.out.println(\
}
private static void usage() {
System.err.println(\ }
//调用程序,传入参数为-comm serial@/dev/ttyUSB0:telosb public static void main(String[] args) throws Exception { String source = null; if (args.length == 2) {
if (!args[0].equals(\ usage();//提示信息 System.exit(1); }
source = args[1]; //参数serial@/dev/ttyUSB0:telosb }
else if (args.length != 0) { usage();
System.exit(1); }
PhoenixSource phoenix; //??????
if (source == null) {
phoenix = BuildSource.makePhoenix(PrintStreamMessenger.err); } else {
phoenix = BuildSource.makePhoenix(source, PrintStreamMessenger.err);//连接串口 }
MoteIF mif = new MoteIF(phoenix);//设置节点 TestSerial serial = new TestSerial(mif); serial.sendPackets(); } }
运行时,先用命令make telosb将java代码编译,才可以使用 java TestSerial -comm serial@/dev/ttyUSB2:telosb 经过测试显示的数据为: Sending packet 0
Received packet sequence number 47 Sending packet 1
Received packet sequence number 48
Sending packet 2
Received packet sequence number 49
当用Ctrl+z停止时,节点不再闪烁,接收不到java程序传来的数据。利用SerialActiveMessage实现了节点与计算信。
TinyOS学习笔记11-节点与计算机利用串口通信2-BaseStation 节点与计算机利用串口通信2-BaseStation
BaseStation的功能是实现一个中转的功能,将收到的节点信息发送给计算机,将收到的计算机的信息广播给其他的节点。
对于基站的节点来说,LED0s闪烁:发送一个数据包到其他节点。LED1闪烁:接收到数据包,发送一个数据包到串口。LED2闪烁:丢失一个数据包(接收的速度大于发送的速度)。 下面对BaseStationP.nc的代码进行分析: //需要用到发送信息的数据包和串口
#include \ #include \
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[i] = &uartQueueBufs[i]; //将buffer中的每一个赋给指针 uartIn = uartOut = 0; //输入输出都为0 uartBusy = FALSE; //串口不忙 uartFull = TRUE; //数据已满
//同理设置radio
for (i = 0; i < RADIO_QUEUE_LEN; i++) radioQueue[i] = &radioQueueBufs[i];
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) {
TinyOS中两个基本组件分析:Timer.nc和ActiveMessageAddress.nc组件
Timer.nc组件
Timer组件相关函数说明如下: startPeriodic(uint32_t dt)
基本接口,设置一个周期性定时器每dt时间单位重复,代替任何当前定时器设置,相当于“startPeriodicAt(getNow(),dt)”,“fired()”函数在每个dt时间单位内被标记。
startOneShot(uint32_t dt)
为之后的一些单位时间设置一个单一的短定时器,代替任何当前定时器设置,相当于“startPeriodicAt(getNow(),dt)”,“fired()”函数在定时时间到后被标记。
stop()
取消一个定时器
fired()
当定时器到期时或重复时进行标记。
isRunning()
扩展接口,检查定时器是否在运行,
isOneShot()
检查这是否是one-shot定时器
startPeriodicAt(uint32_tt0, uint32_t dt) 每个dt时间单元设置重复周期定时器,
startOneShotAt(uint32_tt0, uint32_t dt) 设置一个段定时器从t0到t0+dt,
gett0()
为先前启动的定时器或以前的事件的时间周期性计时器返回的时间帧
getdt()
为先前启动的定时器返回延迟或时间间隔
ActiveMessageAddress.nc组件
ActiveMessageAddress.nc组件函数如下:
setAddress(am_group_tgroup, am_addr_t addr,uint8_t myChannel) 设置此节点的地址信息
setChannel(uint8_tchannel) 设置节点信道
amAddress() 返回节点地址信息
amGroup() 返回节点组群信息
amChannel()
返回节点信道信息
changed()
地址或组设置更改的通知
TinyOS系统捕捉用户中断示例(tmote) 示例
虽然官方的TEP文档(tep117)已经标注为final,不过还是有错误的地方,可见对于2.1.2,并不适用,本人以tmote平台为例展示捕捉用户中断port27口(usrint)。 硬件连接:中断源接6针扩展板的5口和10针9口。 程序:
----------myInterrupt.h---------- #ifndef MYINTERRUPT_H #define MYINTERRUPT_H enum {
TIMER_PERIOD_MILLI0 = 1000,//初始化亮灯间隔 TIMER_PERIOD_MILLI1 = 125,//闪烁间隔 }; #endif
----------myInterruptAppC.nc---------- configuration myInterruptAppC{ }
implementation {
components myInterruptC as App,MainC,LedsC; components new TimerMilliC() as Timer0; components new TimerMilliC() as Timer1;
components HplMSP430InterruptC as IOInterruptC; components new Msp430InterruptC() as Interrupt; App.Boot -> MainC; App.Timer0 ->Timer0; App.Timer1 ->Timer1; App.Leds -> LedsC;
Interrupt -> IOInterruptC.Port27;
App.Interrupt -> Interrupt; }
----------myInterruptC.nc---------- #include \module myInterruptC { uses {
interface Boot; interface Leds;
interface Timer
implementation {
uint8_t tick; //检测到中断后灯的闪烁计数 task void start_Timer0() {//初始化提示定时器 call Timer0.startPeriodic( TIMER_PERIOD_MILLI0); }
event void Boot.booted() {
call Interrupt.enableFallingEdge();//下降沿中断使能 call Leds.led0On();
post start_Timer0();//初始化完成,亮灯1s }
task void start_Timer1() {//闪烁间隔定时器
call Timer1.startPeriodic( TIMER_PERIOD_MILLI1); }
async event void Interrupt.fired() { //中断触发 tick = 7;
post start_Timer1(); }
event void Timer0.fired() {//灯亮1s call Leds.led0Off(); call Timer0.stop(); }
event void Timer1.fired() {//灯闪烁3次 uint8_t temp_tick; atomic{
temp_tick = --tick; }
if ( temp_tick != 0 ) { call Leds.led0Toggle(); } else {
call Timer1.stop(); }
} }
tinyos学习笔记(1)基本概念、tinyos与硬件关系
---- 基本概念、TinyOS与硬件关系、对底层基本操作 (支持原创,作者:叶雨荫城(阿雨))
tinyos的基本概念(个人理解,如有错误请指正)
event-driven:tinyos是一个基于Event-driven驱动的操作系统。这个东西不理解的话是不可能对tinyos有深入了解的,尤其是在移植的过程中搞清楚硬件和软件的界限。 什么是事件驱动?
这里主要包含两个方面的含义:软件层面的事件驱动以及硬件事件驱动。在tinyos中软件层面的驱动主要由event以及signal关键字进行实现。而对于硬件事件驱动主要由硬件中断进行实现,产生中断后进入相应的中断处理函数进行处理。硬件事件驱动和软件驱动的主要的关联的部分可以说完全是由signal来完成的,什么意思?就是说在产生硬件中断后,在中断函数中一般是通过signal来通知注册事件的应用层(软件层)有相应的事件发生,而在软件层面的signal所表现的意义也完全如此。但是我们要注意的是,从event层面来看,硬件的event(中断)的事件句柄(即中断处理函数)是异步的,是抢占式的,即只要有硬件中断,无论在tinyos的任务队列中有多少个任务,都会被推迟执行。而在软件层中的event(完全由signal触发,不由硬件产生中断)是非抢占式的,即属于任务(task)的范畴,执行过程首先进入任务队列,只有在其之前的任务运行完成后才会去执行该event的事件句柄(处理函数),当然在软件层面如果声明command、event时,加上async后,这时命令或者event句柄将会成为抢占式的。
注:在抢占式函数中只能调用抢占式操作。这就是为何有时不在async声明的函数中调用call来完成相应的操作而采用task,原因是虽然task为非抢占式的,但是post task操作是抢占式的。所以在async中调用post task是完全合法的。另外一点就是在非抢占式任务中有时候不允许状态突变或者特殊操作时为了避免被抢占式任务抢占,可以用atomic将代码段进行包含,从而可以避免被抢占,唯一的要求就是不要把过多的操作放入atomic,这样会极大的降低tinyos系统的实时性!!!
模块化:这个是编程中普遍存在的概念,模块化的最大好处就是将功能的实现单位化,这样无论在可复用性、扩展、修改等方面都会有很大的好处,而tinyos在模块化方面表现的就更为明显,通过不同的module来实现不同的功能,并且通过configure组件来实现功能的扩展或者使用者和具体实现者的绑定。
接口(interface):接口就是不同函数功能与事件的结合,这与c++中的类中的方法是极为相似的,只不过接口与具体的实现时分开的,这与c++中的方法还是有区别的。不同的组件会有不同的接口并负责这些接口中函数的各个实现。Tinyos系统标准的接口一般存放在tinyos-2.1.1/tos/interfaces中。而具体硬件的一些接口定义存放在chips文件下的不同功能模块文件下,大家可以看看。
Module组件:从本质来说就是一个功能的具体实现,在tinyos中一般是**P.nc文件来指出,
但我们要清楚,P结尾的组件我们在tinyos中使用很少直接与其绑定,而是通过configure对其进行封装后与该configure来实现绑定从而实现相应的功能。中间的configure主要起的作用就是透明化。
Configure组件:一般以**C.nc结尾,Configure组件大家都知道是完成绑定的操作(wiring)。但是从实现的功能看我个人理解主要有如下几种情形(当然这也是个人理解,如有错误请指正):
(1)提供抽象的接口。隔离软件和硬件的具体实现,软件部分与这个抽象接口进行绑定实现相应的功能,而这些接口与特定的硬件平台的实现进行绑定实现硬件与软件的完全隔离。其实这就是我们说的硬件抽象层(HAL)。
(2)实现功能的扩展,不同的module实现的功能毕竟有限,通过configure可以把不同module提供的接口进行整合,从而实现功能的扩展。
(3)最后一个当然也是应用最普遍的一个就是将调用者与实现者进行绑定,这个也是其最大的功能。
注:最好理解这些不同功能的方式就是多看代码,由于时间关系,我不能一一进行列举,请大家见谅。
硬件与tinyos关系的及如何实现tinyos系统本身与硬件的分离?
大家都知道,tinyos的硬件部分分为三层:硬件表示层,硬件抽象层及硬件接口层。这三层听着是很抽象的,我个人理解,举个例子。硬件表示层主要是chips中各个功能模块的具体定义及实现,这就包括定义相应的接口及相应的模块实现,platform主要是将具体的平台与chips中引脚进行绑定,并实现相应的功能。而硬件接口层在哪??大家可能觉得是在硬件或者平台中,这是错误的。真正的硬件接口层的接口定义及实现在具体模块实现tinyos-2.1.1/tos/interfaces及同目录下的system文件夹下,可以说这三者中属于tinyos系统软件级别的只有硬件接口层。让我举个简单的led灯的例子,我将从chips->platform->system进行解读。
下面是我画的一个基本框图: 1.jpg
TinyOS实验一·定时器使用及TinyOS的一般编 实验名称:基于TinyOS的定时器使用 使用平台:Telosb节点
使用环境:Linux下的TinyOS 2.x开发环境 实验时间:2012-06-27
实验内容:
本实验为自拟实验:节点上电之后启动定时器,同时已对应频率驱动Telosb节点上的LED灯 实验目的:
通过简单的实验理顺基于TinyOS编程的思路,为掌握TinyOS编程打下基础
【准备知识】
TinyOS是为无线传感器网络量身定做的基于模块的开源操作系统,其编程使用nesc语言。首先,从宏观上需要掌内容:
1)nesC的应用程序的基本结构式组件,即程序是以组件形式存在的 2)TinyOS是基于事件驱动型的,即由某事件的触发调用某事件响应函数
正在阅读:
TinyOS学习笔记111-22
监理交底会会议纪要会04-25
新员工入职欢迎词相关范文02-11
软件工程硕士论文 基于Activiti的工作流管理系统的设计与实现03-10
大知大觉110-23
七年级上册期中政治提纲04-25
数学归纳法的拓广04-28
IP地址和MAC地址绑定在路由器上的实现07-27
我国特色小镇的15个经典案例汇总04-10
IOmetrer 存储测试工具的使用06-01
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 笔记
- TinyOS
- 学习