[BLE]CC2640之定时器(Clock)事件

一、定时器(Clock)

     所谓定时器本质上递减计数器,当计数器减到零时可以触发某种动作的执行。这种动作可以通过回调函数来实现,当定时器计时完成后,自定义的回调函数会立即被调用。回调函数可以用来实现闪灯、或者执行其他的动作。需要注意的是一定要避免在回调函数中使用阻塞调用(例如调用任何可以阻塞或删除定时器任务的函数)。

    定时器分为单次定时器和周期性定器。


三、试验平台

Software Version:BLE_STACK_CC26XX_2.1.0

Hardware Version:CC2640/CC2650

IDE:IAR 7.40

四、定时器的创建

    TI-RTOS可以为应用程序提供定时器及相关服务,用来定期轮询,应用程序中可以有任意数量的定时器(只受限于可用RAM空间的大小),util.c中有关于Clock使用的各个函数。

    定时器的时间分辨率用一个常数来配置:DEFAULT_DISCOVERY_DELAY

1、创建定时器

    定时器使用前必须由Util_constructClock()函数创建,其运行模式由该函数的参数指定。其函数原型如下:

/*********************************************************************
 * @fn      Util_constructClock
 *
 * @brief   Initialize a TIRTOS Clock instance.
 *
 * @param   pClock        - pointer to clock instance structure.
 * @param   clockCB       - callback function upon clock expiration.
 * @param   clockDuration - longevity of clock timer in milliseconds
 * @param   clockPeriod   - if set to a value other than 0, the first
 *                          expiry is determined by clockDuration.  All
 *                          subsequent expiries use the clockPeriod value.
 * @param   startFlag     - TRUE to start immediately, FALSE to wait.
 * @param   arg           - argument passed to callback function.
 *
 * @return  Clock_Handle  - a handle to the clock instance.
 */
Clock_Handle Util_constructClock(Clock_Struct *pClock,
                                 Clock_FuncPtr clockCB,
                                 uint32_t clockDuration,
                                 uint32_t clockPeriod,
                                 uint8_t startFlag,
                                 UArg arg)
{
  Clock_Params clockParams;


  // Convert clockDuration in milliseconds to ticks.
  uint32_t clockTicks = clockDuration * (1000 / Clock_tickPeriod);
  
  // Setup parameters.
  Clock_Params_init(&clockParams);
  
  // Setup argument.
  clockParams.arg = arg;
  
  // If period is 0, this is a one-shot timer.
  clockParams.period = clockPeriod * (1000 / Clock_tickPeriod);
  
  // Starts immediately after construction if true, otherwise wait for a call
  // to start.
  clockParams.startFlag = startFlag;


  // Initialize clock instance.
  Clock_construct(pClock, clockCB, clockTicks, &clockParams);
  
  return Clock_handle(pClock);
}

    创建好定时以后,根据各个参数进行定义相应的数据结构。

    关于第四个参数clockPeriod:设置为0的话是单次定时器,不为0的话是周期定时器的周期;其区别是单次定时器执行一次完成结束以后就挂了,周期性定时器只要开启一次,会一直执行,除非关掉它。并且当该参数为0时,定时器的时间分辨率按照DEFAULT_DISCOVERY_DELAY的设定执行,若非0,则定时器第一次运行时的时间分辨率按照DEFAULT_DISCOVERY_DELAY定时,之后的就按照配置的clockPeriod来执行定时。再TI给的demo代码中不能显示单次和周期定时器的区别,因为每次循环中执行中断函数时都开启了一次定时器,所以,看不出区别,只能从Clock的创建函数中的第五个参数区别。

2、定义定时器定时周期

// How often to perform periodic event (in msec)
#define SBP_PERIODIC_EVT_PERIOD               100
//2015.11.02
#define SBP_PERIODIC_EVT_PERIOD1              500
3、创建定时器事件的优先级

    在分配定时器事件的优先级时是按位分配的(协议栈中每个Task用一个16进制数按位代表事件的优先级,共16级)

// Internal Events for RTOS application
#define SBP_STATE_CHANGE_EVT                  0x0001
#define SBP_CHAR_CHANGE_EVT                   0x0002
#define SBP_PERIODIC_EVT                      0x0004
#define SBP_CONN_EVT_END_EVT                  0x0008
<span style="background-color: rgb(255, 0, 0);">#define SBP_PERIODIC_EVT1                     0x000A</span>
//2015.10.15
#define SBC_KEY_CHANGE_EVT                    0x0010
4、创建clock structure(即一个定时器的数据结构)
// Clock instances for internal periodic events.
static Clock_Struct periodicClock;
//2015.11.02  添加定时器2
static Clock_Struct periodicClock1;
5、开启定时器(双定时器同时工作)

    注意需要有各自的中断处理函数。原理是:定时器(属于硬件定时器,定时过程中不占用CPU,不影响协议栈运行)定时到了后设置事件标志位,然后在线程中判断事件标志,事件发生了就处理。PS:flag为false时,必须使用Util_startClock()函数启动定时器,不然定时器不会工作。定时器启动函数如下:

