前面两篇已经介绍了TinyOS的优点,nesC的事件代码分析,可以通过视频去学会自己编写基本应用
如果说interface,event你还觉得TinyOS的nesC的引入吸引不了你的话,那么现在咱们进入个人认为TinyOS编程最难的地方也是整个最吸引我的地方
参数化接口(parameterized interface),其中我们早就接触到了-blink例程
大家要注意的是对于TinyOS来说,components包含configuration和module,interface都是可以把他理解成一个数组元素,不要死板的理解成一个C文件,他们都是一个元素,当然也可以实例化n个;这就是参数化接口的意义!也是本人最喜欢使用TinyOS的最重要的原因;
至此咱们可以想一下,假设n路传感器,代码实现(驱动是一样的),就可以使用参数接口化来编写代码,有一点点对象的意思
回忆一下blink代码:
configuration BlinkAppC
{
}
implementation
{
components MainC, BlinkC, LedsC;
components new TimerMilliC() as Timer0;
components new TimerMilliC() as Timer1;
components new TimerMilliC() as Timer2;
BlinkC -> MainC.Boot;
BlinkC.Timer0 -> Timer0;
BlinkC.Timer1 -> Timer1;
BlinkC.Timer2 -> Timer2;
BlinkC.Leds -> LedsC;
}TimerMilliC()的组件只有一份代码,为什么可以多个实例组件呢,这个也就是参数化接口的作用,相同的比较常常能看见的还有LedsC连接到底层发现IO口部分的参数化接口部分可以随意的设定led对应的IO口;
前面的blip和printf例程都使用到了timer,为什么没有讲解timer的用意也在此,这个参数化接口是nesC语言的杀手锏;
参数化接口有一点类似C语言的定义 uint_8 array[] = {0,0,0,0};的意思,只不过这个数组可以广域化一下,如components,interface,module等
带来的好处是显而易见的,一次编程,多次使用,如内存池pool,fragpool等,理解参数化编程最好的代码应该是fragpool
// The TinyOS Timer structures are discussed in TEP 102.
#ifndef TIMER_H
#define TIMER_H
// @note TSecond is an extension to be added in a successor to TEP 102
typedef struct { int notUsed; } TSecond;
typedef struct { int notUsed; } TMilli;
typedef struct { int notUsed; } T32khz;
typedef struct { int notUsed; } TMicro;
#define UQ_TIMER_SECOND "HilTimerMicroC.Timer"
#define UQ_TIMER_MILLI "HilTimerMilliC.Timer"
#define UQ_TIMER_32KHZ "HilTimer32khzC.Timer"
#define UQ_TIMER_MICRO "HilTimerMicroC.Timer"
#endif再来看看接口Timer,为什么blink的使用uses interface Timer<TMilli>也就是跟了参数,这是咱们之前没有分析过的Timer.nc,接口文件,目录:tinyos-main-release_tinyos_2_1_2\tos\lib\timer
interface Timer<precision_tag>
{
// basic interface
/**
* Set a periodic timer to repeat every dt time units. Replaces any
* current timer settings. Equivalent to startPeriodicAt(getNow(),
* dt). The <code>fired</code> will be signaled every dt units (first
* event in dt units).
*
* @param dt Time until the timer fires.
*/
command void startPeriodic(uint32_t dt);
/**
* Set a single-short timer to some time units in the future. Replaces
* any current timer settings. Equivalent to startOneShotAt(getNow(),
* dt). The <code>fired</code> will be signaled when the timer expires.
*
* @param dt Time until the timer fires.
*/
command void startOneShot(uint32_t dt);
/**
* Cancel a timer.
*/
command void stop();
/**
* Signaled when the timer expires (one-shot) or repeats (periodic).
*/
event void fired();
// extended interface
/**
* Check if timer is running. Periodic timers run until stopped or
* replaced, one-shot timers run until their deadline expires.
*
* @return TRUE if the timer is still running.
*/
command bool isRunning();
/**
* Check if this is a one-shot timer.
* @return TRUE for one-shot timers, FALSE for periodic timers.
*/
command bool isOneShot();
/**
* Set a periodic timer to repeat every dt time units. Replaces any
* current timer settings. The <code>fired</code> will be signaled every
* dt units (first event at t0+dt units). Periodic timers set in the past
* will get a bunch of events in succession, until the timer "catches up".
*
* <p>Because the current time may wrap around, it is possible to use
* values of t0 greater than the <code>getNow</code>'s result. These
* values represent times in the past, i.e., the time at which getNow()
* would last of returned that value.
*
* @param t0 Base time for timer.
* @param dt Time until the timer fires.
*/
command void startPeriodicAt(uint32_t t0, uint32_t dt);
/**
* Set a single-short timer to time t0+dt. Replaces any current timer
* settings. The <code>fired</code> will be signaled when the timer
* expires. Timers set in the past will fire "soon".
*
* <p>Because the current time may wrap around, it is possible to use
* values of t0 greater than the <code>getNow</code>'s result. These
* values represent times in the past, i.e., the time at which getNow()
* would last of returned that value.
*
* @param t0 Base time for timer.
* @param dt Time until the timer fires.
*/
command void startOneShotAt(uint32_t t0, uint32_t dt);
/**
* Return the current time.
* @return Current time.
*/
command uint32_t getNow();
/**
* Return the time anchor for the previously started timer or the time of
* the previous event for periodic timers. The next fired event will occur
* at gett0() + getdt().
* @return Timer's base time.
*/
command uint32_t gett0();
/**
* Return the delay or period for the previously started timer. The next
* fired event will occur at gett0() + getdt().
* @return Timer's interval.
*/
command uint32_t getdt();
}那么对于cc2538cb平台,谁提供了Timer<TMilli>接口呢;#include "Timer.h"
generic configuration TimerMilliC() {
provides interface Timer<TMilli>;
}
implementation {
components TimerMilliP;
// The key to unique is based off of TimerMilliC because TimerMilliImplP
// is just a pass-through to the underlying HIL component (TimerMilli).
Timer = TimerMilliP.TimerMilli[unique(UQ_TIMER_MILLI)];
}TimerMilliP.nc省略configuration HilTimerMilliC{
provides interface Init;
provides interface Timer<TMilli> as TimerMilli[ uint8_t num ];
...
}
implementation{
...
}
new-------------------用于参数化接口的components的创建,实例化
interface xx<...>
{
command; event;
}在此大家可以看到components和interface的编程可以使用参数,使用new创建并完成实例化,实例个数限制和参数有关,更多的需要自己去阅读代码,这玩意只能自己去阅读清楚
例程目录tinyos-main-release_tinyos_2_1_2\apps\cc2538_Test\timerTest
包含文件:
Makefile
TimerAppC.nc---configuration
TimerC.nc
timertest例程为ms单位的定时器使用实验
Makefile
COMPONENT=TimerAppC
CFLAGS += -DUSE_TIMER_HANDLER
#CFLAGS += -DUSE_UART_HANDLER
#CFLAGS += -DUSE_RF_HANDLER
CFLAGS += -DNOT_USE_PRINTFC_BUT_USE_PRINT
include $(MAKERULES)不做介绍,不清楚可以去看blink和printf讲解
TimerAppC.nc
configuration TimerAppC
{
}
implementation
{
components MainC, TimerC;
components new TimerMilliC() as Timer1;
TimerC -> MainC.Boot;
TimerC.Timer1 -> Timer1;
}阅读省略
TimerC.nc
/*******************************************************************
*实验4----毫秒定时器实验
*节点需求数1
*编译命令make cc2538cb
********************************************************************/
#include "Timer.h"
#include "printf.h"
module TimerC
{
uses interface Timer<TMilli> as Timer1;
uses interface Boot;
}
implementation
{
task void time1_Task();
uint16_t Timer_counter=0;
/***************************************************
*启动事件
****************************************************/
event void Boot.booted()
{
/**开启一秒的周期性定时器(单位毫秒) Timer1**/
call Timer1.startPeriodic( 1000 );
}
/***************************************************
*任务time1_Task
****************************************************/
task void time1_Task()
{
printf("Timer1 fired: %u\n", Timer_counter++);
}
/***************************************************
*Timer1定时时间到事件
****************************************************/
event void Timer1.fired()
{
/****提交time1_Task任务***/
post time1_Task();
}
}
阅读省略例程目录tinyos-main-release_tinyos_2_1_2\apps\cc2538_Test\TimerMicro
TimerMicro例程为us单位的定时器使用实验,代码省略

本文探讨TinyOS的nesC编程中最具挑战性的部分——参数化接口,特别是在CC2538平台上的应用。通过举例解释如何使用参数化接口处理多路传感器,强调其类似C语言数组的概念,实现代码复用。文章以timer为例,介绍TimerAppC.nc和TimerC.nc配置和模块,并提供相关例程目录供读者参考,以帮助理解参数化编程在内存池和fragment pool中的应用。

被折叠的 条评论
为什么被折叠?



