标题:
51单片机三路超声波避障与仿真(proteus8.6)源码
[打印本页]
作者:
慕斯雪芙
时间:
2020-4-13 13:12
标题:
51单片机三路超声波避障与仿真(proteus8.6)源码
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
(36.06 KB, 下载次数: 38)
下载附件
2020-4-13 14:29 上传
51hei.png
(18.82 KB, 下载次数: 45)
下载附件
2020-4-13 14:29 上传
单片机源程序如下:
//==============================================================================================================
//程序标题:基于51单片机的三路超声波小车避障程序================================================================
//定稿日期:------- ====================================================================================
//作 者:------- ====================================================================================
//更新日期:2020.3.8 23:51====================================================================================
//最后撰写人:张 虎 ==========================================================================================
//功 能:三方向避障 ====================================================================================
#include<reg51.h> //头文件(定义了一些特殊的寄存器)
#include<intrins.h>
#include<stdio.h>
//==========3个超声波模块定义================================
sbit Trig_left = P1^0; //左边超声波模块端口定义
sbit Echo_left = P1^1;
sbit Trig_mid = P1^2; //中间超声波模块端口定义
sbit Echo_mid = P1^3;
sbit Trig_right = P1^4; //右边超声波模块端口定义
sbit Echo_right = P1^5;
//=========1个298模块2路电机控制端设置=============================
sbit N1 = P2^0; //L298N模块控制马达,通过N1N2和N3N4端口输出1、0控制电机正转,反转,急停
sbit N2 = P2^1;
sbit N3 = P2^2;
sbit N4 = P2^3;
sbit EN1 = P2^4; //L298N模块使能端(利用PWM计数控制使能端可实现电机转速控制,在本程序中没有体现)
sbit EN2 = P2^5; //
//============定义全局变量=======================================
unsigned int time=0; //定义time为十进制无负号整型变量(0-65535),用于读取距离
unsigned long S_left=0; //左边障碍距离
unsigned long S_mid=0; //中间障碍距离
unsigned long S_right=0; //右边障碍距离
//==============================================================================================
void delayms(unsigned int ms) //延时子函数
{
unsigned char i;
while(ms--)
{
for(i=0;i<113;i++);
}
}
void delay_15us(void) //15us精准延时,误差 0us,用于启动超声波模块
{
unsigned char a;
for(a=6;a>0;a--);
}
//=========转向函数=============================================================================
void turn_down() //向前
{
N1=1;
N2=0;
N3=1;
N4=0;
delayms(500);
}
void turn_back() //向后
{
N1=0;
N2=1;
N3=0;
N4=1;
delayms(500);
}
void turn_left() //向左
{
N1=0;
N2=1;
N3=1;
N4=0;
delayms(500);
}
void turn_right() //向右
{
N1=1;
N2=0;
N3=0;
N4=1;
delayms(500);
}
//==========启动超声波模块完成测距并读取数值(cm)===================================================================
void measure_left(void) //左模块
{
EA=0; //关闭总中断
Trig_left=1; //启动一次模块,信号时间应大于10us
delay_15us();
Trig_left=0;
TH1=0; //定时器1高8位寄存器清零
TL1=0; //定时器1低8位寄存器清零
TF1=0; //定时器1溢出位清零
while(Echo_left==0); //当echo为零时等待变为高电平.等待波发出(Echo_lift为模块发送超声波到接受的时间标志,硬件自行设置,单片机检测即可)
TR1=1; //波发出后立即启动定时器1,让TH1,TL1寄存器数值每1us增加1。
EA=1; //总中断允许,开启计数
while(Echo_left); // 等待反波Echo初始状态为0,模块声波发送后(声波离开发射器),硬件将其置位,当检测到有声波返回时(声波由障碍物反射回到模块,接收器已经接受到声波信号)硬件将其复位。Echo置位的时间的一半即超声波从模块发到障碍物止的时间S=Vt,将此时间乘以340m/s即可得到障碍物距离。
time=TH1*256+TL1; //取值读取测距数值到time 将16进制数转化为十进制
TH1=0; //清零
TL1=0;
TR1=0; //关闭定时器1
S_left=(time*17)/1000; //转换,定时器每1us增加1,将数值取值到time中,若初始值为0也就是从定时器开到定时器关一共经过了time个us,微秒除1000是毫秒再除以1000是秒再乘以声速340m/s,理论上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出来是CM(厘米)
delayms(5); //延时
}
//========右边距离测量(同左边一样)============================================================================================
void measure_right(void) //左模块
{
EA=0;
Trig_right=1; //启动一次模块,信号时间应大于10us
delay_15us();
Trig_right=0;
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //溢出位清零
while(Echo_right==0); //当RX为零时等待变为高电平(Echo_lift为模块发送超声波到接受的时间标志,硬件自行设置,单片机检测即可)
TR1=1; //启动定时器1
EA=1; //开启计数 Echo初始状态为0,模块声波发送后(声波离开发射器),硬件将其置位,当检测到有声波返回时(声波由障碍物反射回到模块,接收器已经接受到声波信号)硬件将其复位。Echo置位的时间的一半即超声波从模块发到障碍物止的时间S=Vt,将此时间乘以340m/s即可得到障碍物距离。
while(Echo_right); //当RX为1计数并等待
time=TH1*256+TL1; //取值读取测距数值 将16进制数转化为十进制
TH1=0; //清零
TL1=0;
TR1=0; //关闭定时器1
S_right=(time*17)/1000; //转换,定时器每1us增加1,将数值取值到time中,若初始值为0也就是从定时器开到定时器关一共经过了time个us,微秒除1000是毫秒再除以1000是秒再乘以声速340m/s,理论上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出来是CM(厘米)
delayms(5); //延时
}
//==============中间距离测量(同左边,右边一样)============================================================================
void measure_mid(void) //左模块
{
EA=0;
Trig_mid=1; //启动一次模块,信号时间应大于10us
delay_15us();
Trig_mid=0;
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //溢出位清零
while(Echo_mid==0); //当RX为零时等待变为高电平(Echo_lift为模块发送超声波到接受的时间标志,硬件自行设置,单片机检测即可)
TR1=1; //启动定时器1
EA=1; //开启计数 Echo初始状态为0,模块声波发送后(声波离开发射器),硬件将其置位,当检测到有声波返回时(声波由障碍物反射回到模块,接收器已经接受到声波信号)硬件将其复位。Echo置位的时间的一半即超声波从模块发到障碍物止的时间S=Vt,将此时间乘以340m/s即可得到障碍物距离。
while(Echo_mid); //当RX为1计数并等待
time=TH1*256+TL1; //取值读取测距数值 将16进制数转化为十进制
TH1=0; //清零
TL1=0;
TR1=0; //关闭定时器1
S_mid=(time*17)/1000; //转换,定时器每1us增加1,将数值取值到time中,若初始值为0也就是从定时器开到定时器关一共经过了time个us,微秒除1000是毫秒再除以1000是秒再乘以声速340m/s,理论上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出来是CM(厘米)
delayms(5); //延时
}
//=========退出死区函数,===================================================================================================
void move_left_or_right(void) //设置左右转向函数
{
turn_back(); //退出死区
N1=N2=N3=N4=1; //前方有障碍物,立刻"急停"然后判断距离
delayms(100); //减速延迟
measure_left(); //重新检测左前方距离
measure_right(); //重新检测右前方距离
if(S_left>=S_right) //左右距离不相等时,通过返回数据进行避障
{
turn_left(); //左转
}
else //右边距离大于左边
{
turn_right(); //右转
}
}
//=======判断障碍物,选择行进路线===================================================================================================
void move(void) //设置前进函数
{
if(S_mid>4) //判断中间障碍物的距离,单位CM(不一定准)
// 如果中间障碍物距离均大于4
{
turn_down(); //前进
}
else //判断中间距离小于等于4,
{
N1=N2=N3=N4=1; //前方有障碍物,立刻"急停"然后判断距离
delayms(100); //减速延时
if(S_mid<=4&&S_right>4) //判断右侧距离是否大于4
{
turn_right(); //右转
}
else //即判断中间及其右侧距离均小于等于4
{
if(S_mid<=4&&S_right<=4&&S_left>4) //判断左侧距离
// 如果左侧障碍物距离大于4
{
turn_left(); //左转
}
else //否则 即三侧均小于等于4,进入死区模式
{
move_left_or_right(); //退出死区函数
}
}
}
}
//==========单片机定时器和计数器设置===============================================
void set(void)
{ delayms(10); //上电延时
TMOD=0x10; //设T0为方式1,GATE=0;
TH1=0x00; //T1高8位重装初值
TL1=0x00; //T1低8位重装初值
EA=1; //开启总中断(全局中断)
Trig_left =0;
Trig_mid =0;
Trig_right =0;
EN1=1; //298模块使能
EN2=1;
N1=N2=N3=N4=0; //开机先制动
}
//============主函数===============================================================
void main(void)
{
set(); //单片机及其298初始化
while(1)
{
measure_left(); //检测前方距离
measure_mid(); //检测前方距离
measure_right(); //检测前方距离
move(); //根据检测结果,避障前进
delayms(10); //延时
}
}
//==========================================================
//TH1=[(65536-设定中断时间)/(机器运行周期数/晶振频率MHZ)]/256; 高8位中断初值计算公式
//TL1=[(65536-设定中断时间)/(机器运行周期数/晶振频率MHZ)]%256; 低8位中断初值计算公式
复制代码
所有资料51hei提供下载:
三路超声波避障(OK).7z
(89.53 KB, 下载次数: 73)
2020-4-13 14:31 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
songxia8013
时间:
2020-4-13 22:08
这状态是怎么变换的呢?怎么一直在空挡呢?
作者:
YANJS
时间:
2020-11-24 11:06
这个怎么改变状态
作者:
8556633
时间:
2020-11-24 16:54
先点赞 再慢慢看
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1