在决定了继续使用函数回调的机制实现 uSer和Apper之间通信的方法,在继续实现以前,我们先做一件很重要的事情。
我们来进行一次简单的 时间开销 测试。
因为使用的难易可以通过改进,但是时间开销却是一个硬性指标。
我们已经大致预见到,这样的函数回调数量不会少。(想想,i2c等时序都需要IO实现,所以这样的回调是非常多的,所以它的时间开销会产生致命性影响,不可不慎查。)
为了方便起见,我们采用一种不需要任何其他条件的方法,在debug模式下,通过比较 普通函数调用 和 通过函数指针调用函数 所用的时间差别。
因为我们只关心相对比例,所以我们不需要一个多么精确地计时器。
为此,一个最简单的实现方法是一个 定时中断。
我们也不采用复杂的uSer和Apper这种复杂的调用机制,而是最一般的做法。
以下是code:
void TestFun(void)
{
}
extern U16 Times;
void main(void)
{
static U16 i;
void (*pTest)(void) = NULL;
Timer_Initial();
pTest = TestFun;
while(1)
{
Times = 0;
for(i = 0;i < 5000;i++)
//TestFun();
(*pTest)();
i = 0;// for breakpoint here.
}
复制代码
U16 Times = 0;
#pragma vector=0xF
__interrupt void TIM2_UPD_OVF_BRK_IRQHandler(void)
{
TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
Times++;
}
复制代码
上面是main函数,下面是 定时中断,整个函数非常纯粹。
在debug时,把断点设在 i = 0;的语句。
测试发现,直接调用函数,断点时Timer值为17;
而通过函数指针调用,断点时Timer值为19;
这个比例说起来不算太大,但也不小。
既然已经做了测试,我们不妨再做一个更加符合真实情况的测试。判断函数指针是否为NULL
——实际应用中,不管是调用前直接判断,还是函数一开始就判断,其实说起来都是多了一句判断,所以这个测试是非常符合实际的。
while(1)
{
Times = 0;
for(i = 0;i < 5000;i++)
{
//TestFun();
if(pTest != NULL)
(*pTest)();
}
i = 0;// for breakpoint here.
}
复制代码
现在测试的结果是 23.
这个结果就比较危险了。
23-17/17将近1/3.