单片机中用写delay函数做延时和用定时器做延时有啥区别?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单片机中用写delay函数做延时和用定时器做延时有啥区别?相关的知识,希望对你有一定的参考价值。

两者都可以起到延时的作用。写delay函数做延时,利用CPU处理很多循环,而每次处理一个循环就需要一个指令周期。定时器做延时时利用晶振的脉冲,计数器记录到溢出,而后可以做其他事情。在动态数码管输入扫描信号的时候为什么我们要用定时器做延时?这两种都延时方式有什么区别?

定时器的做法是在你的程序里还有其他事要做的情况下去设置的。也就是说设置了定时器后就可以去做其他事情了,delay就是不做事光用消耗的,消耗一定的时间后再去做其他事 参考技术A 利用循环处理的方式实现的延时,并不精确。
1、当中断发生时,CPU被打断先执行中断服务。导致执行时间变长。
2、使用高级语言时,编译的结果受优化等级等多方面因素干扰,难以计算。

3、在有MMU和Cache的MCU中,指令的执行速度还会受到缓存的影响。
利用定时器延时:
1、因为定时器累加与CPU无关,即使中断,仍然会保持计数。不受上述问题影响
2、缺点需要占用定时器资源。
3、功耗也会高一些本回答被提问者和网友采纳

I2C总线

1. 定义方法

  a.定义起始信号

  b.定义终止信号

  c.定义单片机写入函数

  d.定义单片机读出函数

  e.写入到指定元器件

  f.从指定元器件读出

  g.写一个头文件作为中转

  h.写一个主函数实现对写入读出的调用

 

2. 定义起始信号

  a.SDA 高电平延时

  b.SCL高电平延时

  c.SDA低电平延时

  d.SCL低电平延时

  

    SDA = 1;
    Delay10us();
    SCL = 1;
    Delay10us();
    SDA = 0;
    Delay10us();
    SCL = 0;
    Delay10us();
View Code

  

 

 

3. 终止信号

  a.SDA低电平延时

  b.SCL高电平延时

  c.SDA高电平延时

  

    SDA = 0;
    Delay10us();
    SCL = 1;
    Delay10us();
    SDA = 1;
    Delay10us();
View Code

 

  

4. 单片机写入函数

  a.定义函数需要返回值,需要一个8位形式参数

  b.for循环8次,每次发送一个数据,通过数据左移右移实现,每次写入SDA后要把SCL电平拉低

  c.循环完成后拉高SDA延时后拉高SCL让SDA保持不变

  d.while(SDA)循环等待元器件应答,应答后SDA会被拉低跳出循环

  e.返回值

unsigned char sendaddr(unsigned char dat)
{
    unsigned char a=0,b=0;
    for(a=0;a<8;a++)
    {    SDA=dat>>7;
        dat<<=1;
        Delay10us();
        SCL = 1;
        Delay10us();
        SCL = 0;
        Delay10us();            
    }
    SDA = 1;
    Delay10us();
    SCL = 1;    
    while(SDA)
    { b++;
      if(b>200)
      { SCL = 0;
        Delay10us();
          return 0;
      }
    }
    SCL = 0;
    Delay10us();
    return 1;
}
View Code

5. 单片机读出函数  

  a.定义函数需要返回值不需要形式参数

  b.定义变量作为容器接收数据

  c.for循环8次,先拉高电平保持SDA稳定,num<<=1,num|=SDA 拉低电平

  e.返回num

unsigned char reader()
{
 unsigned char a,num;
  num = 0;
 //SDA = 1;
  Delay10us();
  for(a=0;a<8;a++)
  {
      SCL = 1;
     Delay10us();
     num<<=1;
     num|=SDA;
     Delay10us();
     SCL=0;
     Delay10us();
  }
    return num;
}
View Code

6. 写入元器件函数

  a.定义函数不需要返回值,需要两个形式参数

  b.起始信号>>写入函数(元器件地址0)>>写入函数(元器件首地址)>>写入函数(写入值)>>终止信号

void A204write(unsigned char addr,unsigned char dat)
{
    start();
    sendaddr(0xa0);
    sendaddr(addr);
    sendaddr(dat);
    stop();    

}
View Code  

7. 从元器件读出函数

  a.定义带返回值的函数不需要形式参数

  b.起始信号>>写入函数(元器件地址0)>>写入函数(元器件首地址)>>起始信号>>写入函数(元器件地址1)>>接收SDA的值>>终止信号

  c.返回值  

unsigned char A204read(unsigned char addr)
{
    unsigned char num;
    start();
    sendaddr(0xa0);    
    sendaddr(addr);
    start();
    sendaddr(0xa1);
    num = reader();
    stop();
    return num;
}
View Code

 

8.总代码

  a.主函数 

#include<reg52.h>
#include"i2c.h"
/*
  1.延时函数
  2.定义每个按键的作用
  3.根据num选择数码管的值赋值给P0
*/

typedef unsigned char u8;
typedef unsigned int u16;

sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4;

sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;

