51单片机例程

51单片机

HC-SR04超声波

一、基本介绍

​超声波测距模块是根据超声波遇障碍反射的原理进行测距的,能够发送超声波、接收超声波并通过处理,输出一段和发送与接收间隔时间相同的高电平信号,是常用的测距模块之一。HC-SR04是最常用的超声波测距模块之一,HC-SR04超声波模块可提供2cm~400cm的非接触式距离感测功能,测距精度可达3mm,工作电压为5V;内部模块包括超声波发射器、接收器与控制电路。
Vcc:+5V电源供电;
Trig:输入触发信号(可以触发测距);
Echo:传出信号回响(可以传回时间差);
GND:接地。

二、基本工作原理

(1)采用I/O口连接Trig触发测距,给最少10us的高电平后即可发送超声波;

(2)模块自动发送8个40kHz的方波,并自动检测是否有信号返回;

(3)若有信号返回,经内部电路处理后,通过Echo到I/O口输入一个高电平,高电平持续的时间就是超声波从发射到返回的时间;

(4)测试距离=(高电平时间*音速)/2;音速=340m/s=0.034cm/us。

代码实现

/* 8051单片机头文件,包含特殊功能寄存器定义 */
#include<reg52.h>
/* 内联函数库,包含_nop_()等函数 */
#include<intrins.h>

/* 延时函数,z为延时参数,值越大延时越长 */
void delay(unsigned char z)
{
    unsigned char x,y;
    /* 外层循环,循环z次 */
    for(x=0;x<z;x++)
    {
        /* 内层循环,循环110次(固定延时) */
        for(y=0;y<110;y++)
        {
            ; /* 空指令实现延时 */
        }
    }
}

/* LCD控制引脚定义 */
sbit EN = P2^7;  /* 使能信号 */
sbit RS = P2^6;  /* 寄存器选择(1:数据 0:指令) */          
sbit RW = P2^5;  /* 读写控制(1:读 0:写) */       

/* 检测LCD忙状态函数 */
void jc()       
{
    unsigned char i;
    P0 = 0XFF;   /* P0口置高电平(准备读取) */
    RS = 0;      /* 选择指令寄存器 */
    RW = 1;      /* 设置为读模式 */
    /* 循环检测忙标志,最多200次 */
    for(i=0;i<200;i++)
    {
        EN = 0;  /* 使能脉冲下降沿 */
        EN = 1;  /* 使能脉冲上升沿 */
        /* 读取P0.7(BF忙标志),为0表示不忙 */
        if(!(P0&0X80))
        {
            break; /* 不忙则退出循环 */
        }    
    }
    EN = 0; /* 结束使能 */
}

/* 写数据到LCD函数 */
void xrsj(unsigned char date)
{
    jc();        /* 先检测忙状态 */
    RS = 1;      /* 选择数据寄存器 */
    RW = 0;      /* 设置为写模式 */
    P0 = date;   /* 输出数据到P0口 */
    delay(5);    /* 短暂延时 */
    EN = 1;      /* 使能脉冲上升沿 */
    delay(5);    /* 保持使能 */
    EN = 0;      /* 结束使能 */
}

/* 写指令到LCD函数 */           
void xrml(unsigned char com)
{
    jc();        /* 先检测忙状态 */
    RS = 0;      /* 选择指令寄存器 */
    RW = 0;      /* 设置为写模式 */
    P0 = com;    /* 输出指令到P0口 */
    delay(5);    /* 短暂延时 */
    EN = 1;      /* 使能脉冲上升沿 */
    delay(5);    /* 保持使能 */
    EN = 0;      /* 结束使能 */
}

/*********************** 超声波测距部分 **************************/
unsigned int distance[]={0,0,0,0}; /* 存储距离的各位数字(千、百、十、个位) */
sbit trig = P1^0; /* 超声波触发引脚 */
sbit echo = P1^1; /* 超声波回波引脚 */

/* 函数声明 */
void chufa(); /* 触发超声波 */
void jisuan(); /* 计算距离 */

/* 超声波测距主函数 */
void ceshi()
{
    chufa();     /* 发送触发脉冲 */
    while(!echo); /* 等待回波引脚变高 */
    TR0 = 1;     /* 启动定时器0开始计时 */
    while(echo);  /* 等待回波引脚变低 */
    TR0 = 0;     /* 停止定时器0 */
                  
    jisuan();    /* 计算距离值 */
    delay(5);    /* 短暂延时 */        
}

/* 超声波触发函数 */
void chufa()
{
    trig = 0;    /* 初始低电平 */
    trig = 1;    /* 触发高电平 */
    /* 16个_nop_()实现约16us的脉冲(12MHz时钟) */
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
    trig = 0;    /* 恢复低电平 */    
}

/* 距离计算函数 */
void jisuan()
{
    unsigned int x,y;
    /* 计算定时器计数值(TH0为高8位,TL0为低8位) */
    x = TH0 * 256 +TL0;
    /* 时钟校正(12MHz时钟,11.0592MHz计算) */
    x *= 12/11.0592;
    /* 计算距离(cm):340m/s声速,时间x单位为us */
    /* 0.017 = 34000/1000000/2 (往返时间要除以2) */
    y = x * 0.017;
    
    /* 重置定时器 */
    TH0 = 0;
    TL0 = 0;
    /* 分解距离的各位数字 */
    distance[3] = y / 1 % 10;   /* 个位 */
    distance[2] = y / 10 % 10;  /* 十位 */
    distance[1] = y / 100 % 10; /* 百位 */
    distance[0] = y / 1000 % 10;/* 千位 */
}

/* 显示距离函数 */
void xsjl()
{
    unsigned char i;
    /* 设置LCD显示位置(第二行开头) */
    xrml(0x80+0x40);
    /* 显示4位距离数字 */
    for(i=0;i<4;i++)
    {
        /* 数字转ASCII码(加0x30) */
        xrsj(0x30+distance[i]);
        delay(5);
    }    
}

/*********************** 初始化部分 **************************/
void init()
{
    EA = 1;      /* 开启总中断 */
    ET0 = 1;     /* 开启定时器0中断 */
    TMOD = 0X01; /* 设置定时器0为模式1(16位定时器) */
    TH0 = 0;     /* 定时器初值清零 */
    TL0 = 0;
    /* LCD初始化指令序列 */
    xrml(0x38);  /* 8位数据接口,两行显示,5x7点阵 */
    xrml(0x0c);  /* 开显示,关光标 */
    xrml(0x06);  /* 地址自动增加 */
    xrml(0x01);  /* 清屏 */
}

/*********************** 主函数 **************************/
void main()
{
    /* LCD显示内容定义 */
    unsigned char yi[] = {"ChaoShengBo JuLi"}; /* 第一行文本 */
    unsigned char er[] = {"cm"};               /* 单位 */
    unsigned int k = 0;
    
    init();      /* 系统初始化 */
    
    /* 显示第一行文本 */
    xrml(0x80);  /* 设置第一行起始地址 */
    for(k=0;k<16;k++)
    {
        xrsj(yi[k]); /* 逐个字符显示 */
        delay(5);
    }
    
    /* 显示单位"cm" */
    xrml(0x80+0x44); /* 设置第二行第5列位置 */
    for(k=0;k<2;k++)
    {
        xrsj(er[k]); /* 显示"c"和"m" */
        delay(5);
    }

    /* 主循环 */
    while(1)
    {    
        ceshi(); /* 执行测距 */
        xsjl();  /* 显示距离 */    
    }    
}
posted @ 2025-06-27 12:19  LGQLHT  阅读(49)  评论(0)    收藏  举报