zoukankan      html  css  js  c++  java
  • 51系列单片机的精确延时的解释(文章如有问题之处,请劳烦指正,谢谢!) 可以看看采纳下。

    /*----延时用的变量尽量用char或unsigned char来定义--------*/

    #include<intrins.h>
    //一. 500ms延时子程序
    void delay500ms(void)
    {
      unsigned char i,j,k;
      for(i=15;i>0;i--)
        for(j=202;j>0;j--)
          for(k=81;k>0;k--);
    }
    /*
    计算分析:
    程序共有三层循环
    一层循环n:R5*2 = 81*2 = 162us DJNZ 2us
    二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值 1us = 3us
    三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值 1us = 3us
    循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us = 5us
    延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms
    计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5 (微秒)
    延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5(微秒)
    */

    //二. 200ms延时子程序
    void delay200ms(void)
    {
      unsigned char i,j,k;
      for(i=5;i>0;i--)
        for(j=132;j>0;j--)
          for(k=150;k>0;k--);
    }

    //三. 10ms延时子程序
    void delay10ms(void)
    {
      unsigned char i,j,k;
      for(i=5;i>0;i--)
        for(j=4;j>0;j--)
          for(k=248;k>0;k--);
    }

    //四. 1s延时子程序
    void delay1s(void)
    {
      unsigned char h,i,j,k;
      for(h=5;h>0;h--)
        for(i=4;i>0;i--)
          for(j=116;j>0;j--)
            for(k=214;k>0;k--);
    }
    //几毫秒秒时用此函数;延时时间=[(2*245+3)*2+3]*i+5(微秒),延时2毫秒最精确。
    void aa(unsigned char i)
    {
      unsigned char j,k;
      for(;i>0;i--)
        for(j=2;j>0;j--)
          for(k=245;k>0;k--);
    }
    //如果是微秒级延时的话,无需用调用函数,直接用单个for语句;
    //这时对晶振为12M单片机而定的情况;
    /*-------------------- 1us~511us延时语句 ----------------------*/
    /*
    用法:
    必须用char或unsigned char定义一个数 i;然后写出单个for语句;
    for(i=X;i>0;i--)
    注意:X必需是一个直接给的数,不用定义X;
    延时时间=( X*2+1 )微秒;
    如: ①for(i=1;i>0;i--) X=1; 延时时间=( X*2+1 )=3us;
    ②for(i=2;i>0;i--) X=2; 延时时间=( X*2+1 )=5us;
    ③for(i=10;i>0;i--) X=10; 延时时间=( X*2+1 )=21us;
    ④for(i=100;i>0;i--) X=100; 延时时间=( X*2+1 )=201us;
    因为i是字符型变量,故i不能大于255,即单个for语句的延时时间
    不能大于(255*2+1)=511微秒;也就是不大于0.511毫秒。
    */

    /*
    对一个变量int操作和char操作的指令时间不同,所以延时不一样,导致总线错误
    char是单字节变量,int是双字节变量,单字节变量自减1和双字节变量自减1耗费
    的CPU时间是不同的,换句话说,双字节变量自减1的操作时间要长于单字节变量,
    而你这个延时程序纯粹就是靠CPU循环进行固定次数的自减操作实现的,所以
    单字节变量变成双字节变量以后,自减操作的次数不变,延时时间会增长。
    */
    /*

    #include<intrins.h>里有延时指令 _nop_();
    _nop_();延时时间为一个机械周期=12个时钟周期的时间。
    时钟周期=1/晶振值。
    如12MHZ的晶振的单片机的时钟周期=1/12M=1/(12*10E5)=1/12000000= 1/12 微秒
    如1MHZ的晶振的单片机的时钟周期=1/1M=1/(1*10E5)=1/1000000= 1 微秒
    如24MHZ的晶振的单片机的时钟周期=1/24M=1/(24*10E5)=1/24000000= 1/24 微秒
    */

    /*
    2 软件延时与时间计算
    在很多情况下,定时器/计数器经常被用作其他用途,
    这时候就只能用软件方法延时。下面介绍几种软件延时的方法。

    2.1 短暂延时

    可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,
    如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,
    需要时在主程序中直接调用。如延时10 μs的延时函数可编写如下:

    void Delay10us( )
    {
      _NOP_( );
      _NOP_( );
      _NOP_( );
      _NOP_( );
      _NOP_( );
      _NOP_( );
    }
    Delay10us( )函数中共用了6个_NOP_( )语句,每个语句执行时间为1 μs。
    主函数调用Delay10us( )时,先执行一个LCALL指令(2 μs),
    然后执行6个_NOP_( )语句(6 μs),最后执行了一个RET指令(2 μs),
    所以执行上述函数时共需要10 μs。 可以把这一函数当作基本延时函数,
    在其他函数中调用,即嵌套调用[4],以实现较长时间的延时;但需要注意,
    如在Delay40us( )中直接调用4次Delay10us( )函数,得到的延时时间将是42 μs,
    而不是40 μs。这是因为执行Delay40us( )时,先执行了一次LCALL指令(2 μs),
    然后开始执行第一个Delay10us( ),执行完最后一个Delay10us( )时,直接返回到主程序。
    依此类推,如果是两层嵌套调用,如在Delay80us( )中两次调用Delay40us( ),
    则也要先执行一次LCALL指令(2 μs),然后执行两次Delay40us( )函数(84 μs),
    所以,实际延时时间为86 μs。简言之,只有最内层的函数执行RET指令。
    该指令直接返回到上级函数或主函数。如在Delay80μs( )中直接调用8次Delay10us( ),
    此时的延时时间为82 μs。通过修改基本延时函数和适当的组合调用,
    上述方法可以实现不同时间的延时。

    */

  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/Blub-xinye1/p/5513545.html
Copyright © 2011-2022 走看看