u8 num=0;
u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//延时函数
void lay10us(i)
{
     while(i--);
}
//独立按键函数
void Keypros()
{
    if(K1==0)
    {
        lay10us(10);
        if(K1==0)
        {
            A204write(1,num);
        }
        while(!K1);
    }
    if(K2==0)
    {
        lay10us(10);
        if(K2==0)
        {
            num = A204read(1);
        }
        while(!K2);    
    }    
    if(K3==0)
    {
        lay10us(10);
        if(K3==0)
        {
            num++;
        }
        while(!K3);
    }
    if(K4==0)
    {
        lay10us(10);
        if(K4==0)
        {
            num=0;
        }
    }
    while(!K4);

}
//num按键次数转换为数码管段函数
void dat()
{
    disp[0]=smgduan[num%1000%100%10];
    disp[1]=smgduan[num%1000%100/10];
    disp[2]=smgduan[num%1000/100];
    disp[3]=smgduan[num/1000];
}
//点亮数码管函数
void dispaly()
{
    u8 a;
    for(a=0;a<4;a++)
    {
        switch(a)
        {
            case(0):
                LA=0;LB=0;LC=0;    break;     //数码管第0个
            case(1):
                LA=1;LB=0;LC=0;    break;
            case(2):
                LA=0;LB=1;LC=0;    break;
            case(3):
                LA=1;LB=1;LC=0;        //数码管第4个
        }
        P0=disp[a];
        lay10us(100);
        P0=0x00;                   //数码管消隐
    }    
}

void main()
{
    while(1)
    {
    Keypros();
    dat();
    dispaly();
    }    
}
View Code

  b.子函数

#include<reg52.h>
#include"i2c.h"
unsigned char u8;

/*
  1.起始函数
  2.终止函数
  3.写入函数
  4.接收函数
  5.芯片发送函数
  6.芯片接收函数
*/


/*
  延时函数,延时6us
*/
void Delay10us()
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=2;a>0;a--);

}

/*
  这是起始信号函数
*/
void start()
{
    SDA = 1;
    Delay10us();
    SCL = 1;
    Delay10us();
    SDA = 0;
    Delay10us();
    SCL = 0;
    Delay10us();
} 

/*void start()
{
    SDA=1;
    Delay10us();
    SCL=1;
    Delay10us();//建立时间是SDA保持时间>4.7us
    SDA=0;
    Delay10us();//保持时间是>4us
    SCL=0;            
    Delay10us();        
}  */
/*
  这是终止信号函数
*/
void stop()
{
    SDA = 0;
    Delay10us();
    SCL = 1;
    Delay10us();
    SDA = 1;
    Delay10us();
} 




/*
    写入函数,将主机内容发送到芯片中
            
*/
unsigned char sendaddr(unsigned char dat)
{
    unsigned char a=0,b=0;
    for(a=0;a<8;a++)
    {    SDA=dat>>7;
        dat<<=1;
        Delay10us();
        SCL = 1;
        Delay10us();
        SCL = 0;
        Delay10us();            
    }
    SDA = 1;
    Delay10us();
    SCL = 1;    
    while(SDA)
    { b++;
      if(b>200)
      { SCL = 0;
        Delay10us();
          return 0;
      }
    }
    SCL = 0;
    Delay10us();
    return 1;
}



/*
  读出函数,将芯片的数据读出到主机中
*/

unsigned char reader()
{
 unsigned char a,num;
  num = 0;
 //SDA = 1;
  Delay10us();
  for(a=0;a<8;a++)
  {
      SCL = 1;
     Delay10us();
     num<<=1;
     num|=SDA;
     Delay10us();
     SCL=0;
     Delay10us();
  }
    return num;
}

/*
  写入芯片
  1.起始函数
  2.写入函数发送地址
  3.写入函数发送器件内部地址
  4.写入函数发送数据
  5.终止函数
*/

void A204write(unsigned char addr,unsigned char dat)
{
    start();
    sendaddr(0xa0);
    sendaddr(addr);
    sendaddr(dat);
    stop();    

}


unsigned char A204read(unsigned char addr)
{
    unsigned char num;
    start();
    sendaddr(0xa0);    
    sendaddr(addr);
    start();
    sendaddr(0xa1);
    num = reader();
    stop();
    return num;
}
View Code

  c.头文件

  

#ifndef _I2C_H
#define _I2C_H
#include<reg52.h>
sbit SCL = P2^1;
sbit SDA = P2^0;

void delay6us(void);
void start();
void stop();
unsigned char sendaddr(unsigned char dat);
unsigned char reader();
void A204write(unsigned char addr,unsigned char dat);
unsigned char A204read(unsigned char addr);

#endif

 

 

 

 

 

 

 

以上是关于单片机中用写delay函数做延时和用定时器做延时有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

单片机中delay函数精确延时多少ms?

C语言delay函数延时计算

stm32中Delay()函数延时的时间是怎么计算的?

51单片机定时器0作为时间基准以及延时函数参考使用

怎么用定时器写延时函数

51单片机C语言程序中延时函数delay的原理是啥?