一、本文内容
上一节《01-单片机商业项目编程,从零搭建低功耗系统设计-CSDN博客》已经对事件驱动原理有个基本了解,本节主要就是如何将事件写的更规范,而不是用t_flag这样的标记,写多了可读性也不强;本节结尾总结将提出时间片伪多任务系统概念。
二、事件编程代码优化
代码编写过程中,对于一个特定功能代码,都有初始化、执行两个过程,在上节代码中对于事件t_flag是一个100ms的定时,对于执行就是当t_flag=1时,执行对应任务,我们实际执行过程也会进一步封装,留给最上层的接口往往叫回调函数,所以一个完整的框架包含:创建、执行、回调三个过程。
//事件执行
void evt_handle(void)
{
if(g_event)
{
evt_callback(g_event); //回调
}
set_wakeup_condition();
mcu_sleep_and_wait_wakeup();
}
int main(void)
{
evt_create(EVT_INDEX_100MS,100); //创建100ms事件
evt_create(EVT_INDEX_150MS,150); //创建150ms事件
while (1)
{
evt_handle(); //执行
}
}
对于事件标记实际只需要1bit即可描述,因此事件我们往往直接用uint8_t表示8个事件,或者uint16_t表示16个事件等等,根据自身需求来设定,按上述代码中的EVT_INDEX_100MS、EVT_INDEX_150MS则使用了2byte,对于事件回调则是处理完成则清零即可。
uint16_t g_event = 0x0000; //全局事件标记
#define EVT_INDEX_100MS 0x0001 //100ms事件索引,对应bit0位
#define EVT_INDEX_150MS 0x0002 //100ms事件索引,对应bit1位
//事件回调
void evt_callback(uint16_t event)
{
if(event&EVT_INDEX_100MS)
{
//执行100ms中断对应任务
//...
event ^= EVT_INDEX_100MS;//清零事件标记
}
if(event&EVT_INDEX_150MS)
{
//执行150ms中断对应任务
//...
event ^= EVT_INDEX_150MS;//清零事件标记
}
}
三、总结
创建、执行、回调三部曲这是做系统架构很常见的做法,在代码设计初期,把框架设计好了,后续再针对每个函数去做进一步的参数优化,比如定时事件时持续跑,还是只执行一次等等,还有是不是有附加参数传入等等;当我们搭建了一个基于时间系统的事件,实际我们就做了一个基于时间片的伪操作系统。