写在前面:
超声波测距模块是51单片机项目中比较常见的一个模块,常用于智能小车等需要测量障碍物距离的一个模块。但是其并不是开发板上携带的模块,本节我们学习如何让使用超声波测距,并在LCD1602上进行距离显示;
目录
一、认识HC-SR04
HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
特点:
典型工作电压:5v;
探测距离:2cm-450cm(5V);
探测角度:15°;
高精度:0.3cm;
产品实物图:
该模块共有四个引脚分别为:
VCC | 电源正极 |
GND | 电源地 |
Trig | 触发信号输入 |
Echo | 回响信号输出 |
模块的基本工作原理:
1、利用IO口中Trig触发测距 ,要求:给出至少10us的高电平;
2、模块自动发出8个40KHz的方法,自动检测是否有信号返回;
3、有信号返回,通过IO口Echo输出一高电平;
4、高电平的时间超声波从发射到返回的时间,测试距离=(高电平时间*声速(340m/s))/2
二、超声波时序图
工作流程:
以上时序图表明你只需要提供一个 10us 以上脉冲触发信号,该模块内部将发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。 回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号 时间间隔可以计算得到距离。公式:距离= 高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对回响信号的影响。
其他注意事项:
测距时,被测物体的面积不少于0.5平方米且要尽量平整。 否则会影响测试结果。
如果测试面不是很规则或则测试远距离物体时,可采用多次测量的方法来校正。
此外,温度、湿度、压力、气流都可能造成测试时的准确性;
三、软件实现
项目说明:
通过超声波测试出前方障碍的距离,通过LCD1602液晶屏幕进行显示,并点亮对应位置的LED灯;此处利用定时/计数器计算进行回响信号脉冲的时间;
源码:
main.c文件
#include <REGX52.H>//包含51头文件
#include "delay.h"//包含延时函数
#include "LCD1602.h"//包含LCD1602液晶显示屏
#include "UT.h"//包含超声波模块
sbit LED1=P2^0;//定义对应LED引脚
sbit LED2=P2^1;
sbit LED3=P2^2;
unsigned int dis;//定义距离变量
void LED(unsigned int dis)//通过距离点亮对应的LED灯
{
if(dis<20)
{
LED1=0;
LCD_ShowString(2,1,"LED1");
}
else if(50>dis && dis>20)
{
LED2=0;
LCD_ShowString(2,1,"LED2");
}
else if(50<dis)
{
LED3=0;
LCD_ShowString(2,1,"LED3");
}
}
void main()//主函数
{
LCD_Init();//LCD1602初始化
UT_Init();//超声波模块初始化
LCD_ShowString(1,1,"distance:");
while(1)
{
UT_triggr();//触发测距信号
dis=measure();//返回测距数值
LCD_ShowNumber(1,10,dis,3);//显示测试距离
LED(dis);//点亮LE 函数
Delay100ms(20);//延时2秒
LED1=1;
LED2=1;
LED3=1;
}
}
UT.c文件
#include <REGX52.H>
#include "delay.h"
sbit Trig=P1^6;//定义超声波模块引脚
sbit Echo=P1^5;
/**
*@breaf 定时计数器1初始化
*@param 无
*@retval 无
*/
void T0_Init()
{
TMOD=0x01;//定义计时器0工作方式为1
TH0=0;//定义定时器初值
TL0=0;
ET0=1;//开定时器0中断
EA=1;//开总中断
}
/**
*@beaf 超声波模块初始化
*@param 无
*@retval 无
*/
void UT_Init()
{
Echo=0;
Trig=0;
T0_Init();
}
/**
*@beaf 超声波模块触发函数
*@param 无
*@retval 无
*/
void UT_triggr()
{
Trig=1;
Delay10us(2);
Trig=0;
}
/**
*@beaf超声波测距
*@param 无
*@retval distance 测试的距离
*/
unsigned int measure()
{
unsigned int a,distance;
while(Echo==0);
TR0=1;
while(Echo);
TR0=0;
a=TH0*256+TL0;
TH0=0;
TL0=0;
distance= a*1.7/100;
return distance;
}
LCD1602.c文件
#include <REGX52.H>
//引脚配置:
sbit LCD_RS=P2^6; // RS引脚为数据/指令选择 1为数据,0为指令
sbit LCD_RW=P2^5; // RW引脚为读/写选择 1为读,0为写
sbit LCD_EN=P2^7; // EN引脚为使能 1为数据有效,下降沿执行命令
#define LCD_DataPort P0 //定义P0引脚为数据端口
//延迟函数的定义;LCD1602延时函数,12MHz调用可延时xms;
void LCD_Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//写指令函数定义: LCD1602写指令函数
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;//选择为指令,1为数据,0为指令
LCD_RW=0;//选择为写, 1为读,0为写
LCD_DataPort=Command;//写入指令的内容
LCD_EN=1; //使能脚E先上升沿写入
LCD_Delay(1);
LCD_EN=0; //使能脚E后负跳变完成写入
LCD_Delay(1);
}
// 写数据函数定义: LCD1602写数据函数
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1; //选择为数据,1为数据,0为指令
LCD_RW=0; //选择为写, 1为读,0为写
LCD_DataPort=Data;//写入指数据的内容
LCD_EN=1; //使能脚E先上升沿写入
LCD_Delay(1);
LCD_EN=0; //使能脚E后负跳变完成写入
LCD_Delay(1);
}
//初始化函数定义: LCD1602屏幕初始化
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
//LCD1602 进行清屏
void LCD_clear()
{
LCD_WriteCommand(0x01);
}
//设置光标位置
void LCD_SetCursor(unsigned char Line,unsigned char Column)//(行数1-2,列数1-16)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
// 字符串函数定义: LCD1602显示字符串
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
// 字符数字函数定义: LCD1602显示数字
int Pow(int x,int y)
{
unsigned char i;
int result = 1;
for(i = 0; i < y; i++)
{
result *= x;
}
return result;
}
void LCD_ShowNumber(unsigned char Line,unsigned char Column,unsigned int number,unsigned char length)
{
unsigned char i;
unsigned char temp;
LCD_SetCursor(Line,Column);
for(i =length ; i > 0 ; i--)
{
temp = number/Pow(10,i-1)%10 + '0'; //循环将每一位都提取出来并转换为字符
LCD_WriteData(temp);
}
}
delay.c文件
#include <intrins.h>
/**
*@breaf 延时函数@11.0592MHz 基本单位是100ms
*@param t 为延时的时间 t*100ms
*@retval 无
*/
void Delay100ms(unsigned char t) //@11.0592MHz
{
unsigned char i, j;
while(t--)
{
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
}
/**
*@breaf 延时函数@11.0592MHz 基本单位是10us
*@param t 为延时的时间 t*10us
*@retval 无
*/
void Delay10us(unsigned char t)//@11.0592MHz
{
while(t--)
{
unsigned char i;
i = 2;
while (--i);
}
}
/**
*@breaf 延时函数@11.0592MHz 基本单位是1ms
*@param t 为延时的时间 tms
*@retval 无
*/
void Delay1ms(unsigned char t) //@11.0592MHz
{
unsigned char i, j;
while(t--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
四、实验现象
超声波测距
链接:https://pan.baidu.com/s/1UwZlOn0Qd_m0CaUzZabolw
提取码:1022
总结:本节我们学习了超声波模块的基本知识,其内容还是比较好理解,主要的内容是超声波时序图,我们在此基础上,利用超声波实现了测距以及LCD1602屏幕的显示;
创作不易,还请大家多多点赞👍支持!!