精确的延时函数最大误差05.docVIP

  • 1
  • 0
  • 约2.81千字
  • 约 6页
  • 2017-09-02 发布于浙江
  • 举报
精确的延时函数最大误差05

精确的延时函数,最大误差0.5% /*下面是一个精确的延时程序,延时范围为[1ms, 255ms] 误差范围为(0, 0.5%],随着延时时间的增强,相对误差越来越低, 在延时1毫秒时误差最大0.5%,在延时255毫秒时误差趋向于0 下面就讲讲我是如何写出这个延时函数的: 首先我要确定在延时函数里,用什么语法结构作为延时体 有两类结构 第一类,直接用for循环,格式如下 这是最简单的一层,如果多重嵌套的话就很复杂了 for(i = 0; i 10; --i); 汇编翻译代码如下 C:0x1F22 E4 CLR A C:0x1F23 FE MOV R6,A C:0x1F24 EE MOV A,R6 C:0x1F25 C3 CLR C C:0x1F26 940A SUBB A,#0x0A C:0x1F28 5003 JNC C:1F2D C:0x1F2A 1E DEC R6 C:0x1F2B 80F7 SJMP C:1F24 第二类,用while循环或do...while循环,格式如下 do//第一层 { j = y; do//第二层 { i = x; do//第三层,里面有N个_nop_() { _nop_(); _nop_(); _nop_(); . . . }while(--i); }while(--j); }while(--btXms); 汇编翻译代码如下 C:0x1FBF 7D02 MOV R5,#0x02 C:0x1FC2 7EA5 MOV R6,#0xA5 C:0x1FC4 00 NOP C:0x1FC5 DEFD DJNZ R6,C:1FC4 C:0x1FC7 DDF9 DJNZ R5,C:1FC2 C:0x1FC9 DFF4 DJNZ R7,C:1FBF //从上面可以看到,第二类循环翻译成汇编最简单,整个三重循环就6条指令,平摊到每一个循环就两句话, 由此我选择do...while 作为延时体(当然你也可以用while循环),接下来 就是计算出总延时,这个在C函数里是最难的: 首先我们计算出第三层的延时总周期, C = nx + 2x; 第三层有N个_nop_() 循环了x次所以是nx个周期,DJNZ指令有x次每次两个周期,所以是2x个周期 第二层的延时总周期, B = y + Cy + 2y; 第二层有个MOV 赋值指令 循环了y次所以是y个周期,DJNZ指令有y次每次两个周期,所以是2y个周期, 第三层循环也循环了y次所以是Cy个周期 第一层的延时总周期, A = btXms + BbtXms + 2btXms; 第一层也有个MOV 赋值指令 循环了btXms次所以是btXms个周期, DJNZ指令有btXms次每次两个周期,所以是2btXms个周期, 第二层循环也循环了btXms次所以是BbtXms个周期 由此可以得出中的循环周期为 t = A +5;末尾的5个周期是,传参MOV指令 一个周期,函数返回 RET 两个周期, 函数调用 LCALL 两个周期 于是总的周期就出来了 t = [3y + (2+n)xy + 3]btXms+5 如果晶振为12MHz 那么每一个周期的时间为1us,于是总延时为 T = {[3y + (2+n)xy + 3]btXms+5} (us) 现在就是要求出当 btXms为1时我们要保证延时是1000us,于是有等式为 3y + (2+1)xy + 3 == 1000 //注意那额外的5个周期已经被忽略了,因为这个5个周期不会随着btXms德变化而变化, 我们无法消除这5个周期的误差,为了使函数最简单,这里令n=1; 于是有3y + 3xy == 997 因为997无法整除3,所以这个等式x y 没有整数解,那么我们能不能够造出一个等式使得x y 有整数解呢,这就要我们仔细观察了。 我们发现997不能出以3 但996却可以,所以我们就想如果我们的延时函数执行总周期为t = [3y + (2+n)xy + 4]btXms+5 ,那就一切OK了 很快我们发现,变成这样很容易,最简单的就是在最外层循环中加上一个nop 就行了,于是乎我们的延时函数,被稍微的修改如下 do//第一层 { j = y; _nop_(); do//第二层 {

文档评论(0)

1亿VIP精品文档

相关文档