chan千&夜ge

导航

 

/*----延时用的变量尽量用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。通过修改基本延时函数和适当的组合调用,
上述方法可以实现不同时间的延时。

*/

posted on 2016-05-20 21:57  chan千&夜ge  阅读(589)  评论(0编辑  收藏  举报