/*
* 作者:赵新
* 功能:实现小车躲避障碍,通过检测三个方向的距离,选择最大距离转弯
* 日期:/3/14
* 说明:STC89c52RC,12MHz
* 注意:1000ms和100ms待测,完成后删除此行
*—————————————————管脚说明——————————————
* Trig = P1^0
* Echo = P3^2
* PWM_OUT = P0^4
*————————————————————————————————————————
*/
#include "stc89c5x.h"
#include "intrins.h"
#include "Motor.h"
#define X 20 //最短距离参考值 约为12厘米 受温度影响,会存在10%左右的误差
sbit Trig = P1^0;//发送端
sbit Echo = P3^2;//接收端 若用外部中断0,则此引脚必须是P3.2
sbit PWM_OUT = P0^4;//PWM信号输出端
u8 counts = 0; //设置初值
u8 PWM =6; //设置初值,任意值也可不设
u8 Flag_Angle = 1;//0 左45度 1 右45度 在函数Scan()中调用
u8 Distance_Middle;
u8 Distance_Temp[2];//0 左45度 1 右45度
void Delay20us();
void Delay100ms();
void Delay1000ms();//@12.000MHz用于等待
u8 Compute(u8 th,u8 tl);
void Scan_Around();//扫描左右
void Scan_Middle();//扫描正中前进方向距离
void main()
{
TMOD = 0x11;//设置T0,T1 T0用于电平检测 T1用于产生舵机需要的PWM信号
TH0 = 0x00;//转载初值
TL0 = 0x00;
ET0 = 1;//打开定时器中断
TF0 = 0;//失能定时器中断标志,也可忽略此语句
TR0 = 0;//开始时T0关闭
TH1 = 0xff;//产生时基100us定时,用于组成舵机各个角度的信号
TL1 = 0x9c;
ET1 = 1;
TF0 = 0; //可忽略此语句,51复位此位为0
TR1 = 0;//暂时关闭T1
EX0 = 1; //开外部中断
IT0 = 1; //下降沿触发中断
EA = 1;//全局中断开
Trig = 0;//触发端拉低
Echo = 0;
while(1)
{
//Scan_Around();
Scan_Middle();
if(Distance_Middle<=X)
{
Stop();
Scan_Around();
if((Distance_Temp[0]>Distance_Temp[1])&&Distance_Temp[0]>=X)
{
Turn_Left(0);
Delay100ms();
//Delay100ms();
}else
if((Distance_Temp[0]=X)
{
Turn_Right(0);
Delay100ms();
//Delay100ms();
}else
if((Distance_Temp[0]==Distance_Temp[1])&&Distance_Temp[0]>=X)
{
Turn_Right(0);
Delay100ms();
//Delay100ms();
}else
{
Back();
Delay100ms();
Delay100ms();
Delay100ms();
Delay100ms();
Delay100ms();
Turn_Right(0);
Delay100ms();
//Delay100ms();
}
}else
{
Go();
}
}
}
void Timer1(void) interrupt 3 //PWM产生
{
TH1 = 0xff;
TL1 = 0x9c;
if(counts
{
PWM_OUT = 1;
}
else
{
PWM_OUT = 0;
if(counts==200)
{
counts = 0;
}
}
++counts;
}
void Timer0(void) interrupt 1 //T0溢出中断函数,一般来说T0溢出是不可能发生的,原因是传感器最大探测距离为4m左右,所用时间不会超过65536us
{
}
void INT0_Test(void) interrupt 0//下降沿到来之后,进入外部中断函数,停止T0计数,计算并发送计算值到计算机
{
TR0 = 0;
switch(Flag_Angle)
{
case 0:Distance_Temp[0]=Compute(TH0,TL0);TH0 = TL0 = 0x00;break;//左
case 1:Distance_Temp[1]=Compute(TH0,TL0);TH0 = TL0 = 0x00;break;//右
default:break;
}
//为了下一次准确计数,必须清空
}
void Scan_Around() //扫描左右
{
Flag_Angle = 0;
PWM = 17;//左转45度
TR1 = 1;
Delay1000ms();
TR1 = 0;
Trig = 1; //触发一次检测
Delay20us();
Trig = 0;
while(!Echo); //如果没有检测到返回信号,等
TR0 = 1; //检测到高电平,开T0计数,一直计到下降沿到来
Delay100ms();
Flag_Angle = 1;
PWM = 8; //右转45度
TR1 = 1;
Delay1000ms();
TR1 = 0;
Trig = 1; //触发一次检测
Delay20us();
Trig = 0;
while(!Echo); //如果没有检测到返回信号,等
TR0 = 1; //检测到高电平,开T0计数,一直计到下降沿到来
Delay100ms();
PWM = 12; //测完回到正中
TR1 = 1;
Delay1000ms();
TR1 = 0;
}
void Scan_Middle() //扫描正中前进方向距离
{
//Stop();
Flag_Angle = 3;
Trig = 1; //触发一次检测
Delay20us();
Trig = 0;
while(!Echo); //如果没有检测到返回信号,等
TR0 = 1; //检测到高电平,开T0计数,一直计到下降沿到来
Delay100ms();
Distance_Middle = Compute(TH0,TL0);
TH0 = TL0 = 0x00;
//Go();
}
u8 Compute(u8 th,u8 tl)
{
u16 times = 0x0000;
times = th;
times = times<<8;
times |= tl;
return (times/58);
}
void Delay20us() //@12.000MHz用于产生超声波触发信号
{
unsigned char i;
_nop_();
i = 7;
while (--i);
}
void Delay100ms() //@12.000MHz
{
unsigned char i, j;
i = 195;
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………