C51精确延时

有些特殊的应用会用到比较精确的延时(比如DS18B20等),而C不像汇编,延时精准度不好算。本人经过反复调试,对照KEIL编译后的汇编源文件,得出了以下几条精确延时的语句(绝对精确!本人已通过实际测试),今天贴上来,希望对需要的朋友有所帮助。 


sbit LED  =  P1^0;      // 定义一个管脚(延时测试用) 
unsigned int i = 3;     // 注意i,j的数据类型, 
unsigned char j = 3;    // 不同的数据类型延时有很大不同 
//-----------------各种精确延时语句----------------------------------- 
while( (i--)!=1 );      // 延时10*i个机器周期 
i = 10; while( --i );   // 延时8*i+2个机器周期 
i = 10; while( i-- );   // 延时(i+1)*9+2个机器周期 
j = 5;  while( --j );   // 延时2*j+1个机器周期 
j = 5;  while( j-- );   // 延时(j+1)*6+1个机器周期 


i = 5;  
while( --i )            // 延时i*10+2个机器周期,在i*10+2个机器周期 
if( LED==0 )  break; // 内检测到LED管脚为低电平时跳出延时 


i = 5; 
while( LED )            // 每隔10个机器周期检测一次LED管脚状态,当LED	
if( (--i)==0 ) break;// 为低时或者到了10*i+2个机器周期时跳出延时 
//-------------------------------------------------------------------- 




例如18b20的复位函数(12M晶振): 
//*********************************************************************** 
// 函数功能:18B20复位 
// 入口参数:无 
// 出口参数:unsigned char x: 0:成功 1:失败 
//*********************************************************************** 
unsigned char ow_reset(void) 
{ 
unsigned char x=0;  // 12M晶振 1个机器周期为1us 
DQ = 1;	   // DQ复位 
j = 10;  while(--j);// 稍做延时(延时10*2+1=21个机器周期,21us) 
DQ = 0;	   // 单片机将DQ拉低 
j = 85;  while(j--);// 精确延时(大于480us) 85*6+1=511us 
DQ = 1;	   // 拉高总线 
j = 10;  while(j--);// 精确延时10*6+1=61us 
x = DQ;	   // 稍做延时后, 
return x;	   // 如果x=0则初始化成功 x=1则初始化失败 
j = 25;  while(j--);// 精确延时25*6+1=151us 
} 
//********************************************************************************* 


再如红外解码程序: 
(先说传统红外解码的弊端: 
 程序中用了while(IR_IO);while(!IR_IO);这样的死循环,如果管脚一直处于一种状态,就会一直执行while,造成“死机”现象。当然这种情况很少,但我们也的考虑到。而用以下程序则不会,在规定的时间内没有正确的电平信号就会返回主程序,这样就不会出现“死机”了) 
//***************************外部中断0******************************* 
void int0(void) interrupt 0 
{ 
unsigned char i,j; 
unsigned int count = 800; 
//--------------8.5ms低电平引导码------------------------------------- 
while( --count )	
if( IR_IO==1 )      return;   // 在小于8ms内出现高电平,返回 
count = 100;                     // 延时1ms 
while( !IR_IO )                  // 等待高电平 
if( (--count)==0 )  return;   // 在9ms内未出现高电平,返回 
//-------------4.5ms高电平引导码------------------------------------ 
count = 410;                     // 延时4.1ms 
while( --count )                 // ... 
if( IR_IO==0 )      return;   // 在4.1ms内出现低电平,返回 
count = 50;                      // 延时0.5ms 
while( IR_IO )                   // 等待低电平 
if( (--count)==0 )  return;   // 在4.7ms内未出现低电平,返回 
//----------------------------------------------------------------- 
//------------4个数据码------------------------------------ 
for( j=0;j<4;j++ ) 
{ 
for( i=0;i<8;i++ ) 
{ 
IR_data[j] <<= 1;                // 装入数据 
count = 60;                      // 延时0.6ms 
while( !IR_IO )                  // 等待高电平 
if( (--count)==0 )   return;  // 在0.6ms内未出现高电平,返回 
count = 40;                      // 低电平结束,继续 
while( --count )                 // 延时0.4ms 
if( IR_IO==0 )       return;  // 在0.4ms内出现低电平,返回 
count = 100;                     // 延时1.4ms 
while( IR_IO )                   // 检测IO状态 
if( (--count)==0 )            // 等待1.4ms到来 
{                             // 在1.4ms内都是高电平 
IR_data[j] |= 1;           // 两个单位高电平,为数据1 
break;                     // 跳出循环 
} 
count = 20;                      // 延时0.2ms 
while( IR_IO )                   // 等待低电平跳出 
if( (--count)==0 ) return;    // 0.2ms内未出现低电平,返回 
} 
} 
//------------------------------------------------------------------- 
flag_IR = 1;                           // 置位红外接收成功标志 
} 


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值