APP下载

中职汇编延时程序初探

2011-12-29李公昕

成才之路 2011年16期

  在应用单片机编制各种程序时,经常会遇到实现精确延时的问题,时间从几十微秒到几秒,甚至更高的精度。单片机实现延时通常有两种方法:一种是用定时器/计数器硬件延时,这种方法可以提高CPU的工作效率,也能做到精确延时,另一种是采用循环体进行软件延时。
  一、使用定时器/计数器
  单片机系统若使用频率为12MHz的晶振,一个机器周期为1μs,最长的延时时间可达2的16次方。在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时,从程序的执行效率和稳定性两方面考虑,都是最佳的方案,但需要注意的是,用C51编写的中断服务程序,编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时将占用4个机器周期,如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间要从初值中减去,以达到最小误差的目的。
  二、使用软件嵌套循环程序
  在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。常用的软件延时的方法有:
  1. 短暂延时
  通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10μs( )、Delay25μs( )等存放在一个自定义的文件中,需要时在主程序中直接调用。如延时10μs可编写如下:
  void Delay10μs ( ) {
  _NOP_( );
  _NOP_( );
  _NOP_( );
  _NOP_( );
  _NOP_( );
  _NOP_( );
  }
  上面函数中共用了6个_NOP_( )语句,每个语句执行时间为1μs。主函数调用Delay 10μs( )时,先执行一个LCALL指令(2 μs),然后执行6个_NOP_( )语句(6μs),最后执行了一个RET指令(2μs),所以执行上述函数时共需要10μs。可以把这一函数当做基本延时函数,在其他函数中调用,即嵌套调用,以实现较长时间的延时。
  2. C51中嵌套汇编程序段实现延时
  在C51中通过嵌套汇编语言语句,实现多次循环达到延时的目的。例1:50ms 延时子程序:
   DELAY:MOVR7,#200①
   LOOP1:MOVR6,#125 ②
   LOOP2:DJNZR6,L00P2③
   DJNZR7,LOOP1④
   RET⑤
  精确延时时间为:1+(1×200)+(2×125×200)+(2×200)+2=(2×125+3)×200+3 =50603us≈50ms⑥
  由⑥整理出公式:延时时间=(2×内循环+3)×外循环+3 ⑦
  详解:DELAY这个子程序共有五条指令,现在分别就每一条指令被执行的次数和所耗时间进行分析。第一句:MOVR7,#200在整个子程序中只被执行一次,且为单周期指令,所以耗时1us。第二句:MOVR6,#125从②看到④只要R7-1不为0,就会返回到这句,共执行了R7次,共耗时200us。第三句:DJNZ R6,LOOP2,只要R6-1不为0,就反复执行此句(内循环R6次),又受外循环R7控制,所以共执行R6×R7次,因是双周期指令,所以耗时2×R6×R7us。
  例2:1秒延时子程序:
  DELAY:MOV R7,#10 ①
  LOOP1:MOV R6,#200②
  LOOP2:MOV R5,#248③
  DJNZ R5,$ ④
  DJNZ R6,LOOP2 ⑤
  DJNZ R7,LOOP1 ⑥
  RET⑦
  对每条指令进行计算得出精确延时时间为:1+(1×10)+(1×200×10)+(2×248×200×10)+(2×200×10)+(2×10)+2=[(2×248+3)×200+3]×10+3=998033us≈1s ⑧
  由⑧整理得:延时时间=[(2×第一层循环+3)×第二层循环+3]×第三层循环+3 ⑨
  此式适用三层循环以内的程序,也验证了例1中式⑦(第三层循环相当于1)的成立。注意,要实现较长时间的延时,一般采用多重循环,有时会在程序里加入NOP指令。
  三、使用其他方法实现延时
  如示波器、反汇编工具、性能分析器等确定延时时间。
  四、总结
  中职学生对单片机编程掌握较为薄弱。本文所介绍的多种实现并计算延时程序执行时间的方法,使用定时器进行延时是最佳的选择,可以提高MCU工作效率。编写延时程序是一项很烦琐的任务,需要多次修改才能满足要求。
  (河南省经济管理学校)
   注:“本文中所涉及到的图表、公式、注解等请以PDF格式阅读”