关于Atmel ATmega162汇编函数Timer_Loop_10us的耗时核算疑问
你的核算完全正确,原注释的10µs延时确实不准确
让我们一步步拆解这个函数的时钟周期,验证你的结论:
首先,你提到的指令周期规则完全符合ATmega的指令集规范:
push/pop:各占2个时钟周期ldi/nop/dec/tst:各占1个时钟周期ret:占4个时钟周期brne:条件满足(需要跳转)时占2个周期,条件不满足(无需跳转)时占1个周期,你的这个推测是对的。
接下来逐段计算总周期:
- 函数开头的
push Counter:2周期 ldi Counter,5:1周期- 循环部分(
timer_wait10us):
初始化Counter为5,意味着循环会完整执行5次:- 前4次循环(Counter从5递减到1):每次执行
nop(1) +dec Counter(1) +tst Counter(1) +brne(2,因Counter≠0需跳转),单次循环总周期为5,4次累计20周期 - 第5次循环(Counter从1递减到0):执行
nop(1) +dec Counter(1) +tst Counter(1) +brne(1,因Counter=0无需跳转),单次循环总周期为4 - 循环部分总周期:20+4=24周期
- 前4次循环(Counter从5递减到1):每次执行
- 函数结尾的
pop Counter:2周期 ret:4周期
把所有周期相加:2+1+24+2+4=33周期
再计算实际延时:ATmega162主频16MHz,单个时钟周期为1/16000000 = 0.0625µs,33×0.0625=2.0625µs,确实和你计算的一致,仅约2µs,和原注释的10µs差距明显。
有没有遗漏的因素?
如果你的系统没有开启任何中断(或这段延时期间无中断触发),也没有使用会干扰CPU执行流水线的特殊外设,那这个周期计算就是完全准确的。原代码的注释大概率是错误的——要么是编写时假设的主频不是16MHz,要么是ldi的初始数值写错了(比如要达到10µs,需要约160个时钟周期,减去循环外的9个周期,循环内需要151个周期,得大幅调整Counter的初始值)。
内容的提问来源于stack exchange,提问作者Thern
相关产品推荐
相关产品推荐

