#include<reg52.h>
#include<intrins.h>
#include<string.h>
#define uint unsigned int
#define uchar unsigned char
//停车
#define stop(); { IN31=0; IN32=0; IN33=0; IN34=0;}
//后退
#define back(); { IN31=0; IN32=1; IN33=0; IN34=1;}
//前进
#define go(); { IN31=1; IN32=0; IN33=1; IN34=0;}
//前进时左转
#define left_g(); { IN31=0; IN32=0; IN33=1; IN34=0;}
//前进时右转
#define right_g(); { IN31=1; IN32=0; IN33=0; IN34=0;}
//后退时左转
#define left_b(); { IN31=0; IN32=1; IN33=0; IN34=0;}
//后退时右转
#define right_b(); { IN31=0; IN32=0; IN33=0; IN34=1;}
//原地打转180
#define turn_round(); { IN31=1; IN32=0; IN33=0; IN34=1;}
sfr T2MOD=0xc9; //使用定时器2时必须
sbit IN31= P2^0;//直流电机输入端IN1
sbit IN32= P2^1;//直流电机输入端IN2
sbit IN33= P2^2;//直流电机输入端IN3
sbit IN34= P2^3;//直流电机输入端IN4
sbit EN12= P2^4;//直流电机输入端IN3
sbit EN34= P2^5;//直流电机输入端IN4
sbit rw=P3^1; //1602端口定义
sbit en=P3^0; //1602端口定义
sbit rs=P3^7; //1602端口定义
sbit Test_Black_tape=P3^3; //小车车轮检测黑带条纹数
sbit bing=P3^6; //蜂鸣器
sbit Test_left=P0^0; //黑线左检测端口定义
sbit Test_Middle_left=P0^1; //黑线中检测端口定义
sbit Test_Middle_right=P0^2; //黑线右检测端口定义
sbit Test_right=P0^3; //黑线右检测端口定义
uchar PWM12=47,PWM34=49;//PWM12控制EN12,PWM34控制EN34
uchar PWM_i=0;//调速脉冲进行计时
uchar Test_flag =0;//低四位表黑线情况,第四,三,二,一位表示左,左中,右中,右侧探测结果,1表示在黑线上
uchar detector=8; //4-左侧探测器,2-中间探测器,1-右侧探测器
uchar left_flag=0; //首先检测到黑线时被标记为1;
uchar right_flag=0; //首先检测到黑线时被标记为1;
uchar count=0; // 对黑条进行计数
uchar correction_flag=0;//方位矫正函数标志位,为1时可执行矫正函数
uchar Control_rotation_angle=0; //控制矫正函数转角大小
uchar Control_bing=0;//控制蜂鸣器位,为1时蜂鸣器按一定频率响
uchar bing_i=0;//控制蜂鸣器频率
uchar flag=1;//控制两边边ST188开关,flag为1时开
uint Timing=0;//控制两边边ST188开关,Timing(定时器中)等于300时(600ms),flag置为1
uint mstcnt=0;//定时器重时间计数,每1ms加1
uint time=0;//全程时间
uint Time_delay=0;//延时时间(2ms)
uchar Time_delay_flag=0;//启动延时计时的标志位,1时启动
uint Time_interval=0;//中间两个传感器检测的黑线相差的时间(ms)
uchar Time_interval_flag=0;//启动中间两个传感器检测的黑线相差的时间(ms)的标志位,1时启动
uchar Control_count=1; //为1时允许flag开始计时
uchar turn_round_flag=1; //转弯标志位
uint distance=0,Subsection_distance=0;//全程,每一段时间所行使的路程
uint cycle_number=0;// 记录小车车轮的圈数
uchar open_interrupt0=0;//当Close_interrupt=1时,外部中断1s后打开
uint interrupt0_i=0;//1s打开中断进行计时
uchar stop_flag=0; //终点起点停车标志位
uchar disbuf[4]={0}; //存放路程
uchar seconde[3]={0}; //存放时间
uchar number[2]={0}; //存放黑条数目
uchar code table1[]={"S: 0.0 m t: 0s"};
uchar code table2[]={" count:00" };
/***************延时子函数1us*******************/
void delay1us(uint us)
{
while(us--) ;
}
/***************延时子函数1ms*******************/
void delay1ms(uint ms)
{
uchar j;
while(ms--)
{
for(j=0;j<120;j++);
}
}
void write_com(uchar com)//1602写指令
{
rs=0;
P1=com;
delay1us(4);
en=1;
en=0;
}
void write_data(uchar data0)//1602写数据
{
rs=1;
P1=data0;
delay1us(4);
en=1;
en=0;
}
void display1( ) //显示时间路程程序
{
disbuf[0] = ((distance/1000)%10)+0x30; //路程(cm)千位
disbuf[1] = ((distance/100)%10)+0x30; //路程(cm)百位
disbuf[2] = ((distance/10)%10)+0x30; //路程(cm)十位
disbuf[3] = (distance%10)+0x30; //路程(cm)个位
seconde[0] = (time/100)+0x30; //时间百位
seconde[1] = ((time%100)/10)+0x30; //时间十位
seconde[2] = (time%10)+0x30; //时间个位
if(disbuf[0]==0x30)
{
disbuf[0]=0x20;//如果百位为0,不显示(显示空格)
}
if(seconde[0]==0x30)
{
seconde[0]=0x20;//如果百位为0,不显示(显示空格)
if(seconde[1]==0x30)
{
seconde[1]=0x20;//如果百位为0,十位为0也不显示(显示空格)
}
}
write_com(0x80+2); //显示路程十位
delay1us(2);
write_data(disbuf[0]);
delay1us(2);
write_com(0x80+3); //显示路程个位
delay1us(2);
write_data(disbuf[1]);
delay1us(2);
write_com(0x80+5); //显示路程十分位位
delay1us(2);
write_data(disbuf[2]);
delay1us(2);
write_com(0x80+6); //显示路程百分位
delay1us(2);
write_data(disbuf[3]);
delay1us(2);
write_com(0x80+12); //显示时间百位
delay1us(2);
write_data(seconde[0]);
delay1us(2);
write_com(0x80+13); //显示时间十位
delay1us(2);
write_data(seconde[1]);
delay1us(2);
write_com(0x80+14); //显示时间个位
delay1us(2);
write_data(seconde[2]);
delay1us(2);
}
void display2( ) //显示黑带函数
{
number[0] = (count/10)+0x30; //黑带数目十位
number[1] = (count%10)+0x30; //黑带数目个位
if(number[0]==0x30)
{
number[0]=0x20;//如果十位为0,不显示(显示空格)
}
write_com(0x80+0x40+10); //显示黑条数目十位
write_data(number[0]);
delay1us(2);
write_com(0x80+0x40+11); //显示黑条数目个位
delay1us(2);
write_data(number[1]);
}
/**************计算路程,并把结果放入lcd1602缓冲区**************/
void count_distance()
{
Subsection_distance=cycle_number*5;
distance=distance+Subsection_distance;
cycle_number=0;
}
/*************小车前进转弯函数*********************/
void search_back_small( ) //后退小步,缓冲作用
{
back();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_back( ) //后退
{
back();
Time_delay_flag=1;
while(Time_delay<200); //定时器2延时200x2=400ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_5( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<30); //定时器2延时30x2=60ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_10( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<70); //定时器2延时70x2=140ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_20( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<100); //定时器2延时100x2=200ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_30( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_40( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<170); //定时器2延时170x2=340ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_b( ) //后退实现右转
{
right_b();
Time_delay_flag=1;
while(Time_delay<105); //定时器2延时105x2=210ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_5( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<25); //定时器2延时25x2=50ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_10( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<45); //定时器2延时45x2=90ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_20( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<70); //定时器2延时70x2=140ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_30( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<90); //定时器2延时90x2=180ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_40( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_b( ) //后退实现左转
{
left_b();
Time_delay_flag=1;
while(Time_delay<115); //定时器2延时115x2=230ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void turn_round_180( )
{
turn_round();
Time_delay_flag=1;
while(Time_delay<580); //定时器2延时560x2=1160ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
/*************矫正小车方位函数*********************/
void rotation_angle( )
{
if((Time_interval>=0)&&(Time_interval<=2))
{Control_rotation_angle=0;} //不转角
if((Time_interval>2)&&(Time_interval<=10))
{Control_rotation_angle=1;} //转角5度
if((Time_interval>10)&&(Time_interval<=25))
{Control_rotation_angle=2;} //转角10度
if((Time_interval>25)&&(Time_interval<=40))
{Control_rotation_angle=3;} //转角15度
if((Time_interval>40)&&(Time_interval<=60))
{Control_rotation_angle=4;} //转角20度
if((Time_interval>60)&&(Time_interval<=90))
{Control_rotation_angle=5;} //转角25度
if((Time_interval>90)&&(Time_interval<=150))
{Control_rotation_angle=6;} //转角25度
if(left_flag==1) //左边先检测到黑线
{
switch(Control_rotation_angle)
{
case 1: search_left_g_5( );
break;
case 2: search_left_g_10( );
break;
case 3: search_left_g_20( );
break;
case 4: search_left_g_30( );
break;
case 5: search_left_g_40( );
break;
case 6: search_left_g_40( );
break;
default: break;
}
}
else if(right_flag==1)
{
switch(Control_rotation_angle)
{
case 1: search_right_g_5( );
break;
case 2: search_right_g_10( );
break;
case 3: search_right_g_20( );
break;
case 4: search_right_g_30( );
break;
case 5: search_right_g_40( );
break;
case 6: search_right_g_40( );
break;
default: break;
}
}
right_flag=0;
left_flag=0;
Time_interval_flag=0;
Time_interval=0;
}
/*************检测左中右三处黑线情况*********************/
void Testing ( )
{
Test_flag=0; //标志位清零
detector=8; //标志位清零
while(detector)
{
switch(detector)
{
case 8: if((Test_left==0)&&(flag==1))//左侧红外传感器检测黑线情况(flag为0时对应为始终为0)
{
Test_flag=Test_flag|detector;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 4: if(Test_Middle_left==0) //左侧红外传感器检测黑线情况
{
Test_flag= Test_flag|detector;
flag=0;Control_count=1;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 2: if(Test_Middle_right==0) //左侧红外传感器检测黑线情况
{
Test_flag=Test_flag|detector;
flag=0;Control_count=1;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 1: if((Test_right==0)&&(flag==1))//左侧红外传感器检测黑线情况(flag为0时对应为始终为0)
{
Test_flag=Test_flag|detector;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
default: break;
}
detector >>=1;
}
}
/*************根据检测到的黑线情况选择前进方式*********************/
void forward( )
{
switch(Test_flag)
{
case 0x00: go();
break;
case 0x01: search_back_small( ); //先后退小步
search_left_b( ); //后退实现左转
Control_bing=1; //蜂鸣器响一声
break;
case 0x02: Control_bing=1; //蜂鸣器响一声
if((left_flag==0)&&(right_flag==0))
{
right_flag=1;
Time_interval_flag=1;
}
break;
case 0x03: search_left_g_20( ); //后退实现左转
Control_bing=1; //蜂鸣器响一声
break;
case 0x04: Control_bing=1; //蜂鸣器响一声
if((left_flag==0)&&(right_flag==0))
{
left_flag=1;
Time_interval_flag=1;
}
break;
case 0x06: go();
break;
case 0x08: search_back_small( ); //先后退小步
search_right_b( ); //后退实现右转
Control_bing=1; //蜂鸣器响一声
break;
case 0x12: search_right_g_20( ); //后退实现右转
Control_bing=1; //蜂鸣器响一声
break;
default: search_back( ); //异常处理,后退
Control_bing=1; //蜂鸣器响一声
break;
}
}
/*************终点,起点停车函数*********************/
void start_end( )
{
uchar i=5;
if(count==6) //到达终点停留10s后原地打转180返回
{
display2( ); //显示黑带数目
stop();
while(i--)
{
bing=1;
delay1ms(200);
bing=0;
delay1ms(300);
}
delay1ms(6000);
search_back( );
search_back( );
delay1ms(500);
EX0=0; //关外部中断0
EX1=0;
turn_round_flag=0;
turn_round_180( );
EX0=1; //开外部中断0
EX1=1;
turn_round_flag=1;
delay1ms(200);
display2( ); //显示黑带数目
}
if(count==12) //返回到起点,关闭总中断,响铃三声报警
{
EA=0;
stop();
display2( ); //显示黑带数目
while(i--)
{
bing=1;
delay1ms(200);
bing=0;
delay1ms(300);
}
while(1);
}
}
/*************外部中断0,计算中间黑条的数目*********************/
void INT_0() interrupt 0
{
count++;
EX0=0;
if((count==6)||(count==12)) //起点,终点处理
{
start_end( );
}
if((count==3)||(count==9)) //减速行驶
{
PWM12=38;
PWM34=40;
}
else if((count==5)||(count==11)) //在距离终点0.5米时低速行驶至终点
{
PWM12=29;
PWM34=30;
}
else //正常速度
{
PWM12=47;
PWM34=49;
}
if(count>90)
{
count=0;
}
open_interrupt0=1;
display2( );//显示黑带数目
}
/*************外部中断1,计算车轮黑条数目*********************/
void INT_1() interrupt 2
{
delay1us(500);
if(Test_Black_tape==0)
{
cycle_number++;
IE1=0; //清除中断标志位
if(cycle_number==250)
{
cycle_number=0;
}
}
}
/*************定时计数器中断2,用于电机PWM调速,计时*********************/
void time_2() interrupt 5
{
TF2=0; //定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器不同
PWM_i++;
mstcnt++; //用于计算时间,每隔10ms加1
/*****以下为实时计时程序******/
if(mstcnt>=500)//对小车行驶的时间进行计时,mstcnt满20即为一秒
{
time++;//秒+1
mstcnt=0; //对计数单元的清零,重新开始计数
if(time==500)
{
time=0;
}
if(turn_round_flag==1)
{
count_distance(); //计算路程
display1( ); //显示时间路程程序
}
}
/*****中间先过黑线时,两边黑线检测关闭400ms程序******/
if(Control_count==1)
{
Timing++;
if(Timing>=200)
{
Timing=0;
flag=1;
Control_count=0;
}
}
/*****以下为蜂鸣器响铃控制程序******/
if(Control_bing==1)
{
bing_i++;
if(bing_i<200)
{
bing=1;
}
else
{
bing=0;
bing_i=0;
Control_bing=0;
}
}
/*****以下为中间两个传感器通过黑色胶带的时间差******/
if(Time_interval_flag==1)
{
Time_interval++;
if(right_flag==1) //此时右边传感器先接触黑线
{
if(Test_Middle_left==0)
{
Time_interval_flag=0;
correction_flag=1; //方位矫正标志位,为1时可执行矫正函数
}
}
if(left_flag==1) //此时左边传感器先接触黑线
{
if(Test_Middle_right==0)
{
Time_interval_flag=0;
correction_flag=1; //方位矫正标志位,为1时可执行矫正函数
}
}
if(Time_interval>=200)
{
Time_interval_flag=0;
correction_flag=1;
Time_interval=0;
}
}
/*****以下用于延时******/
if(Time_delay_flag==1)
{
Time_delay++;
if(Time_delay>=2000)
{
Time_delay_flag=0;
Time_delay=0;
}
}
/*****定时1S打开外部中断0,防止抖动,黑条连续计数******/
if(open_interrupt0==1)
{
interrupt0_i++;
if(interrupt0_i>=500)
{
open_interrupt0=0;
EX0=1;
IE0=0; //清除中断标志位
interrupt0_i=0;
}
}
/*****以下为PWM调速程序******/
if(PWM_i<=PWM12) //控制EN12
{
EN12=1;
}
else
{
EN12=0;
}
if(PWM_i<=PWM34) //控制EN34
{
EN34=1;
}
else
{
EN34=0;
}
if(PWM_i>=50)
{
PWM_i=0;
}
}
/*************初始化函数*********************/
void int_int (void)
{
uchar i;
bing=0; //蜂鸣器初始化
rw=0;
write_com(0x38);//设置显示模式
delay1ms(2);
write_com(0x0c);
delay1ms(2);
write_com(0x06);
delay1ms(2);
write_com(0x01); //清零
delay1ms(2);
for(i=0;i<sizeof(table1)-1;i++)
{
write_data(table1[i]);
delay1ms(1);
}
write_com(0x80+0x40);
delay1ms(1);
for(i=0;i<sizeof(table2)-1;i++)
{
write_data(table2[i]);
delay1ms(1);
}
TMOD=0x55;//确定时器工作方式
IE0=0; //清除中断标志位
IE1=0; //清除中断标志位
RCAP2H=0xf8;
RCAP2L=0x30; //定时器2自动重装
T2CON=0x00;
T2MOD=0x00;
ET2=1; // 允许定时器2中断
TR2=1; //开启定时器2
EX0=1; //开外部中断0;
IT0=1; //外部中断0负跳变触发
EX1=1; //开外部中断0;
IT1=1; //外部中断0负跳变触发
IP=0x20; //设置中断优先级(外部中断0,定时中断2为高优先级)
EA=1; //开总中断
}
/*************主函数*********************/
void main()
{
delay1ms(500);//按下电源给小车0.5S的缓冲时间
int_int( ); //系统初始化
while(1) //进入总循环
{
Testing ( ); //检测黑线情况
forward( ); //根据检测的黑线情况选择前进方式
if((correction_flag==1)&&(count!=7)) //执行矫正程序
{
rotation_angle( );
correction_flag=0;
}
}
}
#include<intrins.h>
#include<string.h>
#define uint unsigned int
#define uchar unsigned char
//停车
#define stop(); { IN31=0; IN32=0; IN33=0; IN34=0;}
//后退
#define back(); { IN31=0; IN32=1; IN33=0; IN34=1;}
//前进
#define go(); { IN31=1; IN32=0; IN33=1; IN34=0;}
//前进时左转
#define left_g(); { IN31=0; IN32=0; IN33=1; IN34=0;}
//前进时右转
#define right_g(); { IN31=1; IN32=0; IN33=0; IN34=0;}
//后退时左转
#define left_b(); { IN31=0; IN32=1; IN33=0; IN34=0;}
//后退时右转
#define right_b(); { IN31=0; IN32=0; IN33=0; IN34=1;}
//原地打转180
#define turn_round(); { IN31=1; IN32=0; IN33=0; IN34=1;}
sfr T2MOD=0xc9; //使用定时器2时必须
sbit IN31= P2^0;//直流电机输入端IN1
sbit IN32= P2^1;//直流电机输入端IN2
sbit IN33= P2^2;//直流电机输入端IN3
sbit IN34= P2^3;//直流电机输入端IN4
sbit EN12= P2^4;//直流电机输入端IN3
sbit EN34= P2^5;//直流电机输入端IN4
sbit rw=P3^1; //1602端口定义
sbit en=P3^0; //1602端口定义
sbit rs=P3^7; //1602端口定义
sbit Test_Black_tape=P3^3; //小车车轮检测黑带条纹数
sbit bing=P3^6; //蜂鸣器
sbit Test_left=P0^0; //黑线左检测端口定义
sbit Test_Middle_left=P0^1; //黑线中检测端口定义
sbit Test_Middle_right=P0^2; //黑线右检测端口定义
sbit Test_right=P0^3; //黑线右检测端口定义
uchar PWM12=47,PWM34=49;//PWM12控制EN12,PWM34控制EN34
uchar PWM_i=0;//调速脉冲进行计时
uchar Test_flag =0;//低四位表黑线情况,第四,三,二,一位表示左,左中,右中,右侧探测结果,1表示在黑线上
uchar detector=8; //4-左侧探测器,2-中间探测器,1-右侧探测器
uchar left_flag=0; //首先检测到黑线时被标记为1;
uchar right_flag=0; //首先检测到黑线时被标记为1;
uchar count=0; // 对黑条进行计数
uchar correction_flag=0;//方位矫正函数标志位,为1时可执行矫正函数
uchar Control_rotation_angle=0; //控制矫正函数转角大小
uchar Control_bing=0;//控制蜂鸣器位,为1时蜂鸣器按一定频率响
uchar bing_i=0;//控制蜂鸣器频率
uchar flag=1;//控制两边边ST188开关,flag为1时开
uint Timing=0;//控制两边边ST188开关,Timing(定时器中)等于300时(600ms),flag置为1
uint mstcnt=0;//定时器重时间计数,每1ms加1
uint time=0;//全程时间
uint Time_delay=0;//延时时间(2ms)
uchar Time_delay_flag=0;//启动延时计时的标志位,1时启动
uint Time_interval=0;//中间两个传感器检测的黑线相差的时间(ms)
uchar Time_interval_flag=0;//启动中间两个传感器检测的黑线相差的时间(ms)的标志位,1时启动
uchar Control_count=1; //为1时允许flag开始计时
uchar turn_round_flag=1; //转弯标志位
uint distance=0,Subsection_distance=0;//全程,每一段时间所行使的路程
uint cycle_number=0;// 记录小车车轮的圈数
uchar open_interrupt0=0;//当Close_interrupt=1时,外部中断1s后打开
uint interrupt0_i=0;//1s打开中断进行计时
uchar stop_flag=0; //终点起点停车标志位
uchar disbuf[4]={0}; //存放路程
uchar seconde[3]={0}; //存放时间
uchar number[2]={0}; //存放黑条数目
uchar code table1[]={"S: 0.0 m t: 0s"};
uchar code table2[]={" count:00" };
/***************延时子函数1us*******************/
void delay1us(uint us)
{
while(us--) ;
}
/***************延时子函数1ms*******************/
void delay1ms(uint ms)
{
uchar j;
while(ms--)
{
for(j=0;j<120;j++);
}
}
void write_com(uchar com)//1602写指令
{
rs=0;
P1=com;
delay1us(4);
en=1;
en=0;
}
void write_data(uchar data0)//1602写数据
{
rs=1;
P1=data0;
delay1us(4);
en=1;
en=0;
}
void display1( ) //显示时间路程程序
{
disbuf[0] = ((distance/1000)%10)+0x30; //路程(cm)千位
disbuf[1] = ((distance/100)%10)+0x30; //路程(cm)百位
disbuf[2] = ((distance/10)%10)+0x30; //路程(cm)十位
disbuf[3] = (distance%10)+0x30; //路程(cm)个位
seconde[0] = (time/100)+0x30; //时间百位
seconde[1] = ((time%100)/10)+0x30; //时间十位
seconde[2] = (time%10)+0x30; //时间个位
if(disbuf[0]==0x30)
{
disbuf[0]=0x20;//如果百位为0,不显示(显示空格)
}
if(seconde[0]==0x30)
{
seconde[0]=0x20;//如果百位为0,不显示(显示空格)
if(seconde[1]==0x30)
{
seconde[1]=0x20;//如果百位为0,十位为0也不显示(显示空格)
}
}
write_com(0x80+2); //显示路程十位
delay1us(2);
write_data(disbuf[0]);
delay1us(2);
write_com(0x80+3); //显示路程个位
delay1us(2);
write_data(disbuf[1]);
delay1us(2);
write_com(0x80+5); //显示路程十分位位
delay1us(2);
write_data(disbuf[2]);
delay1us(2);
write_com(0x80+6); //显示路程百分位
delay1us(2);
write_data(disbuf[3]);
delay1us(2);
write_com(0x80+12); //显示时间百位
delay1us(2);
write_data(seconde[0]);
delay1us(2);
write_com(0x80+13); //显示时间十位
delay1us(2);
write_data(seconde[1]);
delay1us(2);
write_com(0x80+14); //显示时间个位
delay1us(2);
write_data(seconde[2]);
delay1us(2);
}
void display2( ) //显示黑带函数
{
number[0] = (count/10)+0x30; //黑带数目十位
number[1] = (count%10)+0x30; //黑带数目个位
if(number[0]==0x30)
{
number[0]=0x20;//如果十位为0,不显示(显示空格)
}
write_com(0x80+0x40+10); //显示黑条数目十位
write_data(number[0]);
delay1us(2);
write_com(0x80+0x40+11); //显示黑条数目个位
delay1us(2);
write_data(number[1]);
}
/**************计算路程,并把结果放入lcd1602缓冲区**************/
void count_distance()
{
Subsection_distance=cycle_number*5;
distance=distance+Subsection_distance;
cycle_number=0;
}
/*************小车前进转弯函数*********************/
void search_back_small( ) //后退小步,缓冲作用
{
back();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_back( ) //后退
{
back();
Time_delay_flag=1;
while(Time_delay<200); //定时器2延时200x2=400ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_5( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<30); //定时器2延时30x2=60ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_10( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<70); //定时器2延时70x2=140ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_20( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<100); //定时器2延时100x2=200ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_30( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_g_40( ) //前进实现右转
{
right_g();
Time_delay_flag=1;
while(Time_delay<170); //定时器2延时170x2=340ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_right_b( ) //后退实现右转
{
right_b();
Time_delay_flag=1;
while(Time_delay<105); //定时器2延时105x2=210ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_5( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<25); //定时器2延时25x2=50ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_10( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<45); //定时器2延时45x2=90ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_20( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<70); //定时器2延时70x2=140ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_30( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<90); //定时器2延时90x2=180ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_g_40( ) //前进实现左转
{
left_g();
Time_delay_flag=1;
while(Time_delay<130); //定时器2延时130x2=260ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void search_left_b( ) //后退实现左转
{
left_b();
Time_delay_flag=1;
while(Time_delay<115); //定时器2延时115x2=230ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
void turn_round_180( )
{
turn_round();
Time_delay_flag=1;
while(Time_delay<580); //定时器2延时560x2=1160ms
Time_delay_flag=0;
Time_delay=0;
stop();
}
/*************矫正小车方位函数*********************/
void rotation_angle( )
{
if((Time_interval>=0)&&(Time_interval<=2))
{Control_rotation_angle=0;} //不转角
if((Time_interval>2)&&(Time_interval<=10))
{Control_rotation_angle=1;} //转角5度
if((Time_interval>10)&&(Time_interval<=25))
{Control_rotation_angle=2;} //转角10度
if((Time_interval>25)&&(Time_interval<=40))
{Control_rotation_angle=3;} //转角15度
if((Time_interval>40)&&(Time_interval<=60))
{Control_rotation_angle=4;} //转角20度
if((Time_interval>60)&&(Time_interval<=90))
{Control_rotation_angle=5;} //转角25度
if((Time_interval>90)&&(Time_interval<=150))
{Control_rotation_angle=6;} //转角25度
if(left_flag==1) //左边先检测到黑线
{
switch(Control_rotation_angle)
{
case 1: search_left_g_5( );
break;
case 2: search_left_g_10( );
break;
case 3: search_left_g_20( );
break;
case 4: search_left_g_30( );
break;
case 5: search_left_g_40( );
break;
case 6: search_left_g_40( );
break;
default: break;
}
}
else if(right_flag==1)
{
switch(Control_rotation_angle)
{
case 1: search_right_g_5( );
break;
case 2: search_right_g_10( );
break;
case 3: search_right_g_20( );
break;
case 4: search_right_g_30( );
break;
case 5: search_right_g_40( );
break;
case 6: search_right_g_40( );
break;
default: break;
}
}
right_flag=0;
left_flag=0;
Time_interval_flag=0;
Time_interval=0;
}
/*************检测左中右三处黑线情况*********************/
void Testing ( )
{
Test_flag=0; //标志位清零
detector=8; //标志位清零
while(detector)
{
switch(detector)
{
case 8: if((Test_left==0)&&(flag==1))//左侧红外传感器检测黑线情况(flag为0时对应为始终为0)
{
Test_flag=Test_flag|detector;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 4: if(Test_Middle_left==0) //左侧红外传感器检测黑线情况
{
Test_flag= Test_flag|detector;
flag=0;Control_count=1;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 2: if(Test_Middle_right==0) //左侧红外传感器检测黑线情况
{
Test_flag=Test_flag|detector;
flag=0;Control_count=1;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
case 1: if((Test_right==0)&&(flag==1))//左侧红外传感器检测黑线情况(flag为0时对应为始终为0)
{
Test_flag=Test_flag|detector;
}//将Test_flag对应的标志为1,1表示检测到黑线}
break;
default: break;
}
detector >>=1;
}
}
/*************根据检测到的黑线情况选择前进方式*********************/
void forward( )
{
switch(Test_flag)
{
case 0x00: go();
break;
case 0x01: search_back_small( ); //先后退小步
search_left_b( ); //后退实现左转
Control_bing=1; //蜂鸣器响一声
break;
case 0x02: Control_bing=1; //蜂鸣器响一声
if((left_flag==0)&&(right_flag==0))
{
right_flag=1;
Time_interval_flag=1;
}
break;
case 0x03: search_left_g_20( ); //后退实现左转
Control_bing=1; //蜂鸣器响一声
break;
case 0x04: Control_bing=1; //蜂鸣器响一声
if((left_flag==0)&&(right_flag==0))
{
left_flag=1;
Time_interval_flag=1;
}
break;
case 0x06: go();
break;
case 0x08: search_back_small( ); //先后退小步
search_right_b( ); //后退实现右转
Control_bing=1; //蜂鸣器响一声
break;
case 0x12: search_right_g_20( ); //后退实现右转
Control_bing=1; //蜂鸣器响一声
break;
default: search_back( ); //异常处理,后退
Control_bing=1; //蜂鸣器响一声
break;
}
}
/*************终点,起点停车函数*********************/
void start_end( )
{
uchar i=5;
if(count==6) //到达终点停留10s后原地打转180返回
{
display2( ); //显示黑带数目
stop();
while(i--)
{
bing=1;
delay1ms(200);
bing=0;
delay1ms(300);
}
delay1ms(6000);
search_back( );
search_back( );
delay1ms(500);
EX0=0; //关外部中断0
EX1=0;
turn_round_flag=0;
turn_round_180( );
EX0=1; //开外部中断0
EX1=1;
turn_round_flag=1;
delay1ms(200);
display2( ); //显示黑带数目
}
if(count==12) //返回到起点,关闭总中断,响铃三声报警
{
EA=0;
stop();
display2( ); //显示黑带数目
while(i--)
{
bing=1;
delay1ms(200);
bing=0;
delay1ms(300);
}
while(1);
}
}
/*************外部中断0,计算中间黑条的数目*********************/
void INT_0() interrupt 0
{
count++;
EX0=0;
if((count==6)||(count==12)) //起点,终点处理
{
start_end( );
}
if((count==3)||(count==9)) //减速行驶
{
PWM12=38;
PWM34=40;
}
else if((count==5)||(count==11)) //在距离终点0.5米时低速行驶至终点
{
PWM12=29;
PWM34=30;
}
else //正常速度
{
PWM12=47;
PWM34=49;
}
if(count>90)
{
count=0;
}
open_interrupt0=1;
display2( );//显示黑带数目
}
/*************外部中断1,计算车轮黑条数目*********************/
void INT_1() interrupt 2
{
delay1us(500);
if(Test_Black_tape==0)
{
cycle_number++;
IE1=0; //清除中断标志位
if(cycle_number==250)
{
cycle_number=0;
}
}
}
/*************定时计数器中断2,用于电机PWM调速,计时*********************/
void time_2() interrupt 5
{
TF2=0; //定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器不同
PWM_i++;
mstcnt++; //用于计算时间,每隔10ms加1
/*****以下为实时计时程序******/
if(mstcnt>=500)//对小车行驶的时间进行计时,mstcnt满20即为一秒
{
time++;//秒+1
mstcnt=0; //对计数单元的清零,重新开始计数
if(time==500)
{
time=0;
}
if(turn_round_flag==1)
{
count_distance(); //计算路程
display1( ); //显示时间路程程序
}
}
/*****中间先过黑线时,两边黑线检测关闭400ms程序******/
if(Control_count==1)
{
Timing++;
if(Timing>=200)
{
Timing=0;
flag=1;
Control_count=0;
}
}
/*****以下为蜂鸣器响铃控制程序******/
if(Control_bing==1)
{
bing_i++;
if(bing_i<200)
{
bing=1;
}
else
{
bing=0;
bing_i=0;
Control_bing=0;
}
}
/*****以下为中间两个传感器通过黑色胶带的时间差******/
if(Time_interval_flag==1)
{
Time_interval++;
if(right_flag==1) //此时右边传感器先接触黑线
{
if(Test_Middle_left==0)
{
Time_interval_flag=0;
correction_flag=1; //方位矫正标志位,为1时可执行矫正函数
}
}
if(left_flag==1) //此时左边传感器先接触黑线
{
if(Test_Middle_right==0)
{
Time_interval_flag=0;
correction_flag=1; //方位矫正标志位,为1时可执行矫正函数
}
}
if(Time_interval>=200)
{
Time_interval_flag=0;
correction_flag=1;
Time_interval=0;
}
}
/*****以下用于延时******/
if(Time_delay_flag==1)
{
Time_delay++;
if(Time_delay>=2000)
{
Time_delay_flag=0;
Time_delay=0;
}
}
/*****定时1S打开外部中断0,防止抖动,黑条连续计数******/
if(open_interrupt0==1)
{
interrupt0_i++;
if(interrupt0_i>=500)
{
open_interrupt0=0;
EX0=1;
IE0=0; //清除中断标志位
interrupt0_i=0;
}
}
/*****以下为PWM调速程序******/
if(PWM_i<=PWM12) //控制EN12
{
EN12=1;
}
else
{
EN12=0;
}
if(PWM_i<=PWM34) //控制EN34
{
EN34=1;
}
else
{
EN34=0;
}
if(PWM_i>=50)
{
PWM_i=0;
}
}
/*************初始化函数*********************/
void int_int (void)
{
uchar i;
bing=0; //蜂鸣器初始化
rw=0;
write_com(0x38);//设置显示模式
delay1ms(2);
write_com(0x0c);
delay1ms(2);
write_com(0x06);
delay1ms(2);
write_com(0x01); //清零
delay1ms(2);
for(i=0;i<sizeof(table1)-1;i++)
{
write_data(table1[i]);
delay1ms(1);
}
write_com(0x80+0x40);
delay1ms(1);
for(i=0;i<sizeof(table2)-1;i++)
{
write_data(table2[i]);
delay1ms(1);
}
TMOD=0x55;//确定时器工作方式
IE0=0; //清除中断标志位
IE1=0; //清除中断标志位
RCAP2H=0xf8;
RCAP2L=0x30; //定时器2自动重装
T2CON=0x00;
T2MOD=0x00;
ET2=1; // 允许定时器2中断
TR2=1; //开启定时器2
EX0=1; //开外部中断0;
IT0=1; //外部中断0负跳变触发
EX1=1; //开外部中断0;
IT1=1; //外部中断0负跳变触发
IP=0x20; //设置中断优先级(外部中断0,定时中断2为高优先级)
EA=1; //开总中断
}
/*************主函数*********************/
void main()
{
delay1ms(500);//按下电源给小车0.5S的缓冲时间
int_int( ); //系统初始化
while(1) //进入总循环
{
Testing ( ); //检测黑线情况
forward( ); //根据检测的黑线情况选择前进方式
if((correction_flag==1)&&(count!=7)) //执行矫正程序
{
rotation_angle( );
correction_flag=0;
}
}
}