您当前的位置:五五电子网电子知识单片机-工控设备综合-其它C51单片机的精准延时程序(Timer) 正文
C51单片机的精准延时程序(Timer)

C51单片机的精准延时程序(Timer)

点击数:7343 次   录入时间:03-04 11:58:09   整理:http://www.55dianzi.com   综合-其它

使用定时器 /  计数器实现精确延时
单片机系统一般常选用 11.059 2 MHz 、 12 MHz 或 6 MHz 晶振。第一种更容易产生各种标准的波特率,
后两种的一个机器周期分别为 1 μ s 和 2 μ s ,便于精确延时。本程序中假设使用频率为 12 MHz 的晶振。 最
长的延时时间可达 216=65 536 μ s 。若定时器工作在方式 2 ,则可实现极短时间的精确延时;如使用其他
定时方式,则要考虑重装定时初值的时间(重装定时器初值占用 2 个机器周期)。
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时
器 / 计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意, C51 编写的中断服务
程序编译后会自动加上 PUSH ACC 、 PUSH PSW 、 POP PSW 和 POP ACC 语句,执行时占用了 4 个机器周
期;如程序中还有计数值加 1 语句,则又会占用 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
),所以执行上述函数时共需要 10 μ s 。 可以把这一函数当作基本延时函数,在其他函数中调用,
套调用 \[4\] ,以实现较长时间的延时;但需要注意,如在 Delay40us( ) 中直接调用 4 次 Delay10us( ) 函 数 ,
的延时时间将是 42 μ s ,而不是 4 0 μ s 。这是因为执行 Delay40us( ) 时,先执行了一次 LCALL 指令( 2
),然后开始执行第一个 Delay10us( ) ,执行完最后一个 Delay10us( ) 时,直接返回到主程序。依此类 推 ,
是两层嵌套调用,如在 Delay80us( ) 中两次调用 Delay40us( ) ,则也要先执行一次 LCALL 指令( 2 μ s ),
执行两次 Delay40us( ) 函数( 84 μ s ),所以,实际延时时间为 86 μ s 。简言之,只有最内层的函数 执
ET 指令。该指令直接返回到上级函数或主函数。如在 Delay8 0 μ s( ) 中直接调用 8 次 Delay10us( ) ,此 时
时时间为 82 μ s 。通过修改基本延时函数和适当的组合调用,上述方法可以实现不同时间的延时。

//--------------------------------------------------------------------------------------------------
// 函数名称: Timer0_init()
// 函数功能: 初始化设置
// 设定 INT0 的工作方式
//--------------------------------------------------------------------------------------------------
void Timer0_init(void )
{
TMOD="0x20"; // 定时器 0 工作在方式 2 的定时模式
ET0=1; // 定时器 0 中断允许
TH0=0;
TL0=0;
TR0=1; // 定时器 0 开始计数
EA="1"; // 系统中断允许
}
//--------------------------------------------------------------------------------------------------
// 函数名称: TIMER0_intrupt
// 函数功能: 定时器 0 中断处理程序 按键定时查询
//--------------------------------------------------------------------------------------------------
void TIMER0_SCANkey() interrupt 1 using 1
{
EA="0"; // 系统中断禁止
if((++COUNT_TI)%30==0)
{
switch(COUNT_TI/30)
{
case 1:if(scan_key()==0)
COUNT_TI=0; // 无键按下,计数值归零
break;
case 2:break;
case 3:if(scan_key()==0)
COUNT_TI=0; // 无键按下,计数值归零,上次按键未扰动
else
key_code=scan_key(); // 又有效建,获取键值
break;
default:if(scan_key()==0) // 等待按键释放
key_manage(key_code); // 有一个有效按键,调用按键处理程序
}
}
EA=1;
}


//--------------------------------------------------------------------------------------------------
// 函数名称: delay
// 入口参数: N
// 函数功能:延时子程序,实现 (16*N+24)us 的延时
// 系统采用 11.0592MHz 的时钟时 , 延时满足要求 , 其它情况需要改动
//--------------------------------------------------------------------------------------------------
void delay(unsigned int N)
{
int i;
for(i=0;i<N;i++);
} 


本文关键字:单片机  程序  综合-其它单片机-工控设备 - 综合-其它