CC2538之TinyOS例程实验:3/4-timer nesC编程最难理解部分参数化接口讲解

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

前面两篇已经介绍了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



分析的是interface Timer<TMilli>,那么首先必须先看的是Timer.h,目录:tinyos-main-release_tinyos_2_1_2\tos\lib\timer
// 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>接口呢;
需要看TimerMilliC.nc ,TimerMilliP.nc(tinyos-main-release_tinyos_2_1_2\tos\system)
TimerMilliC.nc 
#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省略

通过查看cc2538cb平台的chips源码 目录tinyos-main-release_tinyos_2_1_2\tos\chips\cc2538\timer
找见HilTimerMilliC.nc 下面是部分代码,发现他提供了interface
configuration HilTimerMilliC{
  provides interface Init;
  provides interface Timer<TMilli> as TimerMilli[ uint8_t num ];
  ...
}
implementation{
      ...
}


nesC福利:
unique(..)------------提供唯一的id,每调用一次id+1,如果把interface看成是数组的话,类似于数组的下标
uniqueCount(..)---计算使用unique总次数
new-------------------用于参数化接口的components的创建,实例化

Timer的库的写法是最复杂也是最全的nesC的参数化接口写法,最好是大家通过yeti2去查看图形连接关系,然后在eclipse下查看分析源码;

参数化接口格式
interface xx<...>
{
  command;
  event;
}

实际应用我常常使用下面的的方法一样可以达到参数化接口的目的,可以参考fragpool写法或者cc2538底层的io口的写法,interface可以简化写成简单的interface结构,改为configuration和module提供接口的时候改为
configuration/module name(xx){
 provides interface_name[xx];
}
使用他采用components new name(unique(xx));

见仁见智吧,哪一种方法都行,喜欢第二种是代码阅读稍微直观一点。

在此大家可以看到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单位的定时器使用实验,代码省略

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值