资料链接:51单片机超声波测距.rar
(一)项目内密
本课题的主要内容是,将超声波传感器安装在一台沿直线行走的小车上,由AT89C51 控制超声波传感器,发出超声信号,记录超声液从发射到接收的所需要的时间,得到其与|被测物体之间的能离。在小车行走的过程中,不断重复测距,得到一组距离数据。由单片机记录测得的距离,经过数据处理,将其显示在液晶屏上。同时,将一组距离数据,由串口传到上位机,由VB程序保存距离数据,并画出曲线,就得到了被测物体的单边轮廓。
(二)课题研究方需
超声波测距仪系统主要由单片机最小系统、超声波模块、LCO显示电路及电源电路组成。系统的主要功能如下:
超声波传感器发射和接收超声波,依据计时时间测量出与被测物体之间的矩离。
AT89CS51单片机作为主控制器,控制超声波信号的发送和接收,可以用来控制发射模块脸发脉冲的开始时间和脉宽,响应接受超声波返回时刻并进行测量和计数发射到返回的时间间隔。
液晶屏显示器实时显示测量距离。
上位机串口通讯,接收距离数据,利用VB程序把则好的距离记下并画出曲线,还原轮那曲线,从而实现通过超声波来测量物体单边轮常测量。
(一)项目设计思想
1、使用HC-SR04超声波传感器模块测量距离
2、使用LCD1602液晶显示屏显示实时测量距离
3、使用L298N电机驱动,驱动两个电机运转,设置一个按键,按下按键,小车前进一段距离
4、开启串口通信,把距离数据通过串口发送到电脑进行处理
(二)购买材料
1、智能小车底盘
2、L298N
3、超声波模块HC-SR04
4、液晶屏 LCD1602
再准备一些其他小元件就OK,单片机最小系统、洞洞板、按键、插座等
(四)编写代码
main.c
/********************************************
项目名称:51超声波测距
作者:化作尘
版本:V1.1
更新时间:V1.0 2020年4月12日18:28:02
V1.1 2020年4月23日13:35:00
邮箱:[email protected]
*********************************************/
#include "reg52.H"//器件配置文件
#include"lcd.h"
//SR04传感器接口
sbit RX = P3^2;
sbit TX = P3^3;
sbit key = P1^4;
char keymode=0; //按键 模式
int keycount=0; //小车运动延时控制
//变量声明
unsigned int time=0;
unsigned long S=0;
char Mode=0;
bit flag=0;
bit flag_KEY=0;
unsigned char act[]={0xff,0xfa,0xf5,0xf9,0xf6}; //小车动作控制
unsigned char disbuff[4] ={0,0,0,0}; //缓存数组用于存放距离信息
/***************************************************************************/
//延时
void delay_ms(unsigned int m)
{
unsigned int b,c;
for(c=0;c<m;c++)
for(b=0;b<120;b++);
}
//短延时
void delay(unsigned int t)
{
while(t--);
}
/***************************************************************************/
void Key(void)//按键扫描函数
{
key = 1;
delay_ms(1);
if(key==0) //检测按键K1是否按下 开关
{
delay_ms(10); //消除抖动 一般大约10ms
if(key==0) //再次判断按键是否按下
{
keymode++;
if(keymode == 2)keymode = 0;
}
while(!key); //检测按键是否松开
}
if(keymode==1) //检测到按键按下了一次,就让运动延时一会
{
keycount++;
if(keycount==550)
{
keycount=0;
keymode=0;
}
}
P1 = act[keymode]; //小车运动控制
}
/***************************************************************************/
//超声波测距函数,距离保存到S
void Conut(void)
{
TX=1; //启动一次模块
delay(10); //延时10US
TX=0;;
while(!RX); //当上次接收完波后,RX引脚是低电平,取反就是1,此while成立,反复判断RX状态。当RX没有接收到返回波时是高电平,取反就是0,此while不成立,跳出
TR0=1; //开启计数
while(RX); //当RX没有接收到返回波,此while成立,程序停在这里一直判断RX状态。当RX接收到返回波,RX引脚变为低电平,此while不成立,跳出
TR0=0; //停止计数
time=TH0*256+TL0; //读出T0的计时数值
TH0=0;
TL0=0; //清空计时器
S=(time*1.7)/100; //算出来是CM
//声音的速度是340m/s,时间的单位是us,计算到秒需要将时间数据/1000000,
//长度=速度*时间,340*time/1000000,长度数据单位是m转换成cm需要乘以100得到340*time/10000,
//小数点都向左移两位得到3.4*time/100,因为超声波是往返了,所以再除以2,得到距离数据(time*1.7)/100
if(Mode==0) //非设置状态时
{
if(S>=999) //超出测量范围显示“-”
{
disbuff[0]='o'-0x30; //“-”
disbuff[1]='v'-0x30; //“-”
disbuff[2]='e'-0x30; //“-”
disbuff[3]='r'-0x30; //“-”
}
else
{
disbuff[0]=S%1000/100; //将距离数据拆成单个位赋值
disbuff[1]=S%100/10;
disbuff[2]='.'-0x30;
disbuff[3]=S%10;
}
}
}
/***************************************************************************/
//定时器0
void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围
{
flag=1; //中断溢出标志
}
/***************************************************************************/
//定时器初始化
void Timer_Init(void)
{
TMOD=0x11; //设T0为方式1
TH0=0;
TL0=0;
TR0=0; //停止计数
ET0=1; //允许T0中断
EA=1; //开启总中断
}
/***************************************************************************/
//串口初始化
void UsartInit()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
EA=1; //打开总中断
TR1=1; //打开计数器
}
/***************************************************************************/
//串口发送距离数据
void Uart_Send(void)
{
/**将距离数据通过串口发送出去**/
SBUF=S/256;//将数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
SBUF=S%256;//将数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
/****************************************************************************/
//主函数
void main(void)
{
int displaycount=0;
Timer_Init(); //初始化定时器
UsartInit(); //串口初始化 9600
LcdInit(); //初始化LCD
LcdWritestr(" superwave "); //液晶显示距离
while(1)
{
Conut(); //计算
displaycount++;
if(displaycount==10)//隔一段时间刷新一次显示屏
{
displaycount=0;
LcdWriteCom(0x80);
P1 = 0xff;
LcdWritestr("distance:"); //液晶显示距离
LcdWriteData(disbuff[0]+0x30);
LcdWriteData(disbuff[1]+0x30);
LcdWriteData(disbuff[2]+0x30);
P1 = act[keymode]; //小车运动控制
LcdWriteData(disbuff[3]+0x30);
LcdWritestr("cm");
}
Key(); //按键控制电机运转
Uart_Send();//串口发送距离数据
}
}
void Usart() interrupt 4
{
RI = 0;//清除接收中断标志位
}
lcd.h
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
void LcdWritestr(uchar *dat);
void LcdWritenum(uint num);
void LcdClean(void);
#endif
lcd.c
#include "lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=20;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
// Lcd1602_Delay1ms(1);//注释让lcd写快一点
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
// Lcd1602_Delay1ms(1);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
// Lcd1602_Delay1ms(1);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWritestr
* 函数功能 : 向LCD写入多个字节的数据
* 输 入 : *dat
* 输 出 : 无
*******************************************************************************/
void LcdWritestr(uchar *dat) //写入字符串
{
while(*dat != '\0')
{
LcdWriteData(*dat);
dat++;
}
}
点个小赞赞,获取资料
发送“51单片机超声波测距" 到我的邮箱:[email protected]
博主能力有限,如有不到之处还请各位批评指正 。