本帖最后由 Jmhh247 于 2015-11-10 19:43 编辑
关键字:软件定时器;soft timer; C语言;回调函数;菜单超时;定时应用;stm32
这两天气不好,今天下班后更是下起雨来,下得还不小……利用这段时间整理了一个我常用的软件定时器模块,分享出来,希望对大家有用,同时交流。
关于软件定时器,可能大家实现的代码形式不一样,但是觉得大家应该都是喜欢用的。用过的都知道它的好处是非常多的,用到的场景也很多,比如我常用的是菜单超时啊,
开机两秒后播放个提示音啊,啪啪啪的……用的多了就会想着写自己的模块以复用。
好了,说重点:
首先是功能描述:
略,想必大家都很清楚了。
接着是模块使用:
zl_soft_timer模块.zip
(9.47 KB, 下载次数: 138)
2015-11-10 18:45 上传
点击文件名下载附件
模块
模块包含多个文件,解压后你就会发现……其实精简的话,只要一个zl_soft_timer.c 文件和一个zl_soft_timer.h 文件就够了,只不过我写得比较啰嗦……不过表担心,随后我
会给出一个 stm32 平台下的 demo 供参考。
模块的接口函数有五个如下,初始化,用户设置,循环服务等……
- /* Exported functions ------------------------------------------------------- */
- void zl_soft_timer_set(uint8_t chTimerNum, uint32_t wTime, zlfn_st_t fn_call_back);
- void zl_soft_timer_kill(uint8_t chTimerNum);
- void zl_soft_timer_init(void);
- void zl_soft_timer_loop(void);
- void zl_soft_timer_service(void);
复制代码
模块的使用很简单,首先把模块文件添加到你的工程中,然后调用接口函数即可……关于接口调用,还是有一些要求的,但也很简单的。要注意的就是三个固定接口函数的调用
位置,如下:
首先调用的就是初始化了,都懂的
- zl_soft_timer_init();
复制代码
其次是
- zl_soft_timer_loop();
复制代码
这个接口函数必须是在时标中断(心跳)里调用,定时器嘛毕竟是需要时基的。对了,说到时基,这是和定时器时间有关的,都懂的,我的习惯是 1ms……另外,我的编程风
格自己都觉得奇怪,凡是函数名带 loop 的基本都是运行在时标中断里的……凡是带 service 的基本都是运行在超级循环里的……
所以接下来这个接口函数是要放在超级循环里调用的
- zl_soft_timer_service();
复制代码
完成上面三个接口函数的正常调用后,就可以通过配置函数使用软件定时器了
先说下配置定时器函数的使用,它有三个参数,具体见注释
- /* Z L _ S O F T _ T I M E R _ S E T */
- /*-------------------------------------------------------------------------
- * 功能:设置一个定时器。
- * 参数:1.定时器编号,0 至 ZL_SOFT_TIMER_MAX_NUM;
- * 2.定时时间;
- * 3.回调函数。
- * 返回:无
- * 备注:OK.
- -------------------------------------------------------------------------*/
- void zl_soft_timer_set(uint8_t chTimerNum, uint32_t wTime, zlfn_st_t fn_call_back)
- {
- if (!s_wSoftTimerInitOK)
- {
- return;
- }
- if (chTimerNum >= ZL_SOFT_TIMER_MAX_NUM)
- {
- return; /* 超出定时器数量,直接退出 */
- }
- if (0 == wTime)
- {
- return; /* 定时时间为 0 ,直接退出 */
- }
- zl_enter_critical();
- s_tSoftTimer[chTimerNum].wTimer = wTime;
- if (NULL == fn_call_back)
- {
- s_tSoftTimer[chTimerNum].fn_call_back = zl_dummy_func_soft_timer;
- }
- else
- {
- s_tSoftTimer[chTimerNum].fn_call_back = fn_call_back;
- }
- s_tSoftTimer[chTimerNum].hwCtrl = STIMER_START;
- zl_exit_critical();
- }
复制代码
然后是解除定时器的函数,软件定时器的使用一般是执行一次就自动解除的,这个函数用的会比较少,看需求吧
- /* Z L _ S O F T _ T I M E R _ K I L L */
- /*-------------------------------------------------------------------------
- * 功能:停止指定编号的定时器。
- * 参数:1.定时器编号 0 至 ZL_SOFT_TIMER_MAX_NUM。
- * 返回:无
- * 备注:OK.
- -------------------------------------------------------------------------*/
- void zl_soft_timer_kill(uint8_t chTimerNum)
- {
- if (!s_wSoftTimerInitOK)
- {
- return;
- }
- if (chTimerNum >= ZL_SOFT_TIMER_MAX_NUM)
- {
- return; /* 超出定时器数量,直接退出 */
- }
- zl_enter_critical();
- s_tSoftTimer[chTimerNum].hwCtrl = STIMER_STOP;
- zl_exit_critical();
- }
复制代码
接下来给出两个例子
例子1, 是软件定时器用最多的用法,只执行一次回调函数就自动解除了
先是配置软件定时器
- /* 软件定时器测试 */
- zl_soft_timer_set(0, 3000, st_start_play_audio); /* 开机3秒后播放提示音 */
复制代码
然后是回调函数的原型这样的,这里只是串口输出来模拟一个功能的实现
- void st_start_play_audio(void)
- {
- zl_printf_string("
start play audio!
");
- }
复制代码
例子2,说真的,好饿,我不想写了,我得去吃饭了……这是个能周期运行的
- zl_soft_timer_set(1, 5000, st_soft_timer_test); /* 5秒输出一次串口数据 */
- zl_soft_timer_set(2, 500, st_led_flash); /* 500ms 取反一次LED状态 */
复制代码
重点是函数原型,是这样的
- void st_soft_timer_test(void)
- {
- static uint32_t s_wCnt = 0;
- s_wCnt++;
- zl_printf("
soft timer cnt: %d
", s_wCnt);
- zl_soft_timer_set(1, 5000, st_soft_timer_test);
- }
复制代码
- void st_led_flash(void)
- {
- static uint32_t s_wFlashFlag = 0;
- if (s_wFlashFlag)
- {
- bsp_led_ctrl(LED_STA_OFF, LED_Pin_1);
- s_wFlashFlag = 0;
- }
- else
- {
- bsp_led_ctrl(LED_STA_ON, LED_Pin_1);
- s_wFlashFlag = 1;
- }
- zl_soft_timer_set(2, 500, st_led_flash);
- }
复制代码
真的是好饿,不写了,有问题欢迎交流,附件里有一个整理干净的 demo, 其实里面还有一些其它的东西,可以无视,我得去吃饭了 ……
zl_soft_timer_demo.zip
(777 KB, 下载次数: 212)
2015-11-10 18:46 上传
点击文件名下载附件
demo
哈哈,我也不喜欢官方的,所以才有了现在这个 zl_printf 模块……官方的占很多空间,还有些其它
方面让人难以接受。
关于这个模块,我对它的定性只是调试用的,一直没发现问题,串口输出可是调试必备啊……反正
我觉得调试用的话是足够了,你要用作其它方面,我不能保证,得需要你自己测试啦!
另外,需要说明的是这个 zl_printf 的功能是没有官方库强大的,这个模块也不是完全由我自己编写
的,有参考网上的代码,只是我做了一些优化,让它更符合我自己的调试需求。
一周热门 更多>