1、TinyOS学习笔记作者幽暗天琴TinyOS学习笔记1-入门当我们uses某接口时,那么该接口下的所有command和event都可以调用。在一些情况下,组件也可以provides和usesCommand。同样的provides的组件要实现command的函数内容。配置文件现在,我们已经知道某些组件提供的接口,但,仅仅通过这还不足以访问这个组件。如果a,b同时都提供了一个接口c,那么,当组件d访问c接口时访问的到底是a还是b呢?所以配置文件就产生了,它的目的就是声明你要访问的组件名称,并且将它所提供的接口与你想要使用的接口相连接。配置文件的构成配置文件configuration首先声明了其应用
2、程序下的组件,关键字:components.声明了组件之后,通过-可以将两个组件的接口连接起来。Main.StdControl - BlinkM.StdControl;这段代码就是把组件main和blinkm的stdcontrol连接起来,这样,就建立了两个组件之间的联系。当调用main.stdcontrol的时候就相当于调用了blinkm.stdcontrol。关键字- 永远是将一个使用(uses)的接口(左边)于一个提供(provides)的接口(右边)相连接。也就是说只有左边的组件能够调用右边的组件的接口。反之则不可以。并且该关键是一个多对多的关系,即一个组件可以连接到很多接口,反之一样
3、配置文件还可以通过=关键字来进行接口之间的连接,=号表示两个接口之间的关系是等同的,类似于c语言中的指针。=号两边可以是uses=pro也可以是u=u ,p=p.注:配置文件中也可以使用或提供接口。(后面有例子)配置文件和顶级配置文件一个程序中可以有多个配置文件,但一定要有一个顶级配置文件。在tinyos中组件也是分层次的。最底层的组件贴近硬件部分,是经过一层一层封装才有了上层的组件,封装的过程中就使用了配置文件。而一个应用程序需要一个顶级配置文件,在所有其他的配置文件的更高一层,编译时会首先参照该文件进行编译。程序组成程序实例:blink现在我们要编写一个程序,是传感器上的灯每一秒闪烁一次。
4、首先,我们要根据实际情况去筛选我们所需要的组件。控制亮灯的组件:ledc.控制时间的组件:singletime.控制程序开始的组件:main.程序开始从这里运行所以要通过这个组件带动blinkm.再通过blinkm中的函数控制ledc和singletime.控制程序逻辑上下文:blinkm.在该文件中表达逻辑思路。因此该组件需要连接到时间和亮灯的组件接口上。编写配置文件Blink.ncconfiguration Blink implementation components Main, BlinkM, SingleTimer, LedsC; Main.StdControl - BlinkM.S
5、tdControl; Main.StdControl - SingleTimer.StdControl; BlinkM.Timer - SingleTimer.Timer; BlinkM.Leds - LedsC; StdControl 接口interface StdControl command result_t init(); command result_t start(); command result_t stop(); Result_t是一个数据类型,表示uint8_t该接口用来初始化和启动TinyOS 组件。我们需要知道,tinyos中,任何组件使用之前都需要进行初始化,有些组件
6、会提供如stdcontrol的接口比如singletime 我们就可以用它实现该组件的初始化。编写blinkm.nc通过我们知道要使用一个组件或者模块必须先要启动它,而main又uses stdcontrol来实现blinkm和singletime的启动,因此我们blinkm一定要提供stdcontrol的接口,并且实现它。同时,blink需要控制ledc和singletime因此它还需要使用他们所提供的接口leds,timer。Blinkm.ncmodule BlinkM provides interface StdControl;uses interface Timer;interface
7、 Leds;Stdcontrol的实现implementation command result_t StdControl.init() return SUCCESS;command result_t StdControl.start() command result_t StdControl.stop() 在前面我们说过,没一个组件使用之前都需要初始化,现在我们还剩下led没有进行初始化,观看该接口的函数,我们通过添加call Leds.init();进行此接口的初始化。再让我们看看timer接口。Timer接口Timer.ncinterface Timer command result_t
8、 start(char type, uint32_t interval);command result_t stop();event result_t fired();Start()命令被用于指定timer 的类型和那些即将过期的时间间隔。我们使用毫秒来计算时间间隔。有TIMER_REPEAT 和TIMER_ONE_SHOT 两种可用的类型。在指定的时间间隔过后,timer 将会结束,下一个重复的timer 将会继续执行,直到被stop()命令所终止。当一个间隔到来时,事件 fired()被触发。因此我们的设计思路如下:在blinkm初始化时我们需要对所有组件进行启动,然后开始设置时间间隔,当
9、一个时间间隔过后,事件函数被触发,call Leds.redToggle(); 使红灯亮起。经修改,blinkm.nc如下:Blinkm.ncimplementation command result_t StdControl.init() call Leds.init();return SUCCESS;command result_t StdControl.start() return call Timer.start(TIMER_REPEAT, 1000) ;command result_t StdControl.stop() return call Timer.stop();event
10、result_t Timer.fired()call Leds.redToggle();return SUCCESS;关系图 命令是一层一层向下传递事件是一层一层向上传递当timer到期时。首先发生硬件中断然后将此时间向上传递到timer.fired()中,我们再call leds.red()编译Vi,写字板可以进行.nc的创建编译通过gywin我们到apps/blink目录,输入make micaz ncc编译起会产生一个main.exe文件,而这就是我们需要灌到板子上的程序。但通过软件将程序下载到传感器时无法识别程序的型号,所以采用在blink目录下输入 make micaz instal
11、l eprb, ip的方法也可以将程序下载到传感器当中,经过实验第二种方法可以成功实现blink程序。之所以输入make platform就可以进行编译是因为该目录先有一个makefile的脚本。在以后的实验中,一个新程序的编译脚本将由我们自己来编写。如果没有该文件那么要进行编译就要输入ncc -o main.exe -target=mica Blink.nc小结我们所操作的仅仅是上层部分。我们所使用的模块和组件都是经过一层一层封装。程序真正的入口是在raelmain.nc底下当然,因为这涉及到底层的调用,我们可以不关心这一点。但我们要知道的是,就像是c+,c#一样,系统组件和将来我们编写自己
12、的组件一样都需要进行封装。模块内部声明的变量都是局部私有的变量。如果需要声明全局函数或者变量要用到_attribute_.关于blink程序的补充关于blink的代码只有configuration和module 两个.nc 文件,但是,如果只用这两个文件的是编译不出来main.exe的。这是因为singletime 并不是一个系统组件,他是一个非系统的配置文件。我们来看下他的代码singletimer.ncconfiguration SingleTimer provides interface Timer; provides interface StdControl;implementatio
13、n components TimerC; Timer = TimerC.Timerunique(Timer); StdControl = TimerC;Singletime.ncTimerc是一个时间集。Singletime是对timerc的一个封装。从其中抽象出来了一个时间timer。启示:使用配置文件可以对原有系统组件进行封装。编译时类似文件需要添加在一个文件夹内一起编译。Tinyos调度机制TinyOS中的调度机制比较简单,它仅设置一个任务队列。关键字post将一个任务添加到任务队列中。TinyOS的调度遵循FIFS(先来先服务)规则当事件发生时发生抢占。总结Tinyos事件驱动。程序调
14、度使用任务列表,当事件发生时产生中断处理,没有事件发生时任务列表按着fifs进行处理,因为我们是在post一个个的任务,同时当事件发生时编写时间处理函数。Nesc 语言组件之间通过接口和配置文件进行联系。每个模块要声明自己使用和提供的接口,当提供一接口,就要实现其command函数,当使用一个接口就要实现其event函数。调用command函数时使用call关键字,发送event事件时使用signal关键字。认识到tinyos程序是层次化的。命令由顶层向底层传递,而事件有底层向顶层传递。函数和接口通过一步步的封装成为模块,模块又可以通过配置文件的封装成为新的组件。编译的过程中,自定义的组件都要
15、一起编译。系统中所有的应用程序都放在 opt/tinyos-1.x/apps中系统中所有的系统组件都方在 opt/tinyos-1.x/tos/system下系统中所有的接口都放在 opt/tinyos-1.x/tos/interface通过命令make platform docs可以在 opt/tinyos-1.x/doc/nesc/生成source tree和组件关系图。TinyOS学习笔记2-连接永远箭头左边是use关于通信的时候顶级配置文件要使用箭头 configuration RfmToLeds implementation components Main, RfmToInt, In
16、tToLeds; Main.StdControl - IntToLeds.StdControl; Main.StdControl - RfmToInt.StdControl; RfmToInt.IntOutput - IntToLeds.IntOutput; configuration RfmToInt provides interface StdControl; uses interface IntOutput; 在这里此地使用的是 use 接口 是因为 rfmtoint要调用intoutput接口 顶级配置文件 可以把他方在左边 是他调用别人 同时有些数据结构使用时要加上头文件才可以用im
17、plementation components RfmToIntM, GenericComm; IntOutput = RfmToIntM; StdControl = RfmToIntM; RfmToIntM.ReceiveIntMsg - GenericComm.ReceiveMsgAM_INTMSG; RfmToIntM.CommControl - GenericComm;sense程序中configuration Sense / this module does not provide any interfaceimplementationcomponents Main, SenseM,
18、 LedsC, TimerC, Photo;Main.StdControl - SenseM;Main.StdControl - TimerC;SenseM.ADC - Photo;SenseM.ADCControl - Photo;SenseM.Leds - LedsC;SenseM.Timer - TimerC.Timerunique(Timer);和configuration Sense / this module does not provide any interfaceimplementation components Main, SenseM, LedsC, TimerC, De
19、moSensorC as Sensor; Main.StdControl - Sensor; Main.StdControl - TimerC; Main.StdControl - SenseM; SenseM.ADC - Sensor; SenseM.ADCControl - Sensor; SenseM.Leds - LedsC; SenseM.Timer - TimerC.Timerunique(Timer);两者相同 一个是使用了main.stdcontrol接口来初始化sensor 但在模块内部没有实现其中的adccontrol接口另一个是没有使用main进行初始化而是使用了adcc
20、ontrol接口在模块中初始化 语句如下:command result_t StdControl.init() return rcombine(call ADCControl.init(), call Leds.init();/*从这里我们可以知道 使用了一个接口但并不一定要在实现中出现其中的函数。今日完成: 编译blink程序 并且改名之后再次编译都成功 将blink中的red改为green也成功 最后绿灯每秒亮一次 编译了sense程序 得知该程序是在传感器中取得数据,并且将数据通过led显示出来 得到的硬件依赖于光线或者温度传感器。 看了关于传感器之间的通信,阅读其中的源代码发现use的
21、另类使用方法。 在下载程序到传感器的时候 扳子和传感器的接口一定要连接紧密同时也许要 reset编程主板。 有些程序要使用头文件 发现一些程序在lib以下以前没有注意到过 photo D:学习tinyos-1.xtossensorboardsbasicsb下面。TinyOS学习笔记3弄明白了 cnttoledandrfm和rfmtoled两个程序知道了组件和组件之间如何进行工作同时 只有前者的程序时 也可以接收到数据但接收到的数据没有编写事件处理函数 所以不显示。初次使用模拟器进行模拟节点的之间的数据通信configuration RfmToLeds implementation compon
22、ents Main, RfmToInt, IntToLeds; Main.StdControl - IntToLeds.StdControl; Main.StdControl - RfmToInt.StdControl; RfmToInt.IntOutput - IntToLeds.IntOutput;includes IntMsg;configuration RfmToInt provides interface StdControl; uses interface IntOutput;implementation components RfmToIntM, GenericComm; Int
23、Output = RfmToIntM; StdControl = RfmToIntM; RfmToIntM.ReceiveIntMsg - GenericComm.ReceiveMsgAM_INTMSG; RfmToIntM.CommControl - GenericComm;includes IntMsg;module RfmToIntM provides interface StdControl; uses interface ReceiveMsg as ReceiveIntMsg; interface IntOutput; interface StdControl as CommCont
24、rol; implementation command result_t StdControl.init() return call CommControl.init(); command result_t StdControl.start() return call CommControl.start(); command result_t StdControl.stop() return call CommControl.stop(); event TOS_MsgPtr ReceiveIntMsg.receive(TOS_MsgPtr m) IntMsg *message = (IntMs
25、g *)m-data; call IntOutput.output(message-val); return m; event result_t IntOutput.outputComplete(result_t success) return SUCCESS; 进行了 通信结点的试验 结果和预期想符合当两者都同cnttoledandrfm时 都是以广播形式向外发送数据 只有当另一者为rfmtoled时才进行了接收事件的处理使leds组件工作。 分配ip时 如果找不到设备可以手动添加输入 数据显示文档的阅读。TinyOS学习笔记4uartcomm组件是什么 发送和接受数据的一个组件 封装于底层
26、 类似于 genericcomm该程序是通过adc先接受来自传感器上的数据然后通过通信组件将数据发送到本地 然后接受 再读取数据并且把他显示在pc上面。configuration Oscilloscope implementation components Main, OscilloscopeM , TimerC , LedsC , DemoSensorC as Sensor , UARTComm as Comm; Main.StdControl - OscilloscopeM; Main.StdControl - TimerC; OscilloscopeM.Timer - TimerC.Ti
27、merunique(Timer); OscilloscopeM.Leds - LedsC; OscilloscopeM.SensorControl - Sensor; OscilloscopeM.ADC - Sensor; OscilloscopeM.CommControl - Comm; OscilloscopeM.ResetCounterMsg - Comm.ReceiveMsgAM_OSCOPERESETMSG; OscilloscopeM.DataMsg - Comm.SendMsgAM_OSCOPEMSG;module OscilloscopeM provides interface
28、 StdControl; uses interface Timer; interface Leds; interface StdControl as SensorControl; interface ADC; interface StdControl as CommControl; interface SendMsg as DataMsg; interface ReceiveMsg as ResetCounterMsg; implementation uint8_t packetReadingNumber; uint16_t readingNumber; TOS_Msg msg2; uint8
29、_t currentMsg; command result_t StdControl.init() call Leds.init(); call Leds.yellowOff(); call Leds.redOff(); call Leds.greenOff(); /turn on the sensors so that they can be read. call SensorControl.init(); call CommControl.init(); atomic currentMsg = 0; packetReadingNumber = 0; readingNumber = 0; d
30、bg(DBG_BOOT, OSCOPE initializedn); return SUCCESS; command result_t StdControl.start() call SensorControl.start(); call Timer.start(TIMER_REPEAT, 125); call CommControl.start(); return SUCCESS; command result_t StdControl.stop() call SensorControl.stop(); call Timer.stop(); call CommControl.stop(); return SUCCESS; task void dataTask() struct OscopeMsg *pack; atomic pack = (struct Oscop
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1