/*********************************************************************
 * @fn      Util_startClock
 *
 * @brief   Start a clock.
 *
 * @param   pClock - pointer to clock struct
 *
 * @return  none
 */
void Util_startClock(Clock_Struct *pClock)
{
  Clock_Handle handle = Clock_handle(pClock);
  
  // Start clock instance
  Clock_start(handle);
}
6、创建定时器中断函数
    在中断函数中简单的实现串口的发送。
7、定时器超时处理函数

    两个定时器可以使用同一个超时处理函数。

/*********************************************************************
 * @fn      SimpleBLEPeripheral_clockHandler
 *
 * @brief   Handler function for clock timeouts.
 *
 * @param   arg - event type
 *
 * @return  None.
 */
static void SimpleBLEPeripheral_clockHandler(UArg arg)
{
  // Store the event.
  events |= arg;

  // Wake up the application.
  Semaphore_post(sem);
}
8、关闭定时器
/*********************************************************************
 * @fn      Util_stopClock
 *
 * @brief   Stop a clock.
 *
 * @param   pClock - pointer to clock struct
 *
 * @return  none
 */
void Util_stopClock(Clock_Struct *pClock)
{
  Clock_Handle handle = Clock_handle(pClock);
  
  // Stop clock instance
  Clock_stop(handle);
}
五、总结

    曾尝试过创建一个Clock structure 而使用两个不同的事件标志,最终发现只会执行优先级高的,再次证明优先级的用途。

    定时器定时到了以后,定时器中断函数会立即执行,执行过程中不会被另外一个定时器中断函数中断,直到该中断函数执行完毕,才会执行另外一个。

     在CC2640正常工作时至少有3个线程(Task),有时只是挂起当前线程,因为需要等待信号量;没有信号量线程就被挂起,只有有了信号量,线程才会被设置为就绪态,才能在CPU空闲时执行。所以定时器定时到了会发信号量,当前线程执行完毕就会执行就绪态的线程。同时设置事件标志,信号量用于唤醒线程,事件标志(在此处即事件优先级)区分不同的事件进行不同的处理。

    在定时器中断函数中调用Task_sleep()函数来挂起当前线程。Task_sleep()函数并不能控制CPU工作模式,它只是让当前线程进入休眠,让出CPU,具体CPU要进入何种工作模式还要看有没有就绪的任务,也要看有没有配置过某些设置不让CPU进入低功耗模式等;在多任务中(比如sensortag),不管是同任务优先级的还是不同任务优先级的,每个任务都是通过Task_sleep()函数挂起自己从而让出CPU,使其他任务占有CPU,详见多任务实现。

    PS:如果使用定时器定时间隔发送数据,连接事件的最大间隔(connection interval)要小于发送数据的间隔,不然会丢失数据。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: CC2640R2F是一款广受欢迎的低功耗无线芯片,具有强大的性能和灵活的应用能力。下面是关于CC2640R2F的入门介绍。 CC2640R2F是德州仪器公司(Texas Instruments)推出的一款专为低功耗无线通信设计的芯片。它采用了ARM Cortex-M3内核,运行频率高达48MHz,内部集成了256KB的闪存和8KB的SRAM,功能强大。 CC2640R2F支持多种无线通信标准,包括蓝牙低功耗(Bluetooth Low Energy,BLE)和蓝牙5.2。它具有优异的射频性能和低功耗特性,可以实现长达几年的电池寿命。此外,CC2640R2F还具有良好的抗干扰能力和可信任的安全性能,可以满足不同应用场景的需求。 对于初学者来说,了解CC2640R2F的入门方法可以从以下几个方面入手: 1. 学习基础知识:首先,了解CC2640R2F的硬件结构和功能特性。可以查阅相关的技术手册和参考资料,深入了解芯片的主要组成部分和功能模块。 2. 硬件开发环境:为了开始使用CC2640R2F,需要准备相应的硬件开发环境。可以购买开发板或者评估板,或者自行设计底板并搭建相应的开发环境。 3. 软件开发环境:CC2640R2F的软件开发可以使用德州仪器公司提供的开发工具,如Code Composer Studio(CCS)或IAR嵌入式工具链。熟悉使用这些开发工具,可以编写并调试CC2640R2F的应用程序。 4. 学习编程:CC2640R2F的编程可以使用C语言或者基于C语言的工具。学习编程语言的基础知识,并深入了解CC2640R2F的编程接口和开发流程,可以帮助快速入门。 5. 示例和实践:德州仪器公司提供了丰富的示例代码和应用案例,可以帮助初学者更好地理解和应用CC2640R2F。通过参考这些示例,可以逐步掌握CC2640R2F的使用方法和开发技巧。 总之,CC2640R2F是一款功能强大的低功耗无线芯片,适用于各种物联网和物联网应用。初学者可以通过学习基础知识、准备开发环境、学习编程和实践等途径,快速入门并使用CC2640R2F进行开发。 ### 回答2: CC2640R2F是一款蓝牙低能耗无线芯片,具备较高的性能和低功耗的特点,适用于物联网和其他无线通信应用领域。以下是CC2640R2F的入门指南。 首先,要开始使用CC2640R2F芯片,您需要准备以下工具和材料:一个CC2640R2F开发板,JTAG调试器,用于编程的软件(如Code Composer Studio)和USB数据线。 第二步,将CC2640R2F开发板通过USB数据线连接到电脑上,并打开Code Composer Studio软件。在软件中,您可以选择使用现有的示例代码来帮助您进行快速原型开发,或者根据自己的需求进行定制开发。 第三步,使用JTAG调试器将CC2640R2F芯片与计算机连接。通过调试器,您可以在开发板上进行固件的编程和调试。在Code Composer Studio中,您可以选择下载、调试和单步执行程序。 第四步,开始开发您的应用程序。CC2640R2F支持多种通信协议,如蓝牙低能耗、Zigbee和Thread。您可以选择相应的协议,并利用CC2640R2F的特性进行开发。为了更好地了解CC2640R2F的使用和开发,可以参考官方提供的技术文档和开发板用户手册。 第五步,测试和调试您的应用程序。一旦开发完成,您可以将程序下载到CC2640R2F芯片上,并在开发板上进行测试和调试。可以利用开发板上的各种接口和传感器来验证您的应用程序的功能和性能。 最后,当您满意自己的应用程序并通过测试后,您可以考虑将CC2640R2F芯片集成到您的最终产品中。在进行产品化开发时,您需要考虑一些额外的因素,如电源管理、射频设计、外围电路设计等。 综上所述,CC2640R2F是一款功能强大且易于使用的蓝牙低能耗无线芯片,入门操作包括准备工具和材料、连接和配置开发板、开始开发应用程序、测试和调试,最终将芯片集成到您的产品中。通过深入学习和实践,您将能够灵活利用CC2640R2F芯片开发出适用于物联网和其他无线通信应用的创新解决方案。 ### 回答3: CC2640R2F是德州仪器(TI)公司推出的一款低功耗蓝牙(Bluetooth)无线通信芯片,它适用于物联网、智能家居、健康监测和可穿戴设备等领域。对于初学者来说,要入门CC2640R2F,首先需要了解它的主要特点和基本用法。 CC2640R2F采用了TI的BLE-Stack协议栈,支持标准的蓝牙5.2版本,并具有双模功能,即支持BLE和蓝牙经典模式。这意味着它不仅可以与其他BLE设备进行通信,还可以与传统的蓝牙设备兼容。此外,它具有很低的功耗和较长的电池寿命,非常适合低功耗需求的应用。 要入门CC2640R2F,可以首先了解其硬件和开发工具。CC2640R2F芯片提供了丰富的外设接口包括GPIO、SPI、UART和I2C等,可以与其他外部设备进行通信。TI也提供了相关的开发板和开发工具链,如CC2640R2-LAUNCHXL开发板和Code Composer Studio软件,供开发者进行软硬件开发和调试。 接下来,可以学习CC2640R2F的软件编程。TI提供了BLE-Stack软件包,其中包含一些示例代码和应用程序,帮助初学者快速上手。开发者可以使用C编程语言,基于BLE-Stack进行开发,实现蓝牙通信、数据传输和设备控制等功能。 另外,可以学习CC2640R2F的相关文档和参考资料,包括官方文档、用户指南和应用笔记等。通过阅读这些材料,可以更深入地了解CC2640R2F的功能和用法,并掌握开发和调试技巧。 总之,要入门CC2640R2F,需要了解其硬件特性和开发工具,学习软件编程和相关文档。随着不断的学习和实践,可以逐渐掌握CC2640R2F的开发和应用,从而在物联网和蓝牙通信领域取得更好的成果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值