基于事件的单片机程序?
基于事件的单片机程序框架?不知道这个算不算事件驱动,工作中基本是写的裸机程序多,主要用STM32单片机,这样搞能方便程序设计,在MDK中测试OK,母鸡有没啥菜鸡如本人不自知的问题。
程序从大佬程序参考修改得来。
https://github.com/jiejieTop/cmd-parser
代码
-
数据结构
typedef struct _event {
char event_flag : 1; //事件产生的标志位
event_type_t event_type; //事件类型
const char *event_name; //事件名字
event_handler handler; //事件处理函数
} event_t;
方法
- 初始化事件机制?
/**
* @brief: initilize event
* @param[in]: None
* @retval[out]: None
* @author: guangjieSuper
* @github: https://github.com/guangjieSuper
*/
void event_init(void)
{
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */
extern const int EVENT_LIST$$Base;
extern const int EVENT_LIST$$Limit;
_event_list_begin = (event_t *)&EVENT_LIST$$Base;
_event_list_end = (event_t *)&EVENT_LIST$$Limit;
#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
_cmd_init(__section_begin("EVENT_LIST"), __section_end("EVENT_LIST"));
#endif
}
- main函数主循环调用
/**
* @brief: Event handler
* @param[in]: None
* @retval[out]: None
* @author: guangjieSuper
* @github: https://github.com/guangjieSuper
*/
void event_handle_loop(void)
{
event_t *index;
for(index = _event_list_begin; index < _event_list_end; index++)
{
if(index->event_type == CONTINUOUS_EVENT)
{
index->handler();
}
else
{
if(index->event_flag == EVENT_ON)
{
index->handler();
index->event_flag = EVENT_OFF;
}
}
}
}
- 注册事件
注册事件使用这一个宏函数注册
#define EVENT_EXPORT(event_name,event_type, handler) \
EVENT_USED event_t _##event_name EVENT_SECTION("EVENT_LIST")= \
{ \
EVENT_OFF, \
event_type, \
#event_name, \
(event_handler)&handler \
};
- 发布事件
/**
* @brief: post event
* @param[in]: event_name event's name
* @retval[out]: None
* @author: guangjieSuper
* @github: https://github.com/guangjieSuper
*/
void post_event(char *event_name)
{
event_t *index;
for(index = _event_list_begin; index < _event_list_end; index++)
{
if(strncmp(event_name,index->event_name,strlen(index->event_name)) == 0)
{
if(index->event_type == ONCE_EVENT)
index->event_flag = EVENT_ON;
}
}
}
使用
#include "event.h"
void event1(void)
{
printf("1000ms >> RT-Thread\r\n");
}
EVENT_EXPORT(event1,ONCE_EVENT,event1);
void event2(void)
{
printf("2000ms >> uCos\r\n");
}
EVENT_EXPORT(event2,ONCE_EVENT,event2);
void event3(void)
{
printf("500ms >> Linux\r\n");
}
EVENT_EXPORT(event3,ONCE_EVENT,event3);
在需要发布事件的地方调用post_event("eventX");
(x=1 or 2 or 3)就可以执行event1
函数
main函数调用
while(1)
{
software_timer_loop();
event_handle_loop();
}
这样做后暂时感觉主函数都不用修改了。
- 要到主函数中调用执行的函数只要用
EVENT_EXPORT(event_name,event_type, handler)
注册,将event_type
设置为一直运行的类型CONTINUOUS_EVENT
- 对于另一类要定时运行的事件,
event_type
设置为ONCE_EVENT
,使用定时器定时,定时时间到时post_event
一下就行了。 - 还有定义全局变量标志位来标志事件发生的情况也是将
event_type
设置为ONCE_EVENT
,在需要标志让它执行的地方post_event
。这样能减少使用全局变量。
如本菜鸡在软件定时器的回调函数中post_event
void timer1_cb(void *parm)
{
post_event("event1");
}
void timer2_cb(void *parm)
{
post_event("event2");
}
void timer3_cb(void *parm)
{
post_event("event3");
}