定时器应用指导¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
功能概述¶
定时器通常指SoC或MCU内部的硬件外设,可周期性地触发系统中断。系统可依据该中断信号切换任务,或实现分频输出。
从硬件层面上,定时器可分为以下几类:
SysTick
系统滴答定时器,用于周期性地提供计时功能。该定时器可以周期性地产生中断信号,是系统的心跳时钟,用于切换任务或为任务分配时间片。
通用定时器
除了具备基本定时器功能外,还可以提供输入捕捉、输出比较和连接其他传感器接口的功能。
基本定时器
无外部输入或输出引脚,主要用于时基计数和定时。
高级定时器
除了具备通用定时器功能外,还可以提供电机控制、数字电源应用、死区时间可编程的互补输出等功能。
RTC
提供实时时间和日期。
看门狗
监测系统是否出现异常。
定时器背景¶
介绍¶
定时器可以产生中断,通知CPU特定事件已发生。这样CPU无需阻塞等待某一任务的结果,在等待期间可以运行其他功能。这种方式提高了效率,使系统整体运行更流畅、更高效、响应更快,从而提升用户体验并拓展应用范围。
定时器分类¶
定时器从广义上可分为硬件定时器和软件定时器。硬件定时器是软件定时器的基础。软件定时器在硬件定时器的基础上进行软件上的扩展,理论上没有个数限制,但其计时精度较低,且数量越多,差值越大。
硬件定时器¶
硬件定时器分为SysTick、基本定时器、通用定时器、高级定时器、RTC定时器和看门狗定时器等。在系统稳定运行过程中,这些定时器各司其职。
硬件定时器工作原理框图如下所示:
定时器工作原理如下:
时钟信号(CLK)输入至触发控制器。
触发控制器将信号输出到预分频器。
预分频后的信号被输入至计数器。
当计数器数值达到自动装载器数值时(根据定时器类型判断处理),若已使能中断,则定时器产生溢出中断。
上述流程即为定时器的工作原理概述,以下几类定时器的工作原理与此基本一致。
SysTick¶
SysTick(系统滴答定时器)又称心跳定时器。每次产生SysTick中断时,系统会切换任务,以此完成对任务的时间片分配以及任务切换。切换任务示意图见 图2。
内部结构简图见 图3。 RCC使用AHB时钟经8分频后,为 SysTick提供外部时钟源。
基本定时器¶
基本功能如下:
自动装载的累加计数器。
触发DAC的同步电路。
更新时间产生中断请求。
可编程预分频器。
原理概念图见 图1。 时钟从内部或者外部提供给预分频器,经过分频将信号提供给计数寄存器。当计数器达到自动重装载寄存器中的数值时,即满足中断产生的条件。如果已开启中断功能,此时即可触发中断,完成定时任务。由上可知,定时是通过预分频器和自动重装载寄存器的设置完成的。
通用定时器¶
除具备基本定时器功能外,还具有以下功能:
支持向上计数、向下计数、向上或向下计数的自动装载计数器。
独立通道。
使用外部信号控制定时器和定时器互连的同步电路。
支持针对定位的增量编码器和霍尔传感器电路。
触发输入可作为外部时钟,或者用于按周期进行电流管理。
原理概念图见 图1。 通用定时器和基本定时器的基本原理相同,其扩展功能只是在基本功能上进行了一些简单扩展,属于定时器的应用范畴,此处不再赘述。
高级定时器¶
除具备通用定时器功能外,还具有以下功能:
死区时间可编程的互补输出。
仅在指定周期数后更新定时计数器。
中断信号输入,使计时器的输出信号处于重置状态或已知状态。
设置循环次数,实现重复计数。
原理概念图见 图1。 高级定时器和通用定时器、基本定时器的基本原理相同,同样是对基本功能的扩展。其中,死区时间功能对PWM应用非常实用。
RTC定时器¶
实时时钟(RTC)是一个独立的BCD定时器或计数器。它可以将设备从休眠态唤醒,用于管理设备的低功耗模式。在相应配置下,可提供时钟日历功能。模块重启后,RTC时间将被重置。当注网成功后,RTC时间将会更新。其硬件框图如下所示:
看门狗定时器¶
看门狗用于监测和处理由软件错误导致的故障。当计数器递减到0(或者递增到设定的计数值)时,将触发系统复位。它有专用的低速时钟驱动,即使主时钟发生故障也依然有效。通过可配置的时间窗口,可以调整看门狗的时间。所谓“喂狗”,即是对计数器重新赋初值(或计数器清零)。其原理框图如下:
软件定时器¶
软件定时器实现的基础是硬件支持定时任务设置。
其实现逻辑是建立一个链表(或二叉树等其他数据结构)。设置新的软件定时器时,记录到期时间并将其加入到链表中(或者二叉树中)。每次选取最近的软件定时器到期时间,并将其设置到硬件定时器中。当硬件定时器中断触发时,即可执行到期的硬件定时任务,并在其中处理相应的软件定时器任务。下次到期后,选取最近的软件定时器到期时间重新设置到硬件定时器中。如此循环,即可实现软件定时器。从上述原理可以看出,软件定时器无法达到硬件定时器的精准,但是可以突破硬件定时器的数量限制。实现逻辑框图如下:
步骤 1
记录当前添加的软件定时器的到期时间,并加入到软件定时器链表中。步骤 2
遍历软件定时器链表并排序,选取最小的到期时间,将其设置到硬件定时器中。步骤 3
硬件定时器到期后,遍历软件定时器链表,执行此定时器注册的事件,并将到期的节点从软件定时器链表中删除。步骤 4
判断软件定时器链表是否为空。若为空,则退出流程。
以上仅为软件定时器实现的一种简单方式,并非最佳方式。针对不同场景,实际实现会进行数据结构的选型和优化。以上只是介绍其实现的基本原理。
UniRTOS模块定时器分为两种:硬件定时器和软件定时器。硬件定时器用于内核侧,软件定时器开放给应用层使用。
定时器API¶
头文件¶
qosa_sys.h
函数概览¶
函数名 |
功能描述 |
|---|---|
qosa_timer_create() |
创建定时器 |
qosa_timer_start() |
启动定时器 |
qosa_timer_stop() |
停止定时器 |
qosa_timer_is_running() |
检查定时器运行状态 |
qosa_timer_delete() |
删除定时器 |
函数详解¶
qosa_timer_create¶
功能描述
创建定时器,并进行初始化,为定时器分配内存并设置回调函数。函数原型
int qosa_timer_create(qosa_timer_t* timerRef,
void (*callBackRoutine)(void*),
void* argv)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
timerRef |
输出 |
qosa_timer_t* |
指向定时器句柄指针的地址,用于接收创建的定时器 |
callBackRoutine |
输入 |
void ()(void) |
定时器回调函数指针,定时器到期时调用 |
argv |
输入 |
void * |
传递给回调函数的用户参数 |
返回值说明
QOSA_ERROR_OK:函数执行成功
QOSA_ERROR_PARAM_INVALID:定时器参数无效
QOSA_ERROR_NO_MEMORY:申请空间失败
备注
回调函数应尽量简短,避免执行耗时操作。
创建失败时不会分配任何资源,无需清理。
qosa_timer_start¶
功能描述
启动定时器,设置定时时间和循环模式。定时器到期后会调用创建时注册的回调函数。函数原型
int qosa_timer_start(qosa_timer_t timerRef,
qosa_uint32_t set_Time,
qosa_bool_t cyclicalEn)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
timerRef |
输入 |
qosa_timer_t |
定时器句柄,由 qosa_timer_create() 创建。 |
set_Time |
输入 |
qosa_uint32_t |
定时时间。单位:毫秒。 |
cyclicalEn |
输入 |
qosa_bool_t |
循环模式使能。 |
返回值说明
QOSA_ERROR_OK:函数执行成功
QOSA_ERROR_PARAM_IS_NULL:定时器参数无效
QOSA_ERROR_GENERAL:中断定时器执行失败
QOSA_ERROR_TIMER_START_ERR:普通定时器执行失败
备注
循环定时器每次到期后自动重启,直至调用 qosa_timer_stop() 进行停止。
单次定时器触发一次回调后自动停止。
支持动态修改定时参数。重复调用 qosa_timer_start() 会覆盖之前的设置。
qosa_timer_stop¶
功能描述
停止定时器。停止后定时器状态变为 QOSA_FALSE,不再触发回调函数。函数原型
int qosa_timer_stop(qosa_timer_t timerRef)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
timerRef |
输入 |
qosa_timer_t |
定时器句柄 |
返回值说明
QOSA_ERROR_OK:函数执行成功
QOSA_ERROR_PARAM_IS_NULL:定时器参数无效
QOSA_ERROR_GENERAL:中断定时器停止失败
QOSA_ERROR_TIMER_DELETE_ERR:普通定时器停止失败
备注
未启动的定时器调用此函数不会产生错误。
停止后,定时器可通过调用 qosa_timer_start() 重新启动。
qosa_timer_is_running¶
功能描述
检查定时器运行状态。函数原型
qosa_bool_t qosa_timer_is_running(qosa_timer_t timerRef)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
timerRef |
输入 |
qosa_timer_t |
定时器句柄 |
返回值说明
QOSA_TRUE:定时器正在运行
QOSA_FALSE:定时器未运行或参数无效
qosa_timer_delete¶
功能描述
删除定时器,并释放所有相关资源。函数原型
int qosa_timer_delete(qosa_timer_t timerRef)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
timerRef |
输入 |
qosa_timer_t |
定时器句柄 |
返回值说明
QOSA_ERROR_OK:函数执行成功
QOSA_ERROR_PARAM_IS_NULL:定时器参数无效
QOSA_ERROR_TIMER_DELETE_ERR:定时器删除失败
备注
删除前会自动停止定时器。
删除后的定时器句柄不可再使用。
应在不再使用定时器时调用此函数,避免资源泄露。
枚举定义¶
qosa_errcode_os_e¶
结果码枚举定义如下:
typedef enum
{
QOSA_ERROR_PARAM_INVALID
QOSA_ERROR_NO_MEMORY
QOSA_ERROR_PARAM_IS_NULL
QOSA_ERROR_GENERAL
QOSA_ERROR_TIMER_START_ERR
QOSA_ERROR_TIMER_DELETE_ERR
...
}qosa_errcode_os_e;
成员 |
说明 |
|---|---|
QOSA_ERROR_PARAM_INVALID |
参数无效 |
QOSA_ERROR_NO_MEMORY |
内存不足 |
QOSA_ERROR_PARAM_IS_NULL |
参数为空 |
QOSA_ERROR_GENERAL |
通用错误 |
QOSA_ERROR_TIMER_START_ERR |
定时器启动失败 |
QOSA_ERROR_TIMER_DELETE_ERR |
定时器删除失败 |
应用逻辑流程图¶
示例代码¶
完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/system/timer/timer_demo.c 。
运行结果输出:
定时器创建成功
定时器启动成功,模式:循环,间隔:1000ms
定时器正在运行
主程序运行中...
[定时器回调] 测试定时器: 第1次触发
主程序运行中...
主程序运行中...
[定时器回调] 测试定时器: 第2次触发
主程序运行中...
主程序运行中...
[定时器回调] 测试定时器: 第3次触发
主程序运行中...
主程序运行中...
[定时器回调] 测试定时器: 第4次触发
主程序运行中...
主程序运行中...
[定时器回调] 测试定时器: 第5次触发
定时器已停止
定时器已删除
常见问题¶
定时器失效有哪些可能?¶
系统压力过大,导致定时器回调函数未能正常执行。
定时器已经被删除或停止。
定时器是否会因为更新网络时间导致定时器超时时间错乱?¶
不会。定时器的超时时间不受网络时间更新影响。
关机和深休眠情况下定时器表现怎样?¶
关机后: 定时器不再工作。重启后需要重新创建并启用定时器。
深休眠后: 定时器不再运行,唤醒后也不再起作用,需要重新设置。
在深休眠情况下,RTC可以唤醒模块,使其正常运行。
硬件定时器软件定时器的区别?¶
硬件定时器系统个数是有限的,软件定时器理论上只要系统资源足够,没有个数限制。
软件定时器基于硬件定时器实现。