嵌入式框架Zorb Framework搭建六:定时器的实现

我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。

我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮。

一、前言

  事件有同步事件和异步事件,在这一篇中,我们将为Zorb
Framework提供异步事件功能。在很多时候,我们来不及处理部分操作或者对操作的实时性要求不高时,可以考虑使用异步事件功能。如在中断中处理大量的操作是不太明智的,这时候就可以发出一个事件出来,等待事件处理程序在中断外完成。

 

嵌入式框架Zorb Framework搭建过程

嵌入式框架Zorb
Framework搭建一:嵌入式环境搭建、调试输出和建立时间系统

嵌入式框架Zorb
Framework搭建二:环形缓冲区的实现

嵌入式框架Zorb
Framework搭建三:列表的实现

嵌入式框架Zorb
Framework搭建四:状态机的实现

嵌入式框架Zorb
Framework搭建五:事件的实现

嵌入式框架Zorb
Framework搭建六:定时器的实现

嵌入式框架Zorb
Framework搭建七:任务的实现

 

三、事件结果测试

  简单的测试代码如下:

  1 /**
  2   *****************************************************************************
  3   * @file    app_event.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_event.h"
 19 #include "zf_includes.h"
 20 
 21 /* 事件处理器 */
 22 static EventHandler *pEventHandler;
 23 
 24 /******************************************************************************
 25  * 描述  :事件程序1
 26  * 参数  :(in)-pArgList 事件参数列表指针
 27  * 返回  :无
 28 ******************************************************************************/
 29 void EventProcess1(List *pArgList)
 30 {
 31     uint32_t i;
 32     
 33     ZF_DEBUG(LOG_D, "\r\n");
 34     ZF_DEBUG(LOG_D, "event1 arg count is %d\r\n", pArgList->Count);
 35     for (i = 0; i < pArgList->Count; i ++)
 36     {
 37         ZF_DEBUG(LOG_D, "event1 arg %d is %s\r\n", i,
 38             pArgList->GetElementDataAt(pArgList, i));
 39     }
 40 }
 41 
 42 /******************************************************************************
 43  * 描述  :事件程序2
 44  * 参数  :(in)-pArgList 事件参数列表指针
 45  * 返回  :无
 46 ******************************************************************************/
 47 void EventProcess2(List *pArgList)
 48 {
 49     uint32_t i;
 50     
 51     ZF_DEBUG(LOG_D, "\r\n");
 52     ZF_DEBUG(LOG_D, "event2 arg count is %d\r\n", pArgList->Count);
 53     for (i = 0; i < pArgList->Count; i ++)
 54     {
 55         ZF_DEBUG(LOG_D, "event2 arg %d is %s\r\n", i,
 56             pArgList->GetElementDataAt(pArgList, i));
 57     }
 58 }
 59 
 60 /******************************************************************************
 61  * 描述  :任务初始化
 62  * 参数  :无
 63  * 返回  :无
 64 ******************************************************************************/
 65 void App_Event_init(void)
 66 {
 67     Event *pEvent; /* 事件指针 */
 68     
 69     /* 初始化事件处理器 */
 70     EventHandler_create(&pEventHandler);
 71     
 72     /* 创建事件1 */
 73     Event_create(&pEvent);
 74     pEvent->EventProcess = EventProcess1;
 75     pEvent->AddArg(pEvent, "hello", sizeof("hello") + 1);
 76     
 77     /* 推送事件1 */
 78     EVENT_POST(pEventHandler, pEvent);
 79     
 80     /* 创建事件2 */
 81     Event_create(&pEvent);
 82     pEvent->EventProcess = EventProcess2;
 83     pEvent->AddArg(pEvent, "zorb", sizeof("zorb") + 1);
 84     pEvent->AddArg(pEvent, "framework", sizeof("framework") + 1);
 85     
 86     /* 推送事件2 */
 87     EVENT_POST(pEventHandler, pEvent);
 88 }
 89 
 90 /******************************************************************************
 91  * 描述  :任务程序
 92  * 参数  :无
 93  * 返回  :无
 94 ******************************************************************************/
 95 void App_Event_process(void)
 96 {
 97     while(1)
 98     {
 99         /* 执行事件 */
100         if (pEventHandler->GetEventCount(pEventHandler) > 0)
101         {
102             pEventHandler->Execute(pEventHandler);
103         }
104         else
105         {
106             /* 可在此实现低功耗 */
107         }
108     }
109 }
110 
111 /******************************** END OF FILE ********************************/

  结果:

