#include <reg52.h>
#include " LCD1602.h "
sbit zuo = P1^0;
sbit you = P1^1;
sbit zhong = P1^2;
sbit IN1 = P2^1; //P2.0到P2.3是电机驱动输出控制端
sbit IN2 = P2^2;
sbit IN3 = P2^3;
sbit IN4 = P2^4;
sbit Trig = P2^0; //产生脉冲引脚
sbit Echo = P3^3; //回波引脚
uint distance[4]; //测距接收缓冲区
unsigned char code ASCII[16] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};
unsigned char disbuff[4]= { 0,0,0,0,};
uint distance1;
bit succeed_flag; //测量成功标志
void chaoshengbo();
void delay_20us();
void delay_ms(uint x);
void delay(uint t);
void Tracking();
void shunback();
//延时程序1
void delay(uint t)
{
uchar j;
while(t--)
{for(j=5;j>0;j--);}
}
//微妙延时程序
void delay_us(uint x)
{
do {
x--;
}
while(x>1);
}
//毫秒延时
void delay_ms(uint x)
{
while(x!=0)
{
delay_us(500);
x--;
}
}
//20微妙延时
void delay_20us()
{
uchar bt ;
for(bt=0;bt<100;bt++);
}
void Init()
{
Trig=0;
TMOD = 0x11; //T/C1采用16位定时器/计数器
ET1 = 1; //定时器1开中断
ET0 = 1;
TH0 = 0x00;
TL0 = 0x00;
TH1 = 0xff;
TL1 = 0xce;
TR1=1;
TR0 = 1; //定时计数器启动计数
EX0 = 1; //外部中断0关中断
PT1 = 1;
EA = 1; //CPU开中断
}
//超声波测距
void chaoshengbo()
{
uint distance_data,S;
Trig=1;
delay_20us();
Trig=0; //产生一个20us的脉冲,在Trig引脚
while(!Echo); //等待Echo回波引脚变高电平
TR0=1; //启动定时器1
while(Echo);
TR0=0;
delay_ms(7);
distance_data=TH0*256+TL0;
TH0=0;
TL0=0;
S=(distance_data*1.7)/100;
if(succeed_flag==1)
{
distance1=S;
}
disbuff[0]=((S/100)%10);
disbuff[1]=((S/10)%10);
disbuff[2]=(S%10);
DisplayOneChar(9, 0, ASCII[disbuff[0]]);
DisplayOneChar(10, 0, ASCII[10]); //显示点
DisplayOneChar(11, 0, ASCII[disbuff[1]]);
DisplayOneChar(12, 0, ASCII[disbuff[2]]);
DisplayOneChar(13, 0, ASCII[12]); //显示M
}
//左转
void comeleft()
{
IN1=0;
IN2=1;
IN3=1;
IN4=1;
}
//右转
void comeright ()
{
IN1=1;
IN2=1;
IN3=1;
IN4=0;
}
//前进加速;
void comeon()
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
}
void stop()
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
void backward()
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
//红外寻迹
void Tracking()
{
if(zuo==1&&zhong==1&&you==1) //0是接受到黑线,1是白线
{
comeon();
}
else if(zuo==1&&zhong==0&&you==1)
{
comeon();
}
else if(zuo==0&&zhong==1&&you==1)
{
comeleft();
}
else if(zuo==0&&zhong==0&&you==1)
{
comeleft();
}
else if(zuo==1&&zhong==1&&you==0)
{
comeright();
}
else if(zuo==1&&zhong==0&&you==0)
{
comeright();
}
else
{
stop();
}
}
//避障
void shunback()
{
chaoshengbo();
delay_ms(50);
Tracking();// 避障运行
if(distance1<8) //当超声波测距距离小于8则
{
stop(); //小车停止运动
delay_ms(50);
// backward();
// delay_ms(100);
// comeleft();
// delay_ms(60);
TR1=1;
delay_ms(50);
TR1=0;
}
else
{
Tracking();
} //否则小车直走
}
//主函数
void main(void)
{
Init(); //初始化
LCMInit(); //LCM初始化
TMOD=0x01;
TH0=0; //定时器1清零
TL0=0; //定时器1清零
ET0=1; //打开外部中断
EA=1;
succeed_flag=0; //清测量成功标志
while(1)
{
displayfun();
chaoshengbo();
shunback(); //循环调用超声波测距
Tracking();
}
}
//外部中断0,用做判断回波电平
INTO_() interrupt 0 // 外部中断是0号
{
succeed_flag=1; //至成功测量的标志
}
#ifndef __lcd1602__
#define __lcd1602__
//定义引脚
sbit LCM_RS = P2^6;
sbit LCM_RW = P2^5;
sbit LCM_E = P2^7;
//数据口定义
#define LCM_Data P0
sbit BF=LCM_Data^7; //忙信号线
//数组变量
unsigned char code yuyiny[18]={
0x00,0x10,0x18,0x20,0x28,0x30,0x38,0x40,
0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x98};
unsigned char inittime[7]={0x00,0x00,0x12,0x03,0x04,0x06,0x10}; //初始化时间
//变量
#define uchar unsigned char
#define uint unsigned int
/********************************************************************
函 数 名:unsigned char ReadStatusLCM(void)
功 能:忙检测
说 明:
入口参数:无
返 回 值:无
***********************************************************************/
unsigned char ReadStatusLCM(void)
{
bit busy =0;
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 1;
LCM_E = 1;
busy = BF;
LCM_E = 0;
return(busy);
}
/********************************************************************
函 数 名:void WriteCommandLCM(unsigned char WCLCM,BuysC)
功 能:写命令
说 明:
入口参数:WCLCM
BuysC 需要忙检测
返 回 值:无
***********************************************************************/
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
while (ReadStatusLCM());
LCM_RS = 0;
LCM_RW = 0;
LCM_Data = WCLCM;
LCM_E = 1;
LCM_E = 0;
}
/********************************************************************
函 数 名:void WriteDataLCM(unsigned char WDLCM
功 能:写数据
说 明:
入口参数:WDLCM
返 回 值:无
***********************************************************************/
void WriteDataLCM(unsigned char WDLCM)
{
while(ReadStatusLCM()); //检测忙
LCM_RS = 1;
LCM_RW = 0;
LCM_Data = WDLCM;
LCM_E = 1;
LCM_E = 0;
}
/********************************************************************
函 数 名:void LCMInit(void)
功 能:LCM初始化
说 明:
入口参数:无
返 回 值:无
***********************************************************************/
void LCMInit(void)
{
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x0C,1); //显示开及光标设置
WriteCommandLCM(0x06,1); //显示光标移动设置
WriteCommandLCM(0x01,1); //显示清屏
}
/********************************************************************
函 数 名:void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
功 能:按指定位置显示一个字符
说 明:
入口参数:X 一行显示个数限制
Y 上下行限制
DData 数据
返 回 值:无
***********************************************************************/
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码 0x40;
X |= 0x80; // 算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}
/********************************************************************
函 数 名:void displayfun(void)
功 能:界面显示
说 明:
入口参数:无
返 回 值:无
***********************************************************************/
void displayfun(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
/*显示 闹钟 设置*/
DisplayOneChar(0,0,'D');
DisplayOneChar(1,0,'i');
DisplayOneChar(2,0,'s');
DisplayOneChar(3,0,'t');
DisplayOneChar(4,0,'a');
DisplayOneChar(5,0,'n');
DisplayOneChar(6,0,'c');
DisplayOneChar(7,0,'e');
DisplayOneChar(8,0,':');
}
#endif
|