找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 298|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机的几种精确延时

[复制链接]
跳转到指定楼层
楼主
yixingzhb 发表于 2020-10-13 11:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高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);
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享分享 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
bababibu 发表于 2020-10-15 08:49 | 只看该作者
谢谢楼主的分享。如果能结合振晶频率在代码中再注释一下时延的计算过程,就更利于小白学习了。
回复

使用道具 举报

板凳
坤人 发表于 2020-10-17 16:56 | 只看该作者
楼主 我还有点不懂的地方可以求解吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表