CC2530单片机精确延时的时间分析
- IAR 仿真时如何得知运行周期
- for循环的时间计算
- 使用反汇编工具计算延时时间
- 验证
- 讨论
- CC2530与普通8051单片机时钟的不同
IAR 仿真时如何得知运行周期
关于这个问题,网上有很多好文章,讲得很清楚。IAR的操作很简单,我在这里给出链接。
百度经验:《IAR 仿真时如何得知运行周期》
IAR官网:How to measure execution time with CYCLECOUNTER
for循环的时间计算
CC2530单片机延时,可以采用外设定时器进行硬件延时。也可以采用软件方式进行延时。
本文只讨论用2层for循环嵌套的软件延时方式,供大家参考,不对之处请指正!
例如:
void delay_us(void)
{unsigned char a,b;for(a=173;a>0;a--)for(b=143;b>0;b--) ;
}
使用反汇编工具计算延时时间
可用Keil C51中的反汇编工具计算延时时间,在反汇编窗口中可用源程序和汇编程序的混合代码或汇编代码显示目标应用程序。
- 首先来分析 1层for循环 ,
for(b=143;b>0;b--) ;
首先选择build taget,然后单击start/stop debug session按钮进入程序调试窗口,最后打开Disassembly window,找出与这部分循环结构相对应的汇编代码。
首先是for循环中表达式1,对循环变量的赋值,这个需要5个指令周期。
然后是循环判断表达式,这个需要7个指令周期。
最后是循环增量表达式,这个需要2个指令周期。
- 1层for循环的时间计算
分析for循环的过程我们可以发现:for循环中表达式1,对循环变量的赋值,只执行1次;
循环判断表达式(7个指令周期)、增量表达式(2个指令周期),两者一起执行了9倍的循环次数(9个指令周期);
最后,还要执行1次循环判断表达式(跳出该层for循环)。
结论:1层for循环了b0次,其指令总数为:(5+9b0+7)
-
再来分析2层for循环
-
内层for循环作为外层for循环的循环体。也就是说,假定外层循环a0次,那么,内层循环体执行的指令总数为(5+9b0+7)× a0
-
那么,整个2层for循环的指令总数为:外层循环的1次循环变量赋值、外层循环判断× a0次、内层循环体× a0次、外层循环增量表达式× a0次、最后1次的循环判断(7个指令周期)。
-
所以,2层for循环的指令总数为:5+(5+9b0+7)× a0+9a0+7
-
最后,延时函数的调用是6个指令周期,返回是4个指令周期,所以调用延时函数的指令总数为:5+(5+9b0+7)× a0+9a0+7+10
-
展开简化为公式1:21 a0+9 a0 b0+22
验证
void delay_us(void)
{unsigned char a,b;for(a=173;a>0;a--)for(b=143;b>0;b--) ;
}
此延时函数,a0=173,b0=143,代入公式1得:226306
讨论
公式1本质上是1个二元二次方程。我们可以根据所需要的指令个数,编程实现求解方程,得到所需要的a0和b0的值。从而实现精确延时。
CC2530与普通8051单片机时钟的不同
CC2530的每个指令是一个时钟,而标准的8051的指令周期是12个时钟。
若选用32MHZ的时钟频率,那么时钟周期是1/32 us,一个指令也就是1/32us.
ZStack中大多使用的延时函数如下:
void Delay_us(uint16 value){while (value--){asm("NOP"); //一个指令周期占用一个时钟周期asm("NOP");asm("NOP");}
}