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

2023-05-16

一、定时器(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)要小于发送数据的间隔,不然会丢失数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[BLE]CC2640之定时器(Clock)事件 的相关文章

  • BLE蓝牙协议 — 自适应调频算法简单实现

    写在前面 转载文章 若有不妥 通知后我会立即删除 最近看了大神刘权写的 BLE4 0低功耗蓝牙协议总结 感觉收获颇丰 其中有一节是讲解蓝牙的自适应调频算法的 但是代码实现不方便阅读 原文是这样的 小生不才 斗胆做了一下调整 还望大神海涵 下
  • 蓝牙协议介绍

    1 广播 ADV Advertising 1 1 BLE 报文结构 BLE引入access address 概念 用来指明接收者身份 概 其中 0x8E89BED6 这个access address 比较特殊 它表示要发给周边所有设备 即广
  • Dialog DA14585——基本硬件资源配置

    GPIO DA14585共有3中类型的封装 WLCSP34pin QFN40pin QFN48pin 除去专用的RST GND XTAL ANT VBAT脚后 分别有14 25 32个IO口可用 目前最常用的封装类型是QFN40 处理单元
  • 如何在C++中使用clock()

    我怎么打电话clock in C 例如 我想测试线性搜索在数组中查找给定元素需要多长时间 include
  • 画布游戏计时器

    我正在制作一个 HTML5 Canvas 游戏 其中有一个在画布上移动的矩形 目标是尽可能长时间地躲避在画布上移动的多个球 但我正在努力设置一个计时器 以在球击中矩形时显示您的时间 得分 矩形由上 下 左 右键移动 任何了解这方面知识的人可
  • 使用clock()函数调度任务时出现问题

    我想以不同的时间间隔安排任务 0 1 秒 0 9 秒 2 秒等 我使用 Clock C 函数返回自模拟开始以来的滴答数 并使用 CLOCKS PER SEC 将滴答数转换为秒 但我注意到当瞬时为浮点时 任务不会被调度 但是当它是一个整数 这
  • Clock() - C 函数的执行时间

    我正在尝试测量 C 代码块的执行时间 我的代码中有类似这样的内容 clock t begin end double time spent begin clock ATL dsymv 122 n alfa A n X 1 beta Y 1 e
  • 调度周期性任务和时钟漂移

    我想安排一个每隔 X 小时执行一次的定期任务 我有一个用 Java 编写的服务 我正在考虑创建一个长时间运行的后台线程 只要服务启动 它就永远运行 我如何确保我们每 X 小时执行一次任务 我的主机上的时钟漂移是我应该担心的问题吗 我知道如果
  • 自首次启动以来的时间

    我正在开发一个 Android 应用程序 并遇到了确定系统首次启动时间的问题 我的意思是我需要测量多少从设备首次启动起已经过了时间 我知道有关侦听 ACTION BOOT COMPLETED 并将任何内容保存在 SharedPreferen
  • C++:Linux 中的计时(使用 Clock())不同步(由于 OpenMP?)

    在程序的顶部和结尾 我使用clock 来计算程序需要多长时间才能完成 不幸的是 它似乎只花费了报告时间的一半 我用 time 命令仔细检查了这一点 我的程序报告 45 86秒完成 时间命令报告 真实0米22 837秒 用户 0m45 735
  • 由于分析部分之外的代码,使用clock_gettime()进行的时间测量不合理

    我正在使用下面的 C 程序 用 gcc 编译 来测量给定代码部分的计算时间 问题是当usleep 使用函数outside正在分析的代码部分 获得了不同的测量结果elapsed time include
  • Android:深度睡眠的时间间隔(System.nanoTime()、System.currentTimeMillis()、SystemClock.elapsedRealtimeNanos())

    我正在实现一个应用程序 其 API 级别最低为 14 这很重要 并且需要一致的间隔测量 不需要毫秒精度 它只需要始终计算时间 经过的秒数 到目前为止 为了处理时间间隔 我知道这些解决方案 System nanoTime 如果 Android
  • 单击按钮后开始倒计时

    我正在创建一个带有计时器倒计时的儿童游戏 该游戏在用户单击按钮后开始 我正在使用的代码可以毫无问题地启动倒计时 但我希望倒计时仅在单击按钮后才开始 这是我的代码 window onload function function var cou
  • 修改系统时钟时 boost::deadline_timer 可能会失败

    可以在以下位置阅读 https svn boost org trac boost ticket 3504 https svn boost org trac boost ticket 3504 一个定期超时的deadline timer 它是
  • 如何在应用程序运行之间本地检测用户的 iPhone 时钟进度?

    休闲游戏中的一个常见漏洞是人为地提前系统时钟以在游戏中向前跳跃 iOS 设备上的应用程序如何检测此类用户时钟提前 不得涉及网络通信 当时钟提前时 不得假设应用程序已打开 运行或暂停 必须检测时钟前进 仅检测时钟回滚是不够的 理想情况下 该解
  • 如何计算时针和分针之间的角度?

    我正在尝试解决这个问题 但我仍然在努力理解解决这个问题的逻辑 hour degree 360 12 30 minutes degree 360 12 60 0 5 所以 据此 我想我可以在python中制定以下函数 def clockang
  • C `clock()` 函数只返回一个零

    The C clock 函数只返回一个零 我尝试使用不同的类型 但没有任何改进 这是一种高精度测量时间的好方法吗 include
  • STM32内部时钟

    我对 STM32F7 设备 意法半导体的 Cortex M7 微控制器 上的时钟系统感到困惑 参考手册没有充分阐明这些时钟之间的差异 SYSCLK HCLK FCLK 参考手册中阅读章节 gt RCC 为 Cortex 系统定时器 SysT
  • 在 Verilog 设计中产生时钟故障

    我正在使用 Verilog 设计芯片 我有一个 3 位计数器 我希望当计数器处于第 8 次循环时 应该有一个时钟故障 之后就可以正常工作了 在 Verilog 设计中产生时钟故障的可能方法是什么 在时钟信号上注入毛刺的一种方法是使用forc
  • extern auto 变量没有初始值设定项

    我需要在我的 C 程序中使用全局时间戳 std chrono high resolution clock now 我在头文件Header h中声明了它 include

随机推荐