请问有人能帮忙看一下我的问题在哪里吗?
想测试用51单片机超声波避障功能,
用LED显示效果:
P1口对应的单片机LED如下:
P10-LED1
P11-LED2
P12-LED3
P13-LED4
P14-LED5
P15-LED6
P16-LED7
P17-LED8
写入单片机后,希望可以控制小车实现避障
一、目标如下
(一)距离大于20时:
#前进:
#P1^0=1,
#P1^1=0,
#P1^2=1,
#P1^3=0,
#P1^4=PWM,
#P1^5=PWM,
#即在单片机上
#共阳LED1~8:0101,1100,(1为亮,0为不亮)
#其中LED5和LED6闪烁或者亮度较低
(二)距离小于20时:
#左旋转:
#P1^0=0,
#P1^1=1,
#P1^2=1,
#P1^3=0,
#P1^4=PWM,
#P1^5=PWM
#即单片机上:
#LED1~8亮1001,1100,
#其中LED5和LED6闪烁或者亮度较低
二、实际实验结果:程序下载并启动启动后,未按照要求的输出:显示的是LED2和LED4亮,无论如何改变超声波模块与障碍物距离,都无法达到目标。
寻迹代码来源:https://mp.weixin.qq.com/s/vFqbx-vwkY-K6JfZHAflQw
超声波代码来源:https://blog.csdn.net/ca1m0921/article/details/80549746?utm_source=app
#include <reg52.h>
#include <math.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//#define led P2 //流水灯宏定义P2口
sbit L=P0^0; //循迹模块L路:左
sbit M=P0^1; //循迹模块M路:中
sbit R=P0^2; //循迹模块R路:右
sbit TX = P0^3; //超声波产生脉冲引脚
sbit RX = P0^4; //回波引脚
sbit IN1=P1^0; //电机1 ZUO
sbit IN2=P1^1;
sbit IN3=P1^2; //电机2
sbit IN4=P1^3;
sbit ENA=P1^4; //左使能A
sbit ENB=P1^5; //右使能B
uchar m1=0,m2=0; //电机预定速度值
uchar tmp1,tmp2; //电机当前速度值
uchar moto_t=0,n,g,g1,tt=0;//参数:moto__t->pwm计数,n->保留,g-->循迹模式下当前状态,g1-->保留,tt-->
//unsigned int m,t; //流水灯变量
unsigned int time=0;//超声波计数时间
float Distance=0;//距离:用时间计算
bit flag =0; //超声波:T1中断溢出标志
//bit csb_s=0;
void delayms(unsigned int ms);//申明延时函数
void init_Timer();//申明定时器
void motor(int num, int speed);//申明电机控制函数
void zhidong();//申明制动函数
void zhizou();//申明直走函数
void daotui();//申明倒退函数
void youzhuan1();//申明右转函数1
void youzhuan2();//申明右转函数2
void zuozhuan1();//申明左转函数1
void zuozhuan2();//申明左转函数2
void StartModule();//申明超声波发送函数
void Conut();//申明超声波计算与控制电机的函数
void xunji();//申明循迹函数
void csb();//申明超声波作用函数
void main()
{
init_Timer();//定时器初始化
while(1)
{
csb();//调用超声波函数
}
}
void delayms(unsigned int ms)//延时函数
{
unsigned char i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}
}
}
/*******T0定时器初始化*******/
void init_Timer()
{
TMOD=0x22; //T0/T1采用工作方式2
// TF0=1;
TR0=0; //开启定时器T0 :pwm用
ET0=1; //T0中断允许
TH0=0x9b; //定时器T0装入定时器的初值定时100us
TL0=0x9b;
// TF1=1;
TR1=0; //开启定时器T1-->超声波计时
ET1=1; //允许T1中断
TH1=0; //T1初始化,用于判断测距溢出,最大65.536 ms
TL1=0;
EA=1; //开总中断
// IT1=1; //下降沿触发
// EX1=1; //外部中断
}
/********电机处理********/
void motor(int num, int speed) //num:电机号,speed:速度 //motor(电机号,pwm速度值)
{
// ET0=1; 这里原本打算用来初始化T0,但是发现行不通
// ET1=0;
if(speed>=-100 && speed<=100)
{
if(num==1) //电机1的处理
{
m1=abs(speed); //取速度的绝对值
if(speed<0) //判断正反转 //速度值为负则反转
{
IN1=0;
IN2=1;
}
else //不为负数则正转
{
IN1=1;
IN2=0;
}
}
if(num==2)
{
m2=abs(speed);
if(speed<0)
{
IN3=0;
IN4=1;
}
else
{
IN3=1;
IN4=0;
}
}
}
}
/****T0中断服务程序****/
void timer0() interrupt 1
{
/*****电机pwm输出*****/
if(moto_t==0) // 1个PWM周期完成后才会接受新数值
{
tmp1=m1;
tmp2=m2;
}
if(moto_t<tmp1)//产生电机1的PWM信号
{
ENA=1;
}
else
{
ENA=0;
}
if(moto_t<tmp2)//产生电机2的PWM信号
{
ENB=1;
}
else
{
ENB=0;
}
moto_t++;
if(moto_t>=100)//1个PWM信号由100次中断产生
{
moto_t=0;
// TH0=0x9b;
// TL0=0x9b;
}
// t++;
}
/******电机方向控制*******/
void zhizou() //直走
{
motor(1,60);
motor(2,55);
}
void youzhuan1() //右转1
{
motor(1,0);
motor(2,40);
}
void youzhuan2() //右转2
{
motor(1,70);
motor(2,-70);
}
void zuozhuan1() //左转1
{
motor(1,30);
motor(2,0);
}
void zuozhuan2() //左转2
{
motor(1,-80);
motor(2,80);
}
void zhidong() //制动
{
ENA=0;
ENB=0;
}
void daotui()
{
motor(1,-60);
motor(2,-60);
}
void xunji()
{
if (R==0 && M==1 && L==0)
{
zhizou();
g=0;//用于走出黑线判断返回方式
}
/*****右转处理******/
if ((R==0 && M==1 && L==1) || (R==0 && M==0 && L==1))
{
youzhuan1();
g=1;//用于走出黑线判断返回方式
}
/******左转处理******/
if ((R==1 && M==1 && L==0) || (R==1 && M==0 && L==0))
{
zuozhuan1();
g=2;//用于走出黑线判断返回方式
}
/*****全黑****/
if (IN3==1 && IN2==1 && IN1==1)
{
zhizou();
g=3;//用于走出黑线判断返回方式
}
/*****跑出轨道记忆回到跑道上****/
if (IN3==0 && IN2==0 && IN1==0)
{
switch (g)
{
case 0:
youzhuan2();//从线的终点出去,右旋转回到线上
break;
case 1:
zuozhuan1();//右转出线,左转回到线上
break;
case 2:
youzhuan1();//左转出线,右转回到线上
break;
case 3:
daotui();//跨越黑线,倒退回到线上
break;
case 4:
youzhuan2();
break;
}
g=4;//如果最后走出线,右旋转回到线上
}
}
void csb()
{
// ET1=1;
// ET0=0;
StartModule();//发送超声波信号
while(!RX); //当超声波模块接收口输出低电平则等待
TR1=1; //开启计数
while(RX); //当RX为1计数并等待
TR1=0; //关闭计数
Conut(); //计算距离,做出相应措施 //读取定时器的值,计算
delayms(60);
// if(csb_s == 0)//一开始想把距离判断用变量存储起来,然后再控制小车做出动作,但最后发现行不通
// {
// zhizou();
// }
// if(csb_s == 1)
// {
// zuozhuan1();
// }
}
void StartModule() //超声波模块Trig控制端给大于10us的高电平触发模块测距
{
TX=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX=0;
}
void Conut()
{
time=TH1*256+TL1;//计算时间
TH1=0;
TL1=0;
Distance = (time*1.87)/100; //CM (见代码最后注释)
if(flag==1) //超出测量
{
flag=0;
zhizou();
}
if(Distance<20){
zuozhuan1();//距离小于20,左旋转找到距离大于20的方向继续前进
}else{
zhizou();
// printf("Distance = %f CM\n",Distance);
}
}
void Timer0IRQ() interrupt 3 //T0中断用来计数器溢出,超过测距范围
{
flag=1;
}