# softwareTimer **Repository Path**: aHeiDaBai/software-timer ## Basic Information - **Project Name**: softwareTimer - **Description**: 这是一个C语言编写的通过硬件定时器拓展软件定时器的库,可用于STM32等单片机 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2024-12-21 - **Last Updated**: 2025-03-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: stm32, timer ## README # SOFTWARE TIMER ## 1. 关于此项目 这是一个C语言编写的通过硬件定时器拓展软件定时器的库。 在开发嵌入式程序时,通常: 1. 通常对于MCU来说,硬件定时器的数量是有限的,而且一些任务不需要严格定时,这时使用硬件定时器就会有点浪费资源,尤其是在硬件定时器比较稀缺的时候。 2. 单片机的任务大部分都是周期性定时任务,当我们不想使用RTOS或者MCU的资源很小以至于无法使用RTOS,软件定时器提供了一个简单好用的方案。 此项目通过硬件定时器来拓展软件定时器,只要资源够用,理论上可以拓展出无限的软件定时器。 此库有以下特点: - 只依赖于C的标准库,不依赖于其他外部库 - 轻量,只有一个`.c`文件和`.h`文件,方便加入自己的项目中 - 通过一个硬件定时器延伸出无数的软件定时器 - 提供周期性定时器和一次性定时器 - 用户可以指定自己的`malloc`和`free`函数 - 提供堆内存申请成功后和即将释放时的回调函数,可用于监控内存泄露 对于C的要求:C的版本大于`C99`(如果使用的是`keil`,则需要开启`C99`模式) ## 2. 使用方法 1. 将`software_timer.c`和`software_timer.h`加入到自己的项目中 2. 将`utils_st_main`函数放入`main`函数中的死循环(super loop)中 3. 使用一个硬件定时器(`1ms`定时)调用`utils_st_tick`,为软件定时器提供时基 4. 调用各种现成的函数进行操作 下面是部分常用的函数: | 提供的方法 | 函数名 | 备注 | | ---------------------------------------- | ------------------------------- | ------------------------------------------------------------ | | 启动/恢复 定时器 | `utils_st_start_timer` | 无 | | 暂停 定时器 | `utils_st_pause_timer` | 无 | | 初始化 软件定时器 | `utils_st_init_timer` | 初始化定时器后默认是关闭定时器,需要手动开启 | | 重新设置定时周期 | `utils_st_set_timer_period` | 无 | | 重置定时器的计时 | `utils_st_reset_timer` | 无 | | 创建一次性定时器 | `utils_st_create_oneshot_timer` | 一次性定时器在定时结束后自动释放资源。此函数的返回值用来判断是否创建成功。 | | 输出所有存在的定时器信息到一个字符数组中 | `utils_st_print_timer` | 无 | ## 3. 例子 ### 3.1 周期性定时器例子 ```c #include "software_timer.h" #include // 周期函数的参数必须是void *, 返回值必须是void void timer_cb(void * data) { data = (char *)data; printf("timer was Triggered : %s!", data); } int main (void) { // 1. 创建一个周期性软件定时器对象 static utils_st_timer_t timer; // 2. 初始化这个周期性软件定时器 // 定时器的名称叫"demo timer", 它会每隔500ms调用一次timer_cb函数 // 最后一个参数是要传入timer_cb的参数 utils_st_init_timer(&timer, timer_cb, 500, "demo timer","demo"); // 3. 定时器初始化之后是默认关闭的,需要我们手动开启 utils_st_start_timer(&timer); ...... while (1) { utils_st_main(); } } void hardware_timer_1ms() { utils_st_tick(); // 硬件定时器1ms中断为软件定时器提供时基 } ``` ### 3.2 一次性定时器例子 ```c #include "software_timer.h" #include // 周期函数的参数必须是void *, 返回值必须是void void timer_cb(void * data) { data = (char *)data; printf("timer was Triggered : %s!", data); } int main (void) { // 1. 创建一个一次性定时器 // 定时器的名称叫"demo timer", 它会每隔1000ms后调用一次timer_cb函数 // 定时结束之后定时器自动销毁,释放资源 utils_st_timer_t * timer = utils_st_create_oneshot_timer( timer_cb, 1000,"demo timer","demo"); if (timer == NULL) { // 创建失败 } else { // 2. 创建成功,但定时器初始化之后是默认关闭的,需要我们手动开启 utils_st_start_timer(&timer); } ...... while (1) { utils_st_main(); } } void hardware_timer_1ms() { utils_st_tick(); // 硬件定时器1ms中断为软件定时器提供时基 } ``` ## 4. 其他 `software_timer.c`中有两个函数,他们分别在申请内存成功和即将释放内存时调用,可以辅助判断定时器内存是否泄露 ```c void utils_st_malloc_cb(const utils_timer_t *const timer) { // printf("malloc timer pointer: %p\n", (void*)timer); } void utils_st_free_cb(const utils_timer_t *const timer) { // printf("free timer pointer: %p\n", (void*)timer); } ``` `software.h`中可以修改下面两个宏来添加自己的内存函数(默认是使用C标准库中的`malloc`和`free`): ```c #define st_malloc malloc #define st_free free ```