51单片机的几种精确延时

原创 2016年08月29日 23:43:27

实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。 今天主要介绍软件延时,关于硬件延时,之后定时器部分再做详细说明。

首先介绍单片机的几个周期

在电子技术中,脉冲信号是一个按一定电压幅度,一定时间间隔连续发出的脉冲信号。脉冲信号之间的时间间隔称为周期;而将在单位时间(如1秒)内所产生的脉冲个数称为频率。频率是描述周期性循环信号(包括脉冲信号)在单位时间内所出现的脉冲数量多少的计量名称;频率的标准计量单位是Hz(赫)。电脑中的系统时钟就是一个典型的频率相当精确和稳定的脉冲信号发生器。

指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。

时钟周期:也称为振荡周期,一个时钟周期 = 晶振的倒数。对于单片机时钟周期,时钟周期是单片机的基本时间单位,两个振荡周期(时钟周期)组成一个状态周期。

机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作,如取指令、存储器读/写等。

机器周期=6个状态周期=12个时钟周期。

51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/ 晶振频率)= x μs。常用单片机的晶振为11.0592MHz,12MHz,24MHz。其中11.0592MHz的晶振更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。

接下来列出这三种不同的晶振的延时函数

1、 11.0592MHz

//N ms延时
void delay_ms(uint n)
{
uint i,j;
for(i=n;i>0;i–)
for(y=114;y>0;y–);
}

2、12MHz晶振


//延时n毫秒
void delay_ms(unsigned int n)
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}

//延时n秒
void delay_m(unsigned int n)
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<21738;j++);
}
//延时10*n微秒
void delay_10um(unsigned int n)
{
    while(n--);
}

3、24MHz晶振

//延时n毫秒
void delay_ms(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i

//延时n秒  
void delay_s(unsigned int n)  
{  
    unsigned int i=0,j=0;  
    for(i=0;i<n;i++)  
        for(j=0;j<54053;j++);   
}  
//延时10*n微秒  
void delay_10us(unsigned int n)  
{  
    unsigned int i=0;  
    char j=0;  
    for(i=0;i<n;i++)  
        for(j=0;j<2;j++);  
}  

建议大家封装为头文件,可以方便的调用。

接下来介绍几个自动适应主时钟的延时函数

//参数:ms,要延时的ms数,自动适应主时钟  
#define MAIN_Fosc        11059200UL    //定义主时钟HZ  
typedef unsigned int INT16U;  

void delay_ms(INT16U ms)    //INT16U 等价于 unsigned int  
{  
    INT16U i;  
    do{  
        i=MAIN_Fosc/9600;  
        while(--i);     //96T per loop  
    }while(--ms);       //--ms  ms=ms-1  
}  
//5us 延时函数,自动适应主时钟  
#define MAIN_Fosc        11059200UL    //定义主时钟HZ  

void delay5us()  
{  
    #if MAIN_Fosc == 11059200  
        _nop_();  
    #elif MAIN_Fosc == 12000000  
        _nop_();  
    #elif MAIN_Fosc == 22118400  
        _nop_(); _nop_(); _nop_();  
    #elif  
}  

单片机中还可自动生成

//11.0592MHZ延时100微秒

void Delay100us()       //@11.0592MHz
{
    unsigned char i, j;

    _nop_();
    _nop_();
    i = 2;
    j = 15;
    do
    {
        while (--j);
    } while (--i);
}

//100US

void Delay100us()       //@12.000MHz
{
    unsigned char i, j;

    i = 2;
    j = 39;
    do
    {
        while (--j);
    } while (--i);
}

//100US

void Delay100us()       //@24.000MHz
{
    unsigned char i, j;

    i = 3;
    j = 82;
    do
    {
        while (--j);
    } while (--i);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【51单片机】延时函数计算问题以及如何准确延时

几种周期介绍 周期名称 描述 时间 振荡(时钟) 单片机提供时钟脉冲信号的振荡源的周期 T=1/f 状态 振荡周期经二分频后得到的 2T 机器 在一个机器周期内,CPU可以完成一...

51单片机C语言延时函数

关键字:51单片机 C语言 延时函数      C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使...
  • shawsun
  • shawsun
  • 2014年04月26日 23:34
  • 7189

51单片机延时函数

C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。 以某晶振...
  • shawsun
  • shawsun
  • 2014年04月26日 23:34
  • 1638

【转】51单片机精确延迟程序

51单片机精确延时程序(晶振12MHz,一个机器周期1us.) 几个精确延时程序:在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响. ...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

STM32中通过普通延时函数来精确延时

在STM32中处处会用到延时函数,一般而言,对于普通的控制延时,并不会要求特别精确,所以可以使用普通的延时函数,例如 void delay(u32 time) { while(time--); }...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

C51常用延时程序

在一些场合下,我们需要对单片机

3.按键控制LED灯亮灭

实验现象:本实验通过一个按键来控制一个发光二极管的亮灭。按键按一下LED点亮。再按一下LED熄灭。 理论学习: 该实验主要难点:  如何扫描按键的状态?  如何防抖动?  原理讲解: 按键检测原...

用定时器控制Led灯闪烁

实验目的 闪灯程序在嵌入式学习中犹如“Hello World!”在C/C++语言学习中一样经典。它以简单的方式引导了无数的嵌入式爱好者。通过本节的学习你可以基本了解STM32的GPIO以及基本定时器...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:51单片机的几种精确延时
举报原因:
原因补充:

(最多只允许输入30个字)