event1 arg count is 1
event1 arg 0 is hello

event2 arg count is 2
event2 arg 0 is zorb
event2 arg 1 is framework

 

四、最后

  本篇为Zorb
Framework提供了定时器功能。在对定时精度要求不高(毫秒级),完全可以使用软件定时器。软件定时器是在硬件定时器的基础上开发的,好处在于可以挂载多个定时器,不用再为芯片的定时器资源不够而烦恼。

 

  Zorb Framework
github:https://github.com/54zorb/Zorb-Framework

  版权所有,转载请打赏哟

 

如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟

图片 1

嵌入式框架Zorb Framework搭建过程

嵌入式框架Zorb
Framework搭建一:嵌入式环境搭建、调试输出和建立时间系统

嵌入式框架Zorb
Framework搭建二:环形缓冲区的实现

嵌入式框架Zorb
Framework搭建三:列表的实现

嵌入式框架Zorb
Framework搭建四:状态机的实现

嵌入式框架Zorb
Framework搭建五:事件的实现

嵌入式框架Zorb
Framework搭建六:定时器的实现

嵌入式框架Zorb
Framework搭建七:任务的实现

 

三、定时器结果测试

  简单的测试代码如下:

 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。

 

二、事件功能设计

  我们先来看看要实现的事件提供什么功能:

  初步要提供的功能如下:

  1、可以生成事件

  2、事件里边应该有事件处理函数

  3、可以添加事件处理函数的参数

  4、最好事件可以有优先级,优先级高的先执行

  5、最好事件可以自动回收

  因此,初步设计的数据结构如下: 

 1 /* 事件结构 */
 2 struct _Event
 3 {
 4     uint8_t Priority;               /* 优先级 */
 5     IEventProcess EventProcess;     /* 事件程序 */
 6     List *pArgList;                 /* 事件程序的参数指针 */
 7     
 8     /* 增加程序参数(深拷贝,按先后顺序入队列) */
 9     bool (*AddArg)(Event * const pEvent, void *pArg, uint32_t size);
10     
11     /* 销毁事件 */
12     bool (*Dispose)(Event * const pEvent);
13 };
14 
15 /* 事件处理器结构 */
16 struct _EventHandler
17 {
18     List *pEventList;   /* 事件列表 */
19     bool IsRunning;     /* 是否正在运行:默认开 */
20     
21     /* 获取事件数 */
22     uint32_t (*GetEventCount)(EventHandler * const pEventHandler);
23     
24     /* 增加事件(按优先级排序) */
25     bool (*Add)(EventHandler * const pEventHandler, Event *pEvent);
26     
27     /* 删除事件(释放空间) */
28     bool (*Delete)(EventHandler * const pEventHandler, Event *pEvent);
29     
30     /* 清空事件列表(释放空间) */
31     bool (*Clear)(EventHandler * const pEventHandler);
32     
33     /* 销毁事件处理器(释放空间) */
34     bool (*Dispose)(EventHandler * const pEventHandler);
35     
36     /* 执行事件(按列表位置) */
37     void (*Execute)(struct _EventHandler * const pEventHandler);
38 };

  事件和事件处理器已经设计好了,再定义一个宏来帮助推送事件。

1 /* 推送事件 */
2 #define EVENT_POST(handler_, event_) handler_->Add(handler_, event_)

  具体实现请看附件代码或在文末的github地址拉框架源码。

 

一、前言

  在嵌入式开发中,我们常常会用到定时器,我们可以用芯片的定时器外设,可以用内核的systick,也可以使用操作系统的定时器。本篇要设计的定时器类似与操作系统的定时器,是软件定时器。如果Zorb
Framework运行在操作系统上面,大可以不使用本篇的功能,直接使用操作系统自带的定时器。

 

四、最后

  本篇为Zorb
Framework提供了事件功能。事件功能主要用于搭建基于事件驱动的程序,如果一直习惯于开发时间驱动程序(轮询程序)的你,尝试一下事件驱动程序,你会发现别有一番风味。

 

  Zorb Framework
github:https://github.com/54zorb/Zorb-Framework

  版权所有,转载请打赏哟

 

如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟

图片 1

二、定时器设计

  我们先来看看要实现的定时器提供什么功能:

  初步要提供的功能如下:

  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地址拉框架源码。