我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。
嵌入式框架Zorb Framework搭建过程
嵌入式框架Zorb Framework搭建一:嵌入式环境搭建、调试输出和建立时间系统
嵌入式框架Zorb Framework搭建二:环形缓冲区的实现
一、前言
在嵌入式开发中,我们常常会用到定时器,我们可以用芯片的定时器外设,可以用内核的systick,也可以使用操作系统的定时器。本篇要设计的定时器类似与操作系统的定时器,是软件定时器。如果Zorb Framework运行在操作系统上面,大可以不使用本篇的功能,直接使用操作系统自带的定时器。
二、定时器设计
我们先来看看要实现的定时器提供什么功能:
初步要提供的功能如下:
1、可以设置定时时间
2、可以设置定时器是单次还是重复运行
3、可以设置定时器处理函数
4、定时器函数可以直接运行或者推送异步事件
5、可以打开和关闭定时器
因此,初步设计的数据结构如下:
1 /* 定时器处理程序 */ 2 typedef void (*ITimerProcess)(void); 3 4 /* 定时器结构 */ 5 typedef struct _Timer 6 { 7 uint8_t Priority; /* 事件优先级 */ 8 uint32_t Interval; /* 时间间隔(ms) */ 9 uint32_t AlarmTime; /* 定时到达时间 */ 10 bool IsAutoReset; /* 重复运行(默认开) */ 11 bool IsRunning; /* 是否正在运行(默认关) */ 12 /* 事件的处理者,事件将推送到处理者的队列 */ 13 /* 不设置处理者则本地执行(挂载Timer_process的地方) */ 14 EventHandler *pEventHandler; 15 /* 处理事件 */ 16 ITimerProcess TimerProcess; 17 18 /* 开始定时器 */ 19 void (*Start)(struct _Timer * const pTimer); 20 21 /* 关闭定时器 */ 22 void (*Stop)(struct _Timer * const pTimer); 23 24 /* 重新运行定时器 */ 25 void (*Restart)(struct _Timer * const pTimer); 26 27 /* 销毁定时器(释放空间) */ 28 bool (*Dispose)(struct _Timer * const pTimer); 29 } Timer;
事件和事件处理器已经设计好了,再把定时器的处理程序添加到系统滴答程序中即可:
1 /****************************************************************************** 2 * 描述 :系统滴答程序(需挂在硬件的时间中断里边) 3 * 参数 :无 4 * 返回 :无 5 ******************************************************************************/ 6 void ZF_timeTick (void) 7 { 8 /* 系统滴答计数 */ 9 ZF_tick++; 10 11 /* 软件定时器程序 */ 12 Timer_process(); 13 }
具体实现请看附件代码或在文末的github地址拉框架源码。
三、定时器结果测试
简单的测试代码如下:
1 /** 2 ***************************************************************************** 3 * @file app_timer.c 4 * @author Zorb 5 * @version V1.0.0 6 * @date 2018-06-28 7 * @brief 定时器测试的实现 8 ***************************************************************************** 9 * @history 10 * 11 * 1. Date:2018-06-28 12 * Author:Zorb 13 * Modification:建立文件 14 * 15 ***************************************************************************** 16 */ 17 18 #include "app_timer.h" 19 #include "zf_includes.h" 20 21 /* 事件处理器 */ 22 static EventHandler *pEventHandler; 23 /* 定时器1 */ 24 static Timer *pTimer1; 25 /* 定时器2 */ 26 static Timer *pTimer2; 27 28 /****************************************************************************** 29 * 描述 :定时器程序1 30 * 参数 :void 31 * 返回 :无 32 ******************************************************************************/ 33 void TimerProcess1(void) 34 { 35 ZF_DEBUG(LOG_D, "%dms:timer process 1 run\r\n", ZF_SYSTIME_MS()); 36 } 37 38 /****************************************************************************** 39 * 描述 :定时器程序2 40 * 参数 :void 41 * 返回 :无 42 ******************************************************************************/ 43 void TimerProcess2(void) 44 { 45 ZF_DEBUG(LOG_D, "%dms:timer process 2 run\r\n", ZF_SYSTIME_MS()); 46 } 47 48 /****************************************************************************** 49 * 描述 :任务初始化 50 * 参数 :无 51 * 返回 :无 52 ******************************************************************************/ 53 void App_Timer_init(void) 54 { 55 /* 初始化事件处理器 */ 56 EventHandler_create(&pEventHandler); 57 58 /* 创建定时器1 */ 59 Timer_create(&pTimer1); 60 pTimer1->Priority = 1; 61 pTimer1->Interval = 500; 62 pTimer1->TimerProcess = TimerProcess1; 63 pTimer1->IsAutoReset = true; 64 pTimer1->pEventHandler = pEventHandler; 65 pTimer1->Start(pTimer1); 66 67 /* 创建定时器2 */ 68 Timer_create(&pTimer2); 69 pTimer2->Priority = 2; 70 pTimer2->Interval = 1000; 71 pTimer2->TimerProcess = TimerProcess2; 72 pTimer2->IsAutoReset = true; 73 pTimer2->pEventHandler = pEventHandler; 74 pTimer2->Start(pTimer2); 75 } 76 77 /****************************************************************************** 78 * 描述 :任务程序 79 * 参数 :无 80 * 返回 :无 81 ******************************************************************************/ 82 void App_Timer_process(void) 83 { 84 while(1) 85 { 86 /* 执行事件 */ 87 if (pEventHandler->GetEventCount(pEventHandler) > 0) 88 { 89 pEventHandler->Execute(pEventHandler); 90 } 91 else 92 { 93 /* 可在此实现低功耗 */ 94 } 95 } 96 } 97 /******************************** END OF FILE ********************************/
结果:
500ms:timer process 1 run 1000ms:timer process 1 run 1002ms:timer process 2 run 1500ms:timer process 1 run 2000ms:timer process 1 run 2002ms:timer process 2 run 2500ms:timer process 1 run 3000ms:timer process 1 run 3002ms:timer process 2 run 3500ms:timer process 1 run 4000ms:timer process 1 run 4002ms:timer process 2 run 4500ms:timer process 1 run 5000ms:timer process 1 run 5002ms:timer process 2 run
省略...
在测试程序中,定时器1周期为500ms,定时器2周期为1000ms。至于定时器2程序第一次执行的时间为1002ms的原因:定时器1和定时器2同时在1000ms处响应,但定时器1 的优先级比定时器2的优先级高,因此事件处理器先处理完定时器1的事件再处理定时器2的事件,而调试串口波特率115200,定时器1程序把调试数据发送完的时间大约2ms,因此定时器2的第一次执行时间为1002ms。
四、最后
本篇为Zorb Framework提供了定时器功能。在对定时精度要求不高(毫秒级),完全可以使用软件定时器。软件定时器是在硬件定时器的基础上开发的,好处在于可以挂载多个定时器,不用再为芯片的定时器资源不够而烦恼。
Zorb Framework github:https://github.com/54zorb/Zorb-Framework
版权所有,转载请打赏哟
如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