在决定了继续使用函数回调的机制实现 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.