51单片机课程设计:基于51单片机的超声波测距(测距原理介绍)

    本程序利用超声波模块来进行距离的测量,并显示在数码管上,其他朋友可以在本程序的基础上,修改部分代码,应用到智能小车上或者其他测距设备上。

    超声波测距的原理是:首先给模块Trig端一个高电平,然后单片机开始计时,同时模块会发射超声波信号,当单片机检测到Echo端为高电平时(也就是说模块收到反射的信号),计时停止。通过以上操作,我们就可以得到一个时间变量,然后调用对应的公式就可以将时间变量转换为距离。

    相关工程文件以及资料在文章下方,感兴趣的朋友可以下载。

    关于粘贴复制乱码的问题:如果程序复制到Keil编译器上出现注释乱码,可以先建一个.c文件,也就是说不在keil里面编辑,然后用记事本打开.c文件,将源码复制进去,再在keil中添加文件即可。

/****************************************************************
                    基于51单片机的超声波测距例程
如果需要在其他开发板上运行并显示,只需要修改数码管显示模块即可
DisplayData[8]用于存放转换后的距离数据,也就是说你只需要将其中
的数据在其他显示模块显示出来。
    引脚3.1 接模块Trig
    引脚3.2 接模块Echo
    晶振频率一般都是12MHZ
                            2016-12-30---------------------SWorld
****************************************************************/
#include
#define uchar unsigned char   //宏定义无符号字符型
#define uint  unsigned  int   //宏定义无符号整型
#define GPIO_DIG P0//位选以及段选数据输出端口定义
unsigned char code DIG_CODE[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示段码 数码管字跟
unsigned char DisplayData[8];//用来存放要显示的8位数的值
sbit DUC=P2^2;//   DUC段选信号
sbit WEC=P2^3;//WEC    位选信号
sbit Trig=P3^1; 
sbit Echo=P3^2;
uchar succeed_flag=0;
uint timeH,timeL,distance=0,time=0,ss;
//float ;
//延时子程序   延时1ms
void delay_ms(uint c)
{
    uchar a, b;
    for(;c>0;c--)
    {
        for (b=38;b>0;b--)
        {
            for (a=13;a>0;a--);
        }      
    }   
}
//延时子程序  延时1us
void delay_us(uint c)
{
    uchar a ;
    for(;c>0;c--)
        for(a=0;a<5;a++);
}

//数码管显示
void DigDisplay()
{
    unsigned char i;
    unsigned int j;
    for(i=0;i<8;i++)
    {
        WEC=1;DUC=0;
        switch(i) //位选,选择点亮的数码管,
        {
            case(0):
                GPIO_DIG=0x7F; break;//显示第0位
            case(1):
                GPIO_DIG=0xBF; break;//显示第1位
            case(2):
                GPIO_DIG=0xDF; break;//显示第2位
            case(3):
                GPIO_DIG=0xEF; break;//显示第3位
            case(4):
                GPIO_DIG=0xF7; break;//显示第4位
            case(5):
                GPIO_DIG=0xFB; break;//显示第5位
            case(6):
                GPIO_DIG=0xFD; break;//显示第6位
            case(7):
                GPIO_DIG=0xFE; break;//显示第7位
        }
        WEC=0;DUC=1;
        GPIO_DIG=DisplayData[i];//发送段码
        j=15; //扫描间隔时间设定
        while(j--);
        GPIO_DIG=0x00;//消隐
    }
}
//主函数模块
void main(void)
{
    Trig=0;
    EA=1;
    TMOD=0x11;//定时器1,16位工作方式  定时器0 16位工作方式
    while(1)
    {
        EA=0;           //关总中断
        Trig=1;         
        delay_us(20);   //延时20us
        Trig=0;         //20us脉冲
        while(Echo==0);    //等待Echo回波引脚变高电平
            succeed_flag=0; 
        EA=1; //开外部中断
        EX0=1;         //打开外部中断0
        TH1=0;          //定时器1缺清零
        TL1=0;   //计数溢出标志
        TF1=0;          
        TR1=1;          //启动定时器1
        delay_ms(20);      
        TR1=0;          //关闭定时器1
        EX0=0;          //关外部中断
        if(succeed_flag==1)
        {   
            time=timeH*256+timeL;
            distance=time*0.172;  
         }                         
         if(succeed_flag==0)
        {
            distance=0;                    
        } 
        DisplayData[5]=DIG_CODE[distance/100];
        DisplayData[4]=DIG_CODE[(distance%100)/10];  
        DisplayData[3]=DIG_CODE[distance%10];  
        for(ss=0;ss<200;ss++)
        DigDisplay();
    }
}
//外部中断0  用于判断回波电路
void exter()  interrupt 0   
{   
     timeH =TH1;    //取出定时器值H
     timeL =TL1;    //取出定时器值L
     succeed_flag=1;//成功测量标志
     EX0=0;         //关外部中断
}
//定时器1中断  用作超声波测距计时
void timer1() interrupt 3  
{
    TH1=0;
    TL1=0;